Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 在子进程中调用dup2导致父进程';s stdin即将关闭_C_File_Pipe_Fork_Stdin - Fatal编程技术网

C 在子进程中调用dup2导致父进程';s stdin即将关闭

C 在子进程中调用dup2导致父进程';s stdin即将关闭,c,file,pipe,fork,stdin,C,File,Pipe,Fork,Stdin,我正在尝试用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会按预期执行此命令,但

我正在尝试用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]);
            }
        }
    }
}

程序仍然终止,没有等待读取任何输入。我尝试打印一些输入,它包含循环开始时使用from first调用fgets从stdin输入的命令。任何帮助都将不胜感激

这件事没有“应该”的意思。一个进程无法关闭另一个进程的文件,无论进程或文件之间的关系如何。另一方面,至少当您关心函数调用是否成功时,您应该检查函数调用的返回值。此外,由于父进程提前创建了所有管道,每个孩子都需要关闭每个管道的写入端,除了它将要使用的一个(如果有的话)。就其本身而言,父级需要在等待从该管道读取的子级之前关闭每个写入端。总的来说,我认为如果将该问题简化为一个真正的问题,那么回答这个问题会容易得多。在fork/exec循环的每个迭代中只创建一个管道可能比提前创建它们要好得多。
char someinput[256];
fgets(someinput, sizeof(someinput), stdin);
printf("End of loop input: %s\n");