我如何在Unix C中使用两个管道?

How do I use two pipes in Unix C?

我要做一个作业,内容如下:

用C编写一个程序,该程序创建一个孩子,该孩子还将创建一个孩子,在这三个进程之间建立管道,第一个进程(父亲)将连接第二个孩子(该孩子),而该孩子将与第三个孩子(该孩子的孩子)连接 )。 我们的程序应该显示使用bash作为默认shell的系统用户总数。 程序的结果应与" cat / etc / passwd | grep" / bin / bash $" | wc-l"相同

我对第一个孩子和我们关闭第一个管道并同时打开第二个管道的方法感到困惑。 如果您以正确的代码回复我,我将一次无法理解它。

谢谢。

到目前为止,这是我写的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
main()
{
int pid, pid2;
int fd[2];
int fd2[2];
char *arg[3];
char *arg2[3];
char *arg3[3];  
if (pipe(fd) == -1)
{
    perror("pipe");
    exit(1);
}
pid = fork();
if (pid == -1)
{
    perror("fork");
    exit(2);
}
if (pid == 0)
{
    if (pipe(fd2) == -1)
    {
        perror("pipe");
        exit(11);
    }
    pid2=fork();
    if(pid2 == -1)
    {
        perror("fork 2");
        exit(22);
    }
    if (pid2 == 0)
    {
        //i am child 2 (child of the child)
        close (fd2[1]);
        dup2 (fd2[0],0);
        close (fd2[0]);
        arg3[0] ="wc";
        arg3[1] ="-l";
        arg3[2] = NULL;
        execvp("wc", arg3);
        perror("execvp second child");
    }
    else
    {
        //i am child 1
        close (fd[1]);
        dup2(fd[0],0);
        close (fd[0]);
        close (fd2[0]);
        dup2(fd2[1],1);
        close (fd2[1]);
        arg2[0] ="grep";
        arg2[1] ="/bin/bash$";
        arg2[2] = NULL;
        execvp("grep", arg2);
        perror("execvp first child");
    }
}
else
{
    //i 'm the father
    close (fd[0]);
    dup2(fd[1],1);
    close (fd[1]);
    arg[0] ="cat";
    arg[1] ="/etc/passwd";
    arg[2] = NULL;
    execvp("cat", arg);
    perror("execvp father");    
}

}


您的程序几乎可以正常工作。缺少的是

1
2
3
    //i am child 2 (child of the child)
    close (fd[1]);
    close (fd[0]);

您称为fd的管道用于在" cat"和" grep"之间进行通信。当前代码中发生的事情是cat转储文件并退出并关闭其输出。 Grep会读取所有内容,并在其输入上等待EOF。由于"子代2"仍然打开了管道的输入端(它通过fork继承了它),因此grep永远等待。如果运行程序,然后键入ps,应该会看到一个grep和一个wc挂着等待完成。

在构造这样的管道时,通常要做的另一件事是安排它,以便最终任务(在本例中为wc)是外壳程序正在等待的任务。如所写,当您的程序从外壳运行时,它将在cat完成后似乎完成,并且wc的输出将像后台任务一样打印。如果您将管道布置为使wc在"我是孩子1"下,则外壳将改为等待wc。

或者,您可以将这三个进程全部分叉," child 1"将调用wait()来等待所有它们,然后退出。等待过程就像您自己的小外壳。