我必须编写一个显示相同输出的程序,就好像我在终端中写ps aux | grep root | wc -l
一样。在此网站中搜索答案后没有找到任何内容,并尝试从GitHub中了解this program(当我运行它时没有正确完成),这是我的谦虚尝试:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <string.h>
// Program to execute ps aux | grep root | wc -l
int main(int argc, char const *argv[]) {
int parent_child_fd[2];
pid_t child,grandchild;
if (pipe(parent_child_fd) == -1) {
perror("Error creating parent_child_fd");
return EXIT_FAILURE;
}
if ((child = fork()) == -1) {
perror("Error forking child");
return EXIT_FAILURE;
}else if(child == 0){
int child_grandchild_fd[2];
if (pipe(child_grandchild_fd) == -1) {
perror("Error creating child_grandchild_fd");
exit(EXIT_FAILURE);
}
close(parent_child_fd[1]);
close(child_grandchild_fd[0]);
dup2(parent_child_fd[0],0);
close(parent_child_fd[0]);
dup2(child_grandchild_fd[1],1);
close(child_grandchild_fd[1]);
if ((grandchild = fork()) == -1) {
perror("Error forking child");
exit(EXIT_FAILURE);
}else if(grandchild == 0){
close(child_grandchild_fd[1]);
dup2(child_grandchild_fd[0],0);
execlp("/usr/bin/wc","/usr/bin/wc","-l",(char*)NULL);
perror("Grandchild failed executing wc");
exit(EXIT_FAILURE);
}
execlp("/bin/grep","/bin/grep","root",(char*)NULL);
perror("Child failed executing grep");
exit(EXIT_FAILURE);
}
close(parent_child_fd[0]);
dup2(parent_child_fd[1],1);
close(parent_child_fd[1]);
execlp("/bin/ps","/bin/ps","aux", (char*)NULL);
perror("Parent failed executing ps");
return -1;
}
但是,我总是得到相同的输出:
信号17(CHLD)被ps(3.3.12)捕获。 /bin/ps:ps/display.c:66:请报告此错误
有人可以解释为什么这个程序不能正常工作吗?因为我确定它不是因为我必须报告的假设错误。
答案 0 :(得分:0)
分叉程序并不是过于复杂,但需要非常严格的编码实践,因为当它出错时,它更难调试。在这里,我必须先让父母跑(只有ps
),然后是父和子(ps | wc
)。在那一刻,我注意到child_grandchild_fd
上的操作是parent_child_fd
上的交错操作,但它给出了预期的结果。
但是在取消对孙子部分的注释的那一刻,我注意到你的代码在fork 之前关闭了child_grandchild_fd
,所以当你试图在孙子中使用它时,你只需要复制封闭的把手。所以孙子从一个封闭的手柄中读取并在使用管道内容之前退出。
修复很简单:首先是fork,然后管理分支中的管道:
...
if (pipe(child_grandchild_fd) == -1) {
perror("Error creating child_grandchild_fd");
exit(EXIT_FAILURE);
}
close(parent_child_fd[1]);
dup2(parent_child_fd[0],0);
close(parent_child_fd[0]);
if ((grandchild = fork()) == -1) {
perror("Error forking child");
exit(EXIT_FAILURE);
}else if(grandchild == 0){
close(child_grandchild_fd[1]);
dup2(child_grandchild_fd[0],0);
execlp("/usr/bin/wc","/usr/bin/wc","-l",(char*)NULL);
perror("Grandchild failed executing wc");
exit(EXIT_FAILURE);
}
dup2(child_grandchild_fd[1],1); // moved after the fork
close(child_grandchild_fd[0]);
close(child_grandchild_fd[1]);
execlp("/usr/bin/grep","/usr/bin/grep","root",(char*)NULL);
perror("Child failed executing grep");
exit(EXIT_FAILURE);
...