管道和工艺管理

我正在研究用C实现的一个小shell(tsh)(它是一个赋值)。 任务的一部分属于PIPING。 我必须将命令的输出传递给另一个命令。 例如: ls -l | sort ls -l | sort

当我运行shell时,我在其上执行的每个命令都由它生成的子进程处理。 孩子完成后,返回结果。 对于管道我想首先实现一个带编码的示例来检查它是如何工作的。 我写了一个部分有效的方法。 问题是当我运行管道命令时,在子进程完成后,整个程序退出它! 显然我没有正确处理子进程信号(下面的方法代码)。

我的问题:

  • 如何使用pipe()进行流程管理? 如果我运行命令ls -l | sort ls -l | sort是否为ls -l和另一个进程sort创建子进程? 从我到目前为止看到的管道示例中,只创建了一个进程(fork())。

  • 当处理第二个命令(从我们的示例中sort )时,我如何获得其进程ID?

编辑:同时运行此代码我得到两次结果。 不知道为什么它会运行两次,那里没有循环。

这是我的代码:

 pid_t pipeIt(void){ pid_t pid; int pipefd[2]; if(pipe(pipefd)){ unix_error("pipe"); return -1; } if((pid = fork()) <0){ unix_error("fork"); return -1; } if(pid == 0){ close(pipefd[0]); dup2(pipefd[1],1); close(pipefd[1]); if(execl("/bin/ls", "ls", (char *)NULL) < 0){ unix_error("/bin/ls"); return -1; }// End of if command wasn't successful }// End of pid == 0 else{ close(pipefd[1]); dup2(pipefd[0],0); close(pipefd[0]); if(execl("/usr/bin/tr", "tr", "e", "f", (char *)NULL) < 0){ unix_error("/usr/bin/tr"); return -1; } } return pid; }// End of pipeIt 

是的,shell必须fork来执行每个子进程。 请记住,当您调用execve()函数系列之一时,它会将当前过程映像替换为exec。 如果shell直接执行子进程,则shell无法继续处理其他命令,因为此后它不再存在(除了子进程外)。

要修复它,只需在pid == 0分支中再次fork() ,并在该子进程中执行ls命令。 如果不是要异步执行管道,请记住对两个(所有)子进程都wait()

是的,您需要至少调用两次fork,一次为管道中的每个程序调用。 请记住,exec会替换当前进程的程序映像,因此shell会在您开始运行sort或(tr)时停止存在。