我正在使用 pipe、fork 和 exec 来实现用户 shell。问题是它在某些情况下不起作用。例如,如果我有 ls | 它会起作用head 但不适用于 ls |猫。它将显示 cat 的输出,但之后会挂起而不会返回到提示符。
关于代码,我将输入存储在 c->args[0] 中,为此我派生了一个子节点并执行它。
我知道第二个 exec 仍在等待 EOF,但在此之前关闭文件描述符没有帮助。
经历类似的问题,我也尝试在等待之前关闭父进程中的文件描述符,但在这样做之后甚至 ls |头不工作。 我已经在下面发布了相关功能。
void executeProcess(Cmd c,int noofcmds)
{
// printf("Will be entering fork procedure \n");
int cmdNo;
pipe(fd);
for (cmdNo = 0;cmdNo < noofcmds; cmdNo ++)
{
int processid = fork();
pid_t childpid;
// printf("Process id %d\n",processid);
if (processid == 0)
{
// if (noofcmds != 1)
// {
if (cmdNo == 0)
{
printf("Inside first child \n");
close(fd[0]);
dup2(fd[1], 1);
// close(fd[0]);
} else if (cmdNo == noofcmds-1)
{
close(fd[1]);
dup2(fd[0], 0);
// close(fd[0]);
}
// close(fd[1]);
// close(fd[0]);
if (execvp(c->args[0],c->args) < 1)
{ printf("Error\n");
}
} else
{
// printf("Waiting in parent\n");
// close(fd[0]);
// close(fd[1]);
int status;
int returnedpid;
wait(&status);
printf("Returned after waiting\n");
// close(fd[0]);
// close(fd[1]);
}
c = c->next;
// close(fd[0]);
// close(fd[1]);
} // end of for
}
最佳答案
查看事件顺序,使用 ls | cat
这是现在发生的事情:
1) 管道在父级中创建。
2) ls
child 被生成
3) parent 等待 ls
完成
4) cat
child 被生成
5) parent 等待 cat
完成
如您所见,在 5) 中,父级仍然打开管道,因此 cat
永远不会完成。
当您在代码的父部分关闭它时,它会在 3) 之前关闭...因此,当 cat
启动时,管道不再存在 -> cat
没有输出。
你需要的是在 4) 之后用类似的东西关闭它:
...
else // in parent
{
// printf("Waiting in parent\n");
if (cmdNo == 1) // second child is spawned, can close the pipe now.
{
close(fd[0]);
close(fd[1]);
}
int status;
wait(&status);
printf("Returned after waiting\n");
}
代码将需要更多的工作来处理一个管道中的 2 个以上的命令,但你明白了......
提示:找一个自动缩进代码的编辑器,它会让你的生活更轻松!
关于c - 在某些情况下,在管道中执行第二个/最后一个命令后进程挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26208975/