我正在开发一个用C实现的小shell(tsh)(这是一个赋值)。任务的一部分属于PIPING。我必须将命令的输出传递给另一个命令。例如:ls -l | sort
当我运行shell时,我在其上执行的每个命令都由它生成的子进程处理。孩子完成后,返回结果。对于管道我想首先实现一个编码的例子来检查它是如何工作的。我写了一个部分有效的方法。问题是当我运行管道命令时,在子进程完成后,整个程序退出它!显然我没有正确处理子进程信号(下面的方法代码)。
如何使用pipe()进行流程管理?如果我运行一个命令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
答案 0 :(得分:1)
是的,shell必须fork来执行每个子进程。请记住,当您调用其中一个execve()
函数系列时,将替换当前过程映像与exec的一个。如果shell直接执行子进程,则shell无法继续处理其他命令,因为此后它不再存在(除了子进程外)。
要修复它,只需在fork()
分支中再次pid == 0
,并在该子代中执行ls
命令。如果您不是要异步执行管道,请记住wait()
两个(所有)子进程。
答案 1 :(得分:0)
是的,您需要至少调用两次fork,一次为管道中的每个程序调用一次。请记住,exec会替换当前进程的程序映像,因此shell会在您开始运行sort或(tr)时停止存在。