C语言 三个孩子之间的管道



我将执行ls -al / | tr a-j A-J | tr k-z K-Z命令,并从父进程创建三个子进程。

我知道我必须打开两个管道,让父亲等待他所有的孩子(关闭所有的管道),在孩子我必须

  • 在第一个子进程上关闭STDIN
  • 在第一个管道上关闭STDOUT,在第二个管道上关闭STDIN
  • 关闭第三个子进程的STDOUT
现在,这是我的代码。如果我只运行两个子节点,它就能运行。但是,如果我尝试用三个子节点运行它,它就不起作用了。
//  command is ls -al / | tr a-j A-J | tr k-z K-Z
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char **argv) {
int fd1[2];
int fd2[2];
pid_t pid = 0;
pipe(fd1);
pipe(fd2);
pid = fork();
if(pid == 0) {
    close(fd1[0]);
    dup2(fd1[1], 1);
    close(fd1[1]);
    execlp("ls", "ls", "-al", "/", NULL);
}
pid = fork();
if(pid == 0) {
    close(fd1[1]);
    dup2(fd1[0], 0);
    close(fd1[0]);
    close(fd2[0]);
    dup2(fd2[1], 1);
    close(fd2[1]);
    execlp("tr", "tr", "a-j", "A-J", NULL);
}
pid = fork();
if(pid == 0) {
    close(fd2[1]);
    dup2(fd2[0], 0);
    close(fd2[0]);
    execlp("tr", "tr", "k-z", "K-Z", NULL);
}
close(fd1[0]);
close(fd1[1]);
close(fd2[0]);
close(fd2[1]);
while ((pid = wait(NULL)) != -1);
exit(0);
}

提前感谢。

您可以使用pipe2()设置close_on_exec标志。下面的代码可以工作:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char **argv) {
  int fd1[2];
  int fd2[2];
  pid_t pid = 0;
  pipe2(fd1,O_CLOEXEC);
  pipe2(fd2,O_CLOEXEC);
  pid = fork();
  if(pid == 0) {
    dup2(fd1[1],1);
    execlp("ls", "ls", "-al", "/", NULL);
  }
  pid = fork();
  if(pid == 0) {
    dup2(fd1[0],0);
    dup2(fd2[1],1);
    execlp("tr", "tr", "a-j", "A-J", NULL);
  }
  pid = fork();
  if(pid == 0) {
    dup2(fd2[0],0);
    execlp("tr", "tr", "k-z", "K-Z", NULL);
  }
  close(fd1[0]);
  close(fd1[1]);
  close(fd2[0]);
  close(fd2[1]);
  while ((pid = wait(NULL)) != -1);
  exit(0);
}

也可以使用pipe()调用,但您应该注意手动关闭所有描述符,这很容易出错(您通过发布这个问题证明了这一点;-)):

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char **argv) {
  int fd1[2];
  int fd2[2];
  pid_t pid = 0;
  pipe(fd1);
  pipe(fd2);
  pid = fork();
  if(pid == 0) {
    close(fd1[0]);
    dup2(fd1[1], 1);
    close(fd1[1]);
    execlp("ls", "ls", "-al", "/", NULL);
  }
  pid = fork();
  if(pid == 0) {
    close(fd1[1]);
    dup2(fd1[0], 0);
    close(fd1[0]);
    close(fd2[0]);
    dup2(fd2[1], 1);
    close(fd2[1]);
    execlp("tr", "tr", "a-j", "A-J", NULL);
  }
  pid = fork();
  if(pid == 0) {
    close(fd1[0]);
    close(fd1[1]);
    close(fd2[1]);
    dup2(fd2[0], 0);
    close(fd2[0]);
    execlp("tr", "tr", "k-z", "K-Z", NULL);
  }
  close(fd1[0]);
  close(fd1[1]);
  close(fd2[0]);
  close(fd2[1]);
  while ((pid = wait(NULL)) != -1);
}

最新更新