Закрытие неиспользуемого конца в трубах

avatar
Arka Pal
8 апреля 2018 в 06:22
1385
2
2

Я читал о каналах в своем курсе по операционной системе и писал код, чтобы лучше понять его. У меня есть сомнения относительно следующего кода:

int fd[2];              // CREATING PIPE
pipe(fd);
int status;

int pid=fork();
if(pid==0)
{
     // WRITER PROCESS

    srand(123);
    int arr[3]={1,2,3};

    close(fd[0]);                   // CLOSE UNUSED(READING END)
    for(int i=0;i<3;i++)
      write(fd[1],&arr[i],sizeof(int));
    close(fd[1]);                   // CLOSE WRITING END AFTER WRITING SO AS READ GETS THE EOF
}
else
{
    // READER PROCESS

    int arr[10];

    int  i=0;
    int n_bytes;
    //close(fd[1]);                   // CLOSE UNUSED(WRITING END)
    while((n_bytes=read(fd[0],&arr[i],sizeof(int)))>0)        // READIN IN A LOOP UNTIL END
        i++;
    close(fd[0]);                   // CLOSE READING END after reading
    for(int j=0;j<i;j++)
        cout<<arr[j]<<endl;
    while(wait(&status)>0)
       ;
}

Если я запускаю это, чтение блокируется, если я раскомментирую команду close(fd[1]) в процессе чтения, код работает нормально. Это означает, что close(fd[1]) закрывает конец записи, и чтение может продолжаться.

Я сомневаюсь, что даже если я не закрываю конец записи в процессе чтения, он закрывается в конце процесса записи. Так почему же по-прежнему блокируется системный вызов чтения?

Источник

Ответы (2)

avatar
Miles Budnek
8 апреля 2018 в 06:32
4

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

ОС закроет конец канала только тогда, когда все открытые файловые дескрипторы для него будут закрыты, поэтому, если вы не вызовете close(fd[1]) в дочернем процессе, один файловый дескриптор останется открытым, а конец записи канал не будет закрыт, и read заблокируется в ожидании ввода, который никогда не придет.

avatar
Some programmer dude
8 апреля 2018 в 06:29
0

Две проблемы:

Во-первых, из-за приоритета оператора условие цикла n_bytes=read(fd[0],&arr[i],sizeof(int))>0 действительно равно n_bytes = (read(fd[0],&arr[i],sizeof(int)) > 0). То есть вы присваиваете значение сравнения переменной n_bytes. Чтобы исправить это, добавьте дополнительные круглые скобки вокруг присвоения, например (n_bytes=read(fd[0],&arr[i],sizeof(int)))>0.

.

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