Как родительский процесс читает FIFO после того, как дочерний процесс завершил запись этого FIFO? - PullRequest
0 голосов
/ 28 марта 2019

У меня есть очень простая базовая программа, в которой есть два процесса: первый - parent, а второй - child.

Дочерний процесс должен записать некоторые вещи в FIFO. После того, как все письменные задания закончены (после того, как ребенок уволен). Затем родительский процесс должен прочитать весь файл FIFO и распечатать его на stdout.

Так что я думаю, мне нужно wait(NULL); для parent. Таким образом, parent будет ждать, пока child не будет завершен. Но child также заблокирован из-за записи и заблокирован для чтения этой записи. Так что оба процесса ждут друг друга и я думаю, что возникает тупик.

Моя программа такая:

#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 Ответ

3 голосов
/ 28 марта 2019

mkfifo() создает трубу ограниченного размера. Вы не должны ждать в родительском процессе, пока дочерний процесс не закончил, чтобы читать, вы должны постоянно читать в родительском процессе, проверяя, завершился ли дочерний процесс уже.

Вы можете использовать ulimit -p, чтобы прочитать размер каналов по умолчанию в вашей системе Linux. Число умножается на 512, поэтому значение 8 означает 4096 байт.

Использование pipe() больше подходит для задачи, чем mkfifo(), потому что на самом деле вам не нужен именованный канал. это даст вам 2 fds, один для чтения и один для записи. В родительском коде вы закрываете запись fd, в дочернем коде вы закрываете чтение fd, затем вы можете начать чтение из канала в родительском коде, пока он не вернет значение <= 0. Это будет означать, что дочерний процесс завершился (и труба была закрыта для записи). тогда вам нужно всего лишь вызвать <code>waitpid() из родительского кода, чтобы собрать завершенный дочерний процесс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...