【问题标题】:C - Named pipe between top level process and bottom level (leaf) processC - 顶级流程和底层(叶)流程之间的命名管道
【发布时间】:2016-06-12 20:15:29
【问题描述】:

我正在尝试从底层叶进程写入命名管道,并从顶层进程的管道读取。

为此,我首先在顶级进程中创建 FIFO,然后使用 for 循环分叉更多进程。在 for 循环中,我正在检查叶子进程,如果它是叶子,我将写入 FIFO 并从循环中中断。然后,在循环之后,我试图从顶层进程中的 FIFO 中读取。这不起作用,我的程序在叶进程创建后卡住并停止。

如何通过 FIFO 将消息从叶子发送回顶级父进程?

代码:

#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());

    //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);

    //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

            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[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, getpid(), getppid());

            if(check == 1){ //leaf
                fd = open(myfifo, O_WRONLY);
                write(fd,"leaf",sizeof("leaf"));
                close(fd);
                break;
            }

        }
        else{ //parent
            close(pfds[0]);
            char hold[3];
            sprintf(hold,"%d",lev);
            if(write(pfds[1], hold, 3) <= 0){
                perror("parent");
                exit(1);
            }

            wait(NULL);
            return 0;
        }
    }

    //read fifo
    char buff[MAX_BUF];
    fd = open(myfifo,O_RDONLY);
    read(fd,buff,MAX_BUF);
    close(fd);

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

输出:

ALIVE: Level 3 process with pid=554, child of ppid=451.
ALIVE: Level 2 process with pid=555, child of ppid=554.
ALIVE: Level 1 process with pid=556, child of ppid=555.
_ // <---- stalls here

【问题讨论】:

  • 查看代码会有帮助。
  • 添加代码和输出
  • 代码(至少)通过在此处打印非 0 终止的“字符串”来引发未定义的行为:printf("received %s message.\n",buff);
  • ftruncate() 的原型似乎也不见了。
  • ...wait() 相同。

标签: c pipe fork ipc named-pipes


【解决方案1】:

所有进程都挂在“wait()”调用上(即等待其中一个子进程退出),除了最后一个分叉的子进程...挂在“open(myfifo, O_WRONLY)”上。 .. 最后一个孩子将继续挂起,直到某个进程打开 fifo 进行读取...

【讨论】:

  • 如何让我的顶级进程打开 fifo 进行读取?如果我把它放在我 fork 进程的 for 循环之后,for 循环永远不会完成(卡在最后一个孩子身上),所以它永远不会读取。如果我把它放在 for 循环之前,它会在写入之前尝试读取并且永远不会执行循环。如果我尝试在父部分的 for 循环中读取,其他父级也可以从中读取,而不仅仅是顶级父级。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多