C 为什么我的烟斗不互相说话?

C 为什么我的烟斗不互相说话?,c,pipe,C,Pipe,我正在尝试用c编写一个简单的shell。现在我正在试着让管道工作。我有一个结构c,我正在将它输入到这个函数中,它包含一个存储管道文件描述符pipfd的位置,还包含关于每个命令c->type的结束标记的信息(可以是| | |&&&&etc)CommandPrev正在跟踪最后一个命令,以便查看之前的命令是否有管道标记 完成此函数后,我将子pid(返回值)指定给waitpid,以等待使用execvp调用的命令 当我运行诸如echo foo | echo bar之类的命令时,我得到的bar输出完全符合我

我正在尝试用c编写一个简单的shell。现在我正在试着让管道工作。我有一个结构
c
,我正在将它输入到这个函数中,它包含一个存储管道文件描述符
pipfd
的位置,还包含关于每个命令
c->type
的结束标记的信息(可以是| | |&&&&etc)
CommandPrev
正在跟踪最后一个命令,以便查看之前的命令是否有管道标记

完成此函数后,我将子pid(返回值)指定给
waitpid
,以等待使用
execvp
调用的命令

当我运行诸如
echo foo | echo bar
之类的命令时,我得到的
bar
输出完全符合我的预期,一切都很好。我的问题是,当我试图运行任何实际使用管道前半部分输入的命令时,所有内容都会被卡住。如果我运行类似于echo foo | wc-c的东西,我将不会得到任何输出,它将永远挂起

我可以看到这类命令的函数完成了,因为它返回时我会打印。发生的事情是,我用execvp调用的命令永远不会发生,所以我的waitpid会永远等待

我想我的管道两端的连接不知怎么断了。要么事情永远不会被书写,要么它们永远不会被阅读,要么管道的接收端永远不会意识到书写端已经完成,只是永远在等待。我立即关闭所有的管道,所以我倾向于怀疑这是最后一个。。。但我真的不知道如何去测试这三个场景中的任何一个

这是我的代码:

pid_t start_command(command* c, pid_t pgid) {
    (void) pgid;

    // If its a pipe token, create a shared pipe descriptor
    if (c->type == TOKEN_PIPE){
        pipe(c->pipefd);
    }

    // Fork a child process, run the command using `execvp`
    pid_t child = fork();
    if (child == 0) {
        // writing side of the pipe
        if (c->type == TOKEN_PIPE){
            dup2(c->pipefd[WRITE_SIDE], STDOUT_FILENO);
            close(c->pipefd);
        }
        // receiving side of the pipe
        else if (commandPrev->type == TOKEN_PIPE){
            dup2(commandPrev->pipefd[READ_SIDE], STDIN_FILENO);
            close(commandPrev->pipefd);
        }

        // run the command
        if (execvp(c->argv[0], c->argv) == -1) {
            // fork failed
            exit(-1);
        }
    } 
    else{
        // clean up, clean up, everybody, everywhere
        if (commandPrev->type == TOKEN_PIPE){
            close(commandPrev->pipefd);
        }
    }
    printf("return %i\n", getpid() );
    return child;
}

谢谢大家!

正如另一位评论者所说,你看起来像是在试图关闭一个数组。 这样的方法应该更有效:

// writing side of the pipe
if (c->type == TOKEN_PIPE){
    close(c->pipefd[READ_SIDE]);
    dup2(c->pipefd[WRITE_SIDE], STDOUT_FILENO);
    close(c->pipefd[WRITE_SIDE]);
}
// receiving side of the pipe
if (commandPrev->type == TOKEN_PIPE){
    close(commandPrev->pipefd[WRITE_SIDE]);
    dup2(commandPrev->pipefd[READ_SIDE], STDIN_FILENO);
    close(commandPrev->pipefd[READ_SIDE]);
}
或者,您可以在父管道中进行waitpid调用后关闭管道的活动侧。大概是这样的:

waitpid(child, &status, 0);

if (commandPrev->type == TOKEN_PIPE){
    close(commandPrev->pipefd[READ_SIDE]);
}
if (c->type == TOKEN_PIPE){
    close(c->pipefd[WRITE_SIDE]);
}

检查系统调用是否有错误,它们不会自动打印<代码>关闭(c->pipefd)似乎正在尝试关闭数组。请使用
shell
标记回答有关shell规范和语言的知识将有助于人们回答的问题。这在为学校写玩具壳的人身上是非常非常罕见的。@CharlesDuffy我的坏!我不知道,对不起