How does a parent process read a FIFO after the ch

2019-08-19 07:21发布

问题:

I have a very simple basic program that has two process first one is parent and second one is child.

Child process should write some stuff to the FIFO. After all writing jobs finished(after the child is terminated). Then parent process should read all the FIFO file and print to the stdout.

So I think, I need a wait(NULL); for parent. So the parent will wait until the child is terminated. But child is also blocked because of the writing and blocked for reading this writes. So both process wait each other and I think,there occur an deadlock.

My program is this:

#include <stdio.h> 
#include <unistd.h> 
#include <sys/wait.h> 
#include <sys/types.h> 
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <sys/file.h>

int writeSomeStuffToFifo ();
void printAllFifo ();

char * myfifo = "myfifo";

int main(int argc, char **argv) { 

    int pid=0;
    int childPid=-1;
    int status;
    pid=fork();


    if ((pid = fork()) < 0){
        perror("fork() error");
    }
    else if (pid == 0) {
        writeSomeStuffToFifo ();
        exit(1);
    }
    else do {
        if ((pid = waitpid(pid, &status, WNOHANG)) == -1)
           perror("wait() error");
        else if (pid == 0) {
            //child running
            printf("child running\n");
        }
        else {
            if (WIFEXITED(status)){
                printf("child is terminated\n");
                printAllFifo();
            }
            else{ 
                printf("child did not exit successfully\n");
            }
        }
    } while (pid == 0);


    return 0;
}


int writeSomeStuffToFifo (){   //child process will run this function
    int fd;
    mkfifo(myfifo, 0666); 

    fd = open(myfifo, O_WRONLY);
    write(fd,"foo1\n",strlen("foo1\n"));
    close(fd);

    fd = open(myfifo, O_WRONLY);
    write(fd,"foo2\n",strlen("foo2\n"));
    close(fd);

    fd = open(myfifo, O_WRONLY);
    write(fd,"foo3\n",strlen("foo3\n"));
    close(fd);
}


void printAllFifo (){     //parent process will run this function
    int fd=open(myfifo, O_RDONLY);
    char* readBuffer=(char*)malloc((strlen("foo1\n")+strlen("foo2\n")+strlen("foo3\n"))*sizeof(char));
    read(fd, readBuffer, strlen("foo1\n")+strlen("foo2\n")+strlen("foo3\n"));
    printf("%s\n",readBuffer );
    close(fd);
}

回答1:

mkfifo() creates a pipe of limited size. You should not wait in the parent process until the child has finished in order to read, you should read constantly in the parent process while checking if the child has terminated already.

You can use ulimit -p in order to read the default size of pipes in your linux system. The number is multiplications of 512, so a value of 8 means 4096 bytes.

Using pipe() is more suited to the task than mkfifo() because you do not actually need a named pipe. this will provide you with 2 fds, one for read and one for write. In the parent code you close the write fd, in the child code you close the read fd, then you can start reading from the pipe in the parent code until it returns a value <= 0. This would mean that the child process has terminated (and the pipe was closed for writing). then you only need to call waitpid() from the parent code to collect the terminated child process.