首页 > 解决方案 > 为什么我不能重用管道与多个子进程通信?

问题描述

如果我有一个包含子进程的父进程n,为什么我不能使用一个管道将父进程的 pid 发送到所有子进程?这篇文章对此进行了简要介绍,但我觉得解释得不够清楚。

这是我的代码:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

void main(void){

    int n;

    printf("How many child processes would you like to create?");
    scanf("%d", &n);

    pid_t pid, child, ppid, pidout;
    int fd[2];
    pipe(fd);
    
    for (int i = 0; i < n; i++){
        pid = fork();
        switch(pid){
        
            case -1:
                printf("error forking at index %i", i);
                exit(1);
                
            case 0: 
                close(fd[1]);
                child = getpid();
                read(fd[0], &pidout, 4);
                printf("\nNode : %i\nMy pid is : %i\nMy parent's pid is : %i\n\n", i, child, pidout);
                exit(0);
                
            default:    
                close(fd[0]);
                ppid = getpid();
                write(fd[1], &ppid, 4);
                if (!i){
                    printf("\nNode : %i, My pid is : %i\n\n", i, ppid);
                }
        }
    }
    for (int i = 0; i < n; i++){
            wait();
    }

}

在这里,我尝试重用相同的管道将数据从父级发送到子级,但是在父级的 pid 发送到第一个子级后,管道会中断。我知道解决这个问题的方法是使用n-1管道:每个通信一个。但是,我不明白为什么这段代码不起作用。任何澄清将不胜感激。谢谢!

标签: unixpipe

解决方案


(警告:我不是管道和 Unix IPC 专家。)

您可能看到的是管道的预期行为,即通过管道的东西从另一边出来,而不仅仅是留在那里供其他人观察。一个进程写入,另一个进程读取 - 管道不会保留所有数据,并且会被清除。

也许一个不同的系统调用可以工作,它允许在管道缓冲区达到峰值而不清除它,尽管这听起来不是一个优雅的解决方案。另一种可能的方法是建立一个进程间共享内存区域形式的“海报板”,父进程可以写入该内存区域,子进程可以读取该区域。

编辑:在创建所有子项之前,您还存在过早关闭管道读取端的问题。请参阅@MarcoLucidi 的回答。


推荐阅读