C Именованная труба (fifo). Родительский процесс застревает - PullRequest
1 голос
/ 29 мая 2010

Я хочу сделать простую программу, эту ветвь, и потомок пишет в именованный канал, а родитель читает и отображает из именованного канала. Проблема в том, что он входит в родительский объект, выполняет первый printf, а затем становится странным, он больше ничего не делает, не попадает во второй printf, это просто способы ввода в консоли.

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void main()
{
char t[100];
mkfifo("myfifo",777);
pid_t pid;
pid = fork();
if (pid==0)
{
    //execl("fifo2","fifo2",(char*)0);
    char r[100];
    printf("scrie2->");
    scanf("%s",r);

    int fp;
    fp = open("myfifo",O_WRONLY);
    write(fp,r,99);
    close(fp);
    printf("exit kid \n");
    exit(0);
} else
{
    wait(0);
    printf("entered parent \n"); // <- this it prints
    // whats below this line apparently its not being executed
    int fz; printf("1"); 
    fz = open("myfifo",O_RDONLY); printf("2");
    printf("fd: %d",fz);
    char p[100];
    int size;
    printf("------");
    //struct stat *info;
    //stat("myfifo",info); printf("%d",(*info).st_size);
    read(fz,p,99);
    close(fz);
    printf("%s",p);

    printf("exit"); exit(0);
}
}

Ответы [ 2 ]

5 голосов
/ 29 мая 2010

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

Ваш звонок на wait() вызовет проблемы в его текущем местоположении. Открытие FIFO для чтения обычно блокирует, пока какой-то другой процесс не откроет тот же FIFO для записи, и наоборот 1 . Родитель ожидает завершения дочернего процесса, а ребенок ожидает, пока процесс чтения, то есть родитель, подключится к FIFO.

1 - см. Примечание на open() ниже относительно использования O_NONBLOCK с FIFO

Перемещение вызова wait() непосредственно перед выходом из родительского процесса вместе с изменением режима вызова на mkfifo() на 0666, кажется, решает некоторые из ваших непосредственных проблем.

Хорошей практикой также является удаление FIFO, когда вы закончите с ним.

unlink("myfifo");

Из документации по функциям open() в стандарте IEEE 1003.1-2004 :

При открытии FIFO с установленным O_RDONLY или O_WRONLY:

  • Если установлено O_NONBLOCK, open () только для чтения должен возвращаться без задержки. Функция open () только для записи должна возвращать ошибку, если ни один процесс не имеет файла, открытого для чтения.

  • Если O_NONBLOCK очищен, метод open () только для чтения должен блокировать вызывающий поток, пока поток не откроет файл для записи. Функция open () только для записи должна блокировать вызывающий поток, пока поток не откроет файл для чтения.


Следующий пример представляет собой комбинацию кода в исходном вопросе и страницы FIFO Руководства Beej по Unix IPC :

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

#define FIFO_NAME "myfifo"

int main(void)
{
    char buf[256];
    int num, fd;
    pid_t pid;

    if (mkfifo(FIFO_NAME, 0666) < 0)
        perror("mkfifo");

    pid = fork();
    if (pid == 0)
    {
        printf("child - waiting for readers...\n");
        if ((fd = open(FIFO_NAME, O_WRONLY)) < 0)
            perror("child - open");

        printf("child - got a reader -- type some stuff\n");
        while (fgets(buf, sizeof(buf), stdin), !feof(stdin))
        {
            if ((num = write(fd, buf, strlen(buf))) < 0)
                perror("child - write");
            else
                printf("child - wrote %d bytes\n", num);
        }

        close(fd);
        exit(0);
    }
    else
    {
        printf("parent - waiting for writers...\n");
        if ((fd = open(FIFO_NAME, O_RDONLY)) < 0)
            perror("parent - open");

        printf("parent - got a writer\n");
        do
        {
            if ((num = read(fd, buf, sizeof(buf))) < 0)
                perror("parent - read");
            else
            {
                buf[num] = '\0';
                printf("parent - read %d bytes: \"%s\"\n", num, buf);
            }
        } while (num > 0);

        close(fd);
        wait(0);
    }

    unlink(FIFO_NAME);
    return 0;
}

Этот пример был протестирован в Linux. Нажмите Ctrl - D , чтобы завершить программу.

3 голосов
/ 29 мая 2010

Прежде всего, попробуйте fprintf для stderr вместо printf (для stdout)

Stderr не буферизован.

Тогда вы можете сказать, что на самом деле печатается, а что нет.

или хотя бы добавьте fflush перед тем, как что-либо ждать.

...