我正在尝试用 c 语言编写一个简单的 shell。现在我正在努力让管道正常工作。我有一个 struct c
,我将其输入到该函数中,它包含一个存储管道文件描述符 pipfd
的位置,并且还包含有关每个命令的结束标记的信息c->type
(可以是 | || && & 等)。 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 - 为什么我的管道不能互相通信?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40701808/