两个叉子和等待的使用

目前我正在做两个叉来pipe道两个进程,但我认为我正在做我的wait(&status)错误,因为命令后,我的shell只是挂起,并没有返回到我的提示。 我知道我的pipe道工作,因为我可以看到结果,如果我删除等待。

有小费吗?

 pipe(mypipe); pid1=fork(); if(pid1==0) { pid2=fork(); if(pid2==0) { close(0); dup(mypipe[0]); close(mypipe[1]); execv(foundnode2->path_dir,arv2); exit(0); } close(1); dup(mypipe[1]); close(mypipe[0]); pid2 = wait(&status2); execv(foundnode1->path_dir,arv1); exit(0); } pid1 = wait(&status2); 

经验法则:如果使用dup()dup2()将管道的一端映射到标准输入或标准输出,则应close()管道本身的两端。 你不是那样做的; 您的等待正在等待程序完成,但是程序不会完成,因为仍然有管道打开的问题,可以写入管道。 另外,创建管道的进程需要关闭管道的两端,因为管道本身不使用管道(子进程正在使用它)。 另请参阅C MiniShell – 添加管道 。

此外,你不应该等待第一个孩子在发射第二个孩子之前完成(所以pid2 = wait(&status2);行是一个坏主意)。 管道容量相当小; 如果要传输的数据量过大,写入的孩子可能会阻止阅读孩子阅读,但阅读孩子尚未开始,因为它正在等待写作孩子退出(这需要很长时间为了解决这个僵局)。 你看到输出没有wait()调用,因为管道的第二部分执行和处理来自管道第一部分的数据,但是它仍然在等待来自shell的更多数据。

考虑到这些提示,您可能会得到:

 pipe(mypipe); pid1 = fork(); if (pid1 == 0) { pid2 = fork(); if (pid2 == 0) { close(0); dup(mypipe[0]); close(mypipe[1]); close(mypipe[0]); execv(foundnode2->path_dir, arv2); fprintf(stderr, "Failed to exec %s\n", foundnode2->path_dir); exit(1); } close(1); dup(mypipe[1]); close(mypipe[0]); close(mypipe[1]); execv(foundnode1->path_dir, arv1); fprintf(stderr, "Failed to exec %s\n", foundnode1->path_dir); exit(1); } close(mypipe[0]); close(mypipe[1]); pid1 = wait(&status1); 

当命令无法执行execv()时,请注意错误报告为标准错误。 另外,0的退出状态应保留为成功; 1是一个方便的错误退出状态,或者您可以使用<stdlib.h> EXIT_FAILURE

还有很多错误检查被遗漏了。 fork()操作可能会失败; pipe()可能会失败。 其中一个后果是,如果第二个fork()失败,您仍然启动第二个子项(由foundnode1->path_dir )。

我注意到,通过将管道创建移动到第一个子进程(父进程不需要 – 实际上不能 – 关闭管道),您可以节省一些工作量:

 int pid1 = fork(); if (pid1 == 0) { int mypipe[2]; pipe(mypipe); int pid2 = fork(); if (pid2 == 0) { close(0); dup(mypipe[0]); close(mypipe[1]); close(mypipe[0]); execv(foundnode2->path_dir, arv2); fprintf(stderr, "Failed to exec %s\n", foundnode2->path_dir); exit(1); } close(1); dup(mypipe[1]); close(mypipe[0]); close(mypipe[1]); execv(foundnode1->path_dir, arv1); fprintf(stderr, "Failed to exec %s\n", foundnode1->path_dir); exit(1); } pid1 = wait(&status1); 

如果这只是一个有两个进程的管道,我根本不会等待。 只需在父母和子女分岔并做一名高管。

 int fd[2]; pipe(fd); int pid = fork(); if (pid == -1) { /* error handling */ } else if (pid == 0) { dup2(fd[0], 0); close(fd[1]); execv(foundnode2->path_dir,arv2); /* error handling for failed exec */ exit(1); } else { dup2(fd[1], 1); close(fd[0]); execv(foundnode1->path_dir,arv1); /* error handling for failed exec */ exit(1); }