c - 在子进程中调用 dup2 导致父的标准输入关闭
问题描述
我正在尝试用 C 编写一个自定义 shell,它支持使用fork
和dup2
的多个管道pipe
。我的方法是c1 | c2 | c3
,创建一个 2 x 2 矩阵来存储两个管道,按顺序分叉三个子进程,调用dup2
复制stdin
和stdout
正确的管道,然后调用exec
。
shell 适用于以下命令:"echo foo"
, "ls | grep something | wc"
. 但是由于某种原因,当我执行仅包含一个管道的行时,例如"ls | grep something"
,shell 会按预期执行此命令,但无需等待读取更多行就退出。我花了几个小时试图弄清楚为什么它存在于一条带有一根管子的管线上,但它可以在多个管子上正常工作,但没有运气。
以下是创建子进程并运行命令的代码:
int main()
{
char input_line[1000];
size_t size;
size_t chars;
while(fgets(input_line, sizeof(input_line), stdin))
{
input_line[strcspn(input_line, "\n")] = 0;
struct PARSE_INFO* parse_info = initialize_parseInfo();
Parse(input_line, parse_info);
int num_commands = parse_info->num_commands;
int num_pipes = parse_info->num_pipes;
int pipes[num_pipes][2];
bool piping = num_pipes > 0;
// Piping the pipes
for(int i = 0; i < num_pipes; i++)
pipe(pipes[i]);
int i;
for(i = 0; i < num_commands; i++)
{
struct COMMAND* command = (parse_info->commands)[i];
int num_args = command->argnum;
char* newargv[num_args + 2];
create_argv(command, newargv, "/usr/bin");
int pid = fork();
if(pid == 0) // Child
{
char* newenviron[] = { NULL };
if(piping)
{
if(i < num_commands - 1) // Not at end of pipe so write to next pipe
{
dup2(pipes[i][1], STDOUT_FILENO);
}
if(i > 0) // Not at beginning of pipe so read from previous pipe
{
dup2(pipes[i - 1][0], STDIN_FILENO);
close(pipes[i -1][0]);
}
}
execve(newargv[0], newargv, newenviron);
perror("execve");
}
else // Parent
{
int status = 0;
wait(&status);
close(pipes[i][1]);
}
}
}
}
我独立测试了这里调用的函数,它们似乎工作正常,所以我选择不包含它们以减少混乱。我怀疑我没有正确关闭管道。令我困惑的是,如果我理解正确,调用dup2
子进程应该只修改该进程中的文件描述符而不影响父进程,我不确定它为什么会导致stdin
父进程关闭。
在调试过程中,我尝试stdin
通过在 else 块之后添加以下代码来读取 while 循环末尾的一些输入:
char someinput[256];
fgets(someinput, sizeof(someinput), stdin);
printf("End of loop input: %s\n");
该程序仍然终止并且没有等待读取任何输入。我尝试打印 someinput,它包含在循环开始时使用 from first call to fgets 从 stdin 输入的命令。任何帮助将非常感激!
解决方案
推荐阅读
- node.js - 在使用 Mocha 测试之前清除集合
- spring-integration - 批处理作业失败后如何停止或暂停轮询?
- git - .gitignore 无法正常工作
- android - 从从 MySQL 获取数据的微调器获取文本
- spring - 使用 Vue.js 将 Spring Boot 部署到 Heroku 构建成功,但无法启动
- r - x轴上带有日期字符串的ggplot错误
- c - 使用蒙特卡罗模拟多线程计算 Pi
- android - 颤振正在更新而不使用 setState
- linux - vim搜索并用不同的字符串替换连续出现的字符串
- java - 从其他类访问方法到 Activity