2009-06-10 1 views
9

Вот example, чтобы проиллюстрировать, что я имею в виду:Зачем мне нужно закрывать fds при чтении и записи на трубу?

#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); 

}

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

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

+0

Я думаю, что ты нужна блокировка, тогда вы можете «заблокировать трубу», когда один процесс ее использует. Когда все процессы выполняются с помощью одного из них, он закрывает его. – Skurmedel

+0

Они не будут работать с трубой в течение всего времени программы. – 2009-06-10 14:47:34

+1

Хорошо. Затем завершается последний финишный процесс: либо вы открываете тонны труб, либо синхронизируете доступ к одной трубе. – Skurmedel

ответ

23

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

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

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

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

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

+0

У меня только один читатель - родительский и один писатель - дочерний поток. – 2009-06-10 15:30:04

+4

Если вы находитесь в потоковой среде, то файловые дескрипторы разделяются различными потоками. Поэтому в этих обстоятельствах НЕ закрывайте кончик чтения/записи трубы до тех пор, пока вы не закончите полностью, иначе труба закроется. Теперь я понимаю вопрос - когда труба охватывает процессы, закрывайте нежелательные концы, когда труба охватывает потоки (внутри процесса), поэтому не закрывайте нежелательные концы. – Beano

11

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

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

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

+0

Немного разъяснений, я не создайте процессы, но поток, и я передаю конец записи в поток, чтобы использовать для записи – 2009-06-10 14:56:59

+0

. Почему вы fork тогда? fork не создает потоки, он создает дочерние процессы. – qrdl

+0

Это был просто пример. отдельный поток от процессов. – 2009-06-10 15:27:56

0

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

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

+0

У меня только один читатель - родительский и один писатель - дочерний поток – 2009-06-10 15:28:59

0

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

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

Я надеюсь, что я понимаю, право запроса.

0

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

Смежные вопросы