我想在c中编写一个简单的shell。现在我试图让管道工作。我有一个结构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;
}
谢谢!
检查您的系统调用错误,它们不会自动打印。 'close(c-> pipefd);'似乎试图关闭一个数组。 –
对于壳牌规格和语言的知识将帮助人们回答的问题,请使用'shell'标签。人们为学校编写玩具壳这一点非常非常少见。 –
@CharlesDuffy我的坏!我不知道,对不起 – Twiigs