C中多个子进程之间的管道示例

时间:2017-03-30 16:17:22

标签: c pipe fork stdin file-descriptor

当我在C中使用pipe()函数时,我有点困惑。我的目标是在子进程之间传输数据。我希望每个孩子从fd[0]获取输入并写信给fd[1]。我的代码在这里,但我无法获得任何结果。哪里出错了?我怎么能想象管道?

    int main()
    {

    char *arr = malloc(sizeof(int));
    int num;
    int fd[2];
    char *piping = malloc(10*sizeof(char));
    char *word = malloc(10*sizeof(char));

    while(1)
    {
        printf("enter the number of child: ");
        fflush(stdout);
        fgets(arr, 10, stdin);

        printf("enter word: ");
        fflush(stdout);
        fgets(word, 10, stdin);

        num = atoi(arr);

        pipe(fd);
        for(int i = 0; i < num; i++)
        {
                if(!fork())
                {
                        read(0, piping, 10);
                        if(i != 0)
                        {   
                            dup2(fd[0],0);
                        }
                        if(i != num-1)
                        {
                            dup2(fd[1],1);
                        }
                        write(1, piping, 10);
                }
                else
                    wait(0);
        }
    }   
    return 0;
   }

2 个答案:

答案 0 :(得分:2)

这有点不对劲。暂时忘掉所有管道的东西,看看分叉。代码如下所示:

exit(0);

父母进入循环,创建第一个孩子并等待它。

第一个孩子进入循环的第二次迭代,创建一个孩子并等待它

第一个孩子的孩子进入循环的第三次迭代,创建一个孩子并等待它。

依此类推,直到我们拥有一个数量为1的父母和孩子的祖先链。 num-1的孩子只是退出,这意味着它的父母将停止等待并继续循环的下一次迭代。它也将退出,因此第2,3个孩子将停止等待,但它仍然有循环的迭代,所以它创建另一个孩子并等待它。

你正在创造更多的孩子然后你可能想要因为你忘记了父母和孩子都在分叉后继续执行相同的代码。您可能希望if ... else的if部分包含exec作为其最后一个语句。

然而,你的问题不在那里。在if部分中,首先尝试从stdin读取,这意味着所有多个子进程都将阻止等待来自终端的输入。

重复的东西目前毫无意义。除了你读取标准输入之后,你不会将管道的读取端重复到标准输入,除非你调用fd[1],否则为什么不直接使用它。写作的孩子可以直接写到fd[0],阅读的孩子可以直接从 1 function Dijkstra(Graph, source): 2 3 create vertex set Q 4 5 for each vertex v in Graph: // Initialization 6 dist[v] ← INFINITY // Unknown distance from source to v 7 prev[v] ← UNDEFINED // Previous node in optimal path from source 8 add v to Q // All nodes initially in Q (unvisited nodes) 9 10 dist[source] ← 0 // Distance from source to source 11 12 while Q is not empty: 13 u ← vertex in Q with min dist[u] // Node with the least distance will be selected first 14 remove u from Q 15 16 for each neighbor v of u: // where v is still in Q. 17 alt ← dist[u] + length(u, v) 18 if alt < dist[v]: // A shorter path to v has been found 19 dist[v] ← alt 20 prev[v] ← u 21 22 return dist[], prev[] 阅读。

答案 1 :(得分:1)

当前的问题是每个子进程在进行之前等待从其标准输入(而不是管道)读取某些内容,并且您没有提供任何输入(或者至少对所有子进程都不够)。也许你打算在 xhr.responseType = "blob"; xhr.onload = () => { console.log(xhr.response.type) }; 之前执行dup2()时执行它。

虽然解决这个问题可能会让你的程序运行完成,但总体策略至少在这些方面存在缺陷:

    在开始下一个孩子之前,
  • 每个孩子的父read()个。这会产生两种问题

    • 你没有任何实际的并发性。那么,什么是分叉的重点?
    • 如果孩子们正在向管道写入更多输出,那么他们就有可能填充缓冲区并因此阻塞。这会产生死锁,因为缓冲区只会被下一个孩子耗尽,而下一个孩子在其前任终止之前就不会被启动。
  • 每对进程都使用相同的管道进行通信。这只能起作用,因为父级序列化子进程的执行(如上所述)。由于此类序列化存在固有问题,除其他原因外,您通常希望每个管道专用于一对流程。