Зачем мне закрывать fds при чтении и записи в канал? - PullRequest
9 голосов
/ 10 июня 2009

Вот пример , чтобы проиллюстрировать, что я имею в виду:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main(void)
{
        int     fd[2], nbytes;
        pid_t   childpid;
        char    string[] = "Hello, world!\n";
        char    readbuffer[80];

        pipe(fd);

        if((childpid = fork()) == -1)
        {
                perror("fork");
                exit(1);
        }

        if(childpid == 0)
        {
                /* Child process closes up input side of pipe */
                close(fd[0]);

                /* Send "string" through the output side of pipe */
                write(fd[1], string, (strlen(string)+1));
            exit(0);
    }
    else
    {
            /* Parent process closes up output side of pipe */
            close(fd[1]);

            /* Read in a string from the pipe */
            nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
            printf("Received string: %s", readbuffer);
    }

   return(0);

}

Однако, что если одному из моих процессов необходимо непрерывно записывать в канал, в то время как другому каналу нужно читать?

Кажется, что приведенный выше пример работает только для одной записи и одной операции чтения.

Ответы [ 5 ]

24 голосов
/ 10 июня 2009

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

если ваш канал охватывает процессы (т. Е. Создается перед fork (), а затем родитель и потомок используют его для связи), вы можете иметь одну запись и одну конец чтения. Тогда рекомендуется закрыть нежелательные концы трубы. Это будет

  • убедитесь, что когда конец записи закрывает канал, он виден концом чтения. В качестве примера, скажем, что ребенок - сторона записи, и она умирает. Если родительская сторона записи не была закрыта, то родительский элемент не получит «eof» (чтение нулевой длины ()) из канала - потому что канал имеет открытый конец записи.
  • дает понять, какой процесс выполняет запись, а какой - чтение в канале.

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

Ничто не мешает вам непрерывно записывать один процесс в канал, а другой - читать процесс. Если у вас возникла проблема, сообщите нам более подробную информацию.

11 голосов
/ 10 июня 2009

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

Помимо очевидного факта, что если вы не закроете дескрипторы, ОС сохранит дополнительные записи в таблице открытых файлов, если вы не закроете конец записи канала, читатель никогда не получит EOF, поскольку способ ввода данных в трубу. AFAIK (и IIRC) нет проблем в том, чтобы не закрывать чтение fd в другом процессе, то есть, кроме того, что файл открывается без причины.

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

0 голосов
/ 19 июля 2011

только для синхронизации, чтобы обеспечить атомарность операции

0 голосов
/ 11 июня 2009

"Пример выше работает только для одной записи и одной операции чтения."

Это потому, что после одного чтения и записи ваш код завершается. Вы должны продолжать писать в цикле и читать в цикле, чтобы добиться непрерывности. Кажется, это не имеет никакого отношения к закрытию FD. Как упоминалось в предыдущем ответе, вам нужен один конец для каждого процесса, чтобы другой был закрыт.

Надеюсь, я правильно понял вопрос.

0 голосов
/ 10 июня 2009

Канал не даст вам двунаправленный канал и не будет многоадресным. Канал только с двумя концами, у него нет одного конца записи и нескольких концов чтения.

Если вам нужно много читателей, вам нужно столько каналов, сколько у вас есть процесса чтения.

...