FIFO - 从顶层进程读取,从底层进程写入

Posted

技术标签:

【中文标题】FIFO - 从顶层进程读取,从底层进程写入【英文标题】:FIFO - reading from top level process, writing from bottom level process 【发布时间】:2016-03-02 21:05:41 【问题描述】:

我正在尝试在程序的顶层和底层进程之间进行通信。首先我创建 FIFO,然后我有一个 for 循环来分叉 n 个进程。在 for 循环中,我检查一个进程是否是底层进程,如果是,我写入 FIFO。

我对在底层进程写入 FIFO 后如何从 FIFO 中读取数据感到困惑。如果我尝试在循环之前读取,则循环永远不会执行,因为没有写入任何内容。如果我尝试在循环期间阅读,在代码的父部分中,其他父母也可以阅读它。如果我尝试在 for 循环之后阅读,代码循环永远不会完成,因为当最后一个孩子尝试写入时它会卡住。这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <errno.h>

#define MAX_BUF 1024

int main(int argc, char **argv)

    int numprocs = atoi(argv[1]);
    int lev = numprocs;
    fprintf(stdout,"ALIVE: Level %d process with pid=%d, child of ppid=%d.\n", lev, getpid(), getppid());
    int currpid = getpid();

    //create shared memory
    const int SIZE = numprocs * sizeof(int);
    const char *name = "dleggio1OS";
    int shm_fd;
    int *ptr;
    shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
    ftruncate(shm_fd, SIZE);
    ptr = mmap(0, SIZE, PROT_WRITE, MAP_SHARED, shm_fd, 0);
    *ptr = getpid();

    //create fifo
    int fd;
    char *myfifo = "/tmp/dleggio1fifo";
    mkfifo(myfifo, 0666);
    //read fifo
    /*char buff[MAX_BUF];
    fd = open(myfifo,O_RDONLY);
    read(fd,buff,MAX_BUF);
    printf("process %d received %s message.\n",getpid(),buff);
    close(fd);*/


    //spawn procs
    int i;
    for(i = 1; i < numprocs; i++)
        lev--;
        int pfds[2];
        char buf[30];
        if(pipe(pfds) == -1)
            perror("pipe");
            exit(1);
        
        pid_t pid;


        if((pid = fork()) < 0)
            perror("fork");
            exit(1);
        

        if(pid == 0) //child

            ptr[i] = getpid();

            close(pfds[1]);
            if(read(pfds[0], buf, 3) <= 0)
                perror("child");
                exit(1);
            
            int check = atoi(buf);
            fprintf(stdout,"ALIVE: Level %d process with pid=%d, child of ppid=%d.\n", check, ptr[i], ptr[i-1]);

            if(check == 1) //leaf
                //write to fifo
                fd = open(myfifo, O_WRONLY);
                write(fd,"leaf",sizeof("leaf"));
                close(fd);
                return 0;
            

        
        else //parent
            close(pfds[0]);
            char hold[3];
            sprintf(hold,"%d",lev);
            if(write(pfds[1], hold, 3) <= 0)
                perror("parent");
                exit(1);
            
            //read fifo
            /*char buff[MAX_BUF];
            fd = open(myfifo,O_RDONLY);
            read(fd,buff,MAX_BUF);
            printf("process %d received %s message.\n",getpid(),buff);
            close(fd);*/

            wait(NULL);
            return 0;
        
    

    //read fifo

    /*char buff[MAX_BUF];
    fd = open(myfifo,O_RDONLY);
    read(fd,buff,MAX_BUF);
    printf("received %s message.\n",buff);
    close(fd);*/

    shm_unlink(name);
    unlink(myfifo);
    return 0;

【问题讨论】:

【参考方案1】:

如果我尝试在循环期间读取代码的父部分, 其他家长也可以阅读。

它们都可以从 FIFO 中读取,因为您在派生任何进程之前创建了 FIFO;因此,他们都使用同一个。如果您希望每个父/子对都有一个只有他们可以使用的私有 FIFO,那么您需要将您的 mkfifo() 调用移动到循环内,并为每个 fork() 创建一个 FIFO(具有唯一名称)。

【讨论】:

我怎样才能只让顶层父级和底层子级拥有私有 FIFO? 在每次循环迭代中,创建一个具有唯一名称的新 FIFO(例如,将循环计数器添加到名称的末尾)并让父/子使用它。然后每次迭代将只知道它的私有 FIFO 的名称,并且无法访问其他任何人的名称。

以上是关于FIFO - 从顶层进程读取,从底层进程写入的主要内容,如果未能解决你的问题,请参考以下文章

FIFO:一个进程从不从管道中读取

如何停止 fgets 从 FIFO 文件中读取

read() 不会阻塞在没有 O_NONBLOCK 标志的情况下打开的空 FIFO

当多个进程尝试同时写入然后从文件中读取时,如何防止竞争条件

Linux - 进程间通信 - 命名管道

Linux 进程间通信之管道(pipe),(fifo)