gpt4 book ai didi

c - 为什么我的管道不能互相通信?

转载 作者:行者123 更新时间:2023-11-30 20:35:00 25 4
gpt4 key购买 nike

我正在尝试用 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com