UNIX FIFO: процесс зависает, если я не закрываю входную сторону fifo - PullRequest
1 голос
/ 12 января 2011

Я только начал работать с UNIX FIFO и обнаружил кое-что, экспериментируя с моей первой программой FIFO. Программа работает следующим образом: после создания FIFO два процесса запускаются с использованием функции fork(). Дочерний процесс читает то, что отец передает ему через FIFO, и печатает это на экране. Обмениваемые данные - это строка, указанная в качестве аргумента. Вопрос в том, что в родительском разделе, если я забуду закрыть входную сторону FIFO (это означает, что я исключаю строку close(fd)), программа просто зависнет, даже если обмен данными между процессами происходит правильно. В противном случае все работает нормально, и программа завершается без зависания. Может кто-нибудь объяснить, почему?

Спасибо за ваше терпение. Вот код основной функции:

int main(int argc, char *argv[])
{
    if(argc != 2)
    {
        printf("An argument must be specified\n");
        return -1;
    }   

    int ret = mkfifo("./fifo.txt", 0644);
    char buf;

    if(ret < 0)
    {
        perror("Error creating FIFO");
        return -1;
    }

    pid_t pid = fork();

    if(pid < 0)
    {
        perror("Error creating child process");
        return -1;
    }

    if(pid == 0) /* child */
    {
        int fd = open("./fifo.txt", O_RDONLY); /* opens the fifo in reading mode */

        while(read(fd, &buf, 1) > 0)
        {
            write(STDOUT_FILENO, &buf, 1);
        }
        write(STDOUT_FILENO, "\n", 1);
        close(fd);
        return 0;
    }
    else /* father */
    {
        int fd = open("./fifo.txt", O_WRONLY); /* opens the fifo in writing mode */

        write(fd, argv[1], strlen(argv[1]));
        close(fd);
        waitpid(pid, NULL, 0);
        return 0;
    }
}

Ответы [ 2 ]

5 голосов
/ 12 января 2011

read(2) блоков, пока не появятся доступные символы или канал не будет закрыт на другом конце. Процесс-отец должен закрыть канал, чтобы последний потомок read() вернулся. Если вы опустите close(fd) в отце, ребенок будет блокироваться в read() до тех пор, пока отец не выйдет (автоматически закроет трубу), но отец будет висеть в waitpid(), пока ребенок не выйдет.

0 голосов
/ 12 января 2011

Перво-наперво: есть несколько проблем с кодом, который вы опубликовали.

  1. Нет директив #include, следовательно, нет прототипов в области действия для любой из функций, которые вы вызываете.C89 требует прототипов для функций с переменным числом, таких как printf();C99 требует прототипов для всех функций.И для C89, и для C99 требуются объявления в области видимости для O_RDONLY, O_WRONLY, STDOUT_FILENO и NULL.
  2. -1 - недопустимое возвращаемое значение для main().
  3. C89 не позволяет смешивать объявления и заявления.

Незначительная гнида: обычная номенклатура - "родитель и ребенок", а не "отец и ребенок".

Я изменил вашПрограмма для исправления этой проблемы и улучшения читабельности:

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>

#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int
main(int argc, char *argv[])
{
    if (argc != 2) {
        printf("An argument must be specified\n");
        return 1;
    }

    int ret = mkfifo("./fifo.txt", 0644);
    char buf;

    if (ret < 0) {
        perror("Error creating FIFO");
        return 1;
    }

    pid_t pid = fork();

    if (pid < 0) {
        perror("Error creating child process");
        return 1;
    }

    if (pid == 0) { /* child */
        int fd = open("./fifo.txt", O_RDONLY); /* opens the fifo in reading mode */

        while(read(fd, &buf, 1) > 0) {
            write(STDOUT_FILENO, &buf, 1);
        }
        write(STDOUT_FILENO, "\n", 1);
        close(fd);
        return 0;
    } else { /* parent */
        int fd = open("./fifo.txt", O_WRONLY); /* opens the fifo in writing mode */

        write(fd, argv[1], strlen(argv[1]));
        close(fd);
        waitpid(pid, NULL, 0);
        return 0;
    }
}

Но самое главное, вы не упомянули, какую операционную систему и компилятор вы используете.

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

...