多个子进程之间的管道

时间:2014-11-07 04:53:53

标签: c operating-system pipe

我试图通过来自父母的不同子进程来处理输入。我可以通过前3个孩子来做到这一点,但在那之后,我似乎无法获得任何输入或任何类型的东西。

这是我的代码。

#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>

int main(int argc, char** argv)
{
pid_t pid;
int  pipes_1[2];
int pipes_2[2];
pipe(pipes_1);
pipe(pipes_2);

switch(pid=fork())
  {
  case 0:
    dup2(pipes_1[0], 0);//copy stdin onto pipe 1 read
    dup2(pipes_2[1], 1);//copy stdout onto pipe 2 write
    close(pipes_1[0]);
    close(pipes_1[1]);
    close(pipes_2[0]);
    close(pipes_2[1]);

    execlp("sed", "sed","s/[^a-zA-Z]/ /g", "test.txt", (char*)NULL);

    break;

  default:
    break;
  }

switch(pid = fork())
  {
  case 0:
    dup2(pipes_2[0],0); //copy std onto pipes 2 read
    dup2(pipes_1[1],1);
    close(pipes_1[0]);
    close(pipes_1[1]);
    close(pipes_2[0]);
    close(pipes_2[1]);

    execlp("tr", "tr", "[A-Z]", "[a-z]", (char*)NULL);

    break;
  default:

    break;
  }
switch(pid=fork())
  {
  case 0:
    dup2(pipes_1[0], 0);
    dup2(pipes_2[1], 1);
    close(pipes_1[0]);
    close(pipes_1[1]);
    close(pipes_2[0]);
    close(pipes_2[1]);

    execlp("awk", "awk", "{for(i = 1; i <= NF; i++) {print $i;}}", (char*)NULL);
    break;
  default:

    break;
  }

switch(pid=fork())
  {
  case 0:
    dup2(pipes_2[0], 0);
    //dup2(pipes_1[1], 1);
    close(pipes_1[0]);
    close(pipes_1[1]);
    close(pipes_2[0]);
    close(pipes_2[1]);
    execlp("sort", "sort", (char*)NULL);
  default:
    break;
    }
wait();
return 0;
}

我知道格式化很糟糕。但你能看出我做错了什么吗?我认为这可能与仅使用两个管道有关。

编辑:用4个管道更新了代码。

int main(int argc, char** argv)
{
pid_t pid;
int  pipes_1[2];
int pipes_2[2];
int pipes_3[2];
int pipes_4[2];
 pipe(pipes_1);
pipe(pipes_2);
pipe(pipes_3);
pipe(pipes_4);

switch(pid=fork())
  {
  case 0:
    dup2(pipes_1[0], 0);//copy stdin onto pipe 1 read
    dup2(pipes_2[1], 1);//copy stdout onto pipe 2 write
    close(pipes_1[0]);
    close(pipes_1[1]);
    close(pipes_2[0]);
    close(pipes_2[1]);

    execlp("sed", "sed","s/[^a-zA-Z]/ /g", "test.txt", (char*)NULL);

    break;

  default:
    break;
  }

switch(pid = fork())
  {
  case 0:
    dup2(pipes_2[0],0); //copy std onto pipes 2 read
    dup2(pipes_3[1],1);
    close(pipes_3[0]);
    close(pipes_3[1]);
    close(pipes_2[0]);
    close(pipes_2[1]);

    execlp("tr", "tr", "[A-Z]", "[a-z]", (char*)NULL);

    break;
  default:

    break;
  } 
switch(pid=fork())
{
case 0:
  dup2(pipes_3[0], 0);
  dup2(pipes_4[1], 1);
  close(pipes_3[0]);
  close(pipes_3[1]);
  close(pipes_4[0]);
  close(pipes_4[1]);

  execlp("awk", "awk", "{for(i = 1; i <= NF; i++) {print $i;}}", (char*)NULL);
  break;
default:

  break;
  }*/

switch(pid=fork())
{
case 0:
  dup2(pipes_4[0], 0);
  //dup2(pipes_1[1], 1);
  close(pipes_4[0]);
  close(pipes_4[1]);
  //close(pipes_2[0]);
  //close(pipes_2[1]);
  execlp("sort", "sort", (char*)NULL);
default:
  break;
  }
wait();
return 0;
}

1 个答案:

答案 0 :(得分:1)

你似乎有一个管道:

sed … | tr … | awk … | sort

您只需创建两个管道,其中需要三个管道。创建第三个管道并正确处理它,你就可以了。


调整第二个代码。请注意,四个进程只需要三个管道(通常N个进程需要N-1个管道)。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

static inline void error(const char *msg)
{
    perror(msg);
    exit(EXIT_FAILURE);
}

int main(void)
{
    int pid;
    int pipes_1[2];
    int pipes_2[2];
    int pipes_3[2];
    pipe(pipes_1);
    pipe(pipes_2);
    pipe(pipes_3);

    if ((pid = fork()) == 0)
    {
        dup2(pipes_1[1], 1);
        close(pipes_1[0]);
        close(pipes_1[1]);
        close(pipes_2[0]);
        close(pipes_2[1]);
        close(pipes_3[0]);
        close(pipes_3[1]);
        execlp("sed", "sed", "s/[^a-zA-Z]/ /g", "test.txt", (char *)NULL);
        error("Failed to exec sed");
    }
    printf("sed:  %d\n", pid);

    if ((pid = fork()) == 0)
    {
        dup2(pipes_1[0], 0);
        dup2(pipes_2[1], 1);
        close(pipes_1[0]);
        close(pipes_1[1]);
        close(pipes_2[0]);
        close(pipes_2[1]);
        close(pipes_3[0]);
        close(pipes_3[1]);
        execlp("tr", "tr", "[A-Z]", "[a-z]", (char *)NULL);
        error("Failed to exec tr");
    }
    printf("tr:   %d\n", pid);

    if ((pid = fork()) == 0)
    {
        dup2(pipes_2[0], 0);
        dup2(pipes_3[1], 1);
        close(pipes_1[0]);
        close(pipes_1[1]);
        close(pipes_2[0]);
        close(pipes_2[1]);
        close(pipes_3[0]);
        close(pipes_3[1]);
        execlp("awk", "awk", "{for(i = 1; i <= NF; i++) {print $i;}}", (char *)NULL);
        error("Failed to exec awk");
    }
    printf("awk:  %d\n", pid);

    if ((pid = fork()) == 0)
    {
        dup2(pipes_3[0], 0);
        close(pipes_1[0]);
        close(pipes_1[1]);
        close(pipes_2[0]);
        close(pipes_2[1]);
        close(pipes_3[0]);
        close(pipes_3[1]);
        execlp("sort", "sort", (char *)NULL);
        error("Failed to exec sort");
    }
    printf("sort: %d\n", pid);

    close(pipes_1[0]);
    close(pipes_1[1]);
    close(pipes_2[0]);
    close(pipes_2[1]);
    close(pipes_3[0]);
    close(pipes_3[1]);

    int status;
    int corpse;
    while ((corpse = wait(&status)) > 0)
        printf("PID %d died 0x%.4X\n", corpse, status);

    return 0;
}

示例输入:

Happy Go Lucky!
PENULTIMATE DESTINY@
missing all upper-case=
What gives?
Digital 023123098 Diarrhea

示例输出:

sed:  74841
tr:   74842
awk:  74843
sort: 74844
PID 74841 died 0x0000
PID 74842 died 0x0000
PID 74843 died 0x0000
all
case
destiny
diarrhea
digital
gives
go
happy
lucky
missing
penultimate
upper
what
PID 74844 died 0x0000

进程ID信息主要是诊断信息。如果将程序的输出传递给过滤器,则会得到不同的输出(因为缓冲等),但不同之处在于排序数据与诊断相对应的顺序。将诊断信息打印为标准错误,或在每个fflush(stdout)之后添加printf(),您将更常规地获得与所示输出相似的内容。