简体   繁体   English

程序执行ps aux | grep根| wc -l在C中使用管道

[英]Program to execute ps aux | grep root | wc -l using pipes in C

I have to write a program that displays the same output as if I write ps aux | grep root | wc -l 我必须编写一个显示与我写ps aux | grep root | wc -l相同输出的程序ps aux | grep root | wc -l ps aux | grep root | wc -l ps aux | grep root | wc -l in the terminal. 终端中的ps aux | grep root | wc -l After searching for answers in this web and not finding anything, and trying to understand this program from GitHub (which doesn't finish properly when I run it), this has been my humble attempt: 在此网络中搜索答案但未找到任何内容,并尝试从GitHub理解该程序 (运行时无法正常完成)之后,这是我的拙尝试:

#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;
}

However, I always get the same output: 但是,我总是得到相同的输出:

Signal 17 (CHLD) caught by ps (3.3.12). 信号17(CHLD)被ps(3.3.12)捕获。 /bin/ps:ps/display.c:66: please report this bug /bin/ps:ps/display.c:66:请报告此错误

Could someone give me an explanation why this program doesn't work properly? 有人可以给我解释一下为什么该程序不能正常工作吗? Because I'm sure it's not because of the supposed bug I have to report. 因为我确定不是因为我必须报告该错误。

Forking program is not excessively complex but requires very strict coding practices because when it goes wrong it is harder to debug. 分叉程序不是太复杂,但是需要非常严格的编码实践,因为如果出错,则很难调试。 Here I had to first let only parent run (just ps ), then parent and child ( ps | wc ). 在这里,我必须首先让仅父级运行(仅ps ),然后让父级和子级( ps | wc )运行。 At that moment I noticed that operations on child_grandchild_fd were interleaved amont operations on parent_child_fd , but it gave expected results. 在那一刻,我注意到,在操作child_grandchild_fd是在交错操作入账金额parent_child_fd ,但它给了预期的效果。

But at the moment of uncommenting the grandchild part, I noticed that your code was closing child_grandchild_fd before the fork , so when you try to use it in grandchild, you only dup already closed handles. 但是在取消注释孙子部分的那一刻,我注意到您的代码在fork之前关闭了child_grandchild_fd ,因此当您尝试在孙子中使用它时,您只会将已经关闭的句柄进行child_grandchild_fd So the grandchild reads from a closed handle and exits before using the content of the pipes. 因此,孙子在使用管道内容之前从封闭的句柄读取并退出。

The fix is trivial: just fork at first, then manage the pipe in the branches: 修复很简单:首先进行分叉,然后在分支中管理管道:

...
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);
...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM