Что вызывает зависание моей программы и ее неправильное завершение? (труба, чтение системного вызова, пока цикл)

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

for (i = 0; i < MAXP; i++) {
    if(id == i) {
        while(read(pfds[i][0], buf, sizeof(buf)) > 0)
             printf("process%d has received a message from %s\n",i,buf);    
    }
}

Однако с помощью следующего кода программа завершает работу корректно, но не печатает все сообщения (так как они не все прочитаны):

for (i = 0; i < MAXP; i++) {
    if(id == i) {
        nbytes = read(pfds[i][0], buf, sizeof(buf));
        printf("process%d has received a message from %s\n",i,buf); 
    }
}

Это мой код записи в каналы:

write(pfds[j][1],msg,9);  // write the message to j pipe

и сообщение:

sprintf(msg, "process%d", i); // create the message - 9 bytes (inc. null term)
// the message is "process0" or "process1" ... through "process8"

который является 9-байтовым массивом символов:

char msg[9];

Решение

for (j = 0; j < MAXP; j++) {
    close(pfds[j][1]); // close write to j from i
}

2 ответа

Решение

Может б / к ты не закрыл трубу? если конец записи не закрыт, чтение продолжит зависать

Попытка добавления

close(pfds[j][1]);

после того, как вы напишите свои сообщения в трубу

read(fd) (где fd конец чтения канала) вернет только 0 когда все концы записи для канала были закрыты.

Обратите внимание, что fork()-ing будет дублировать все дескрипторы открытых файлов. Итак, это:

int fd[2];
pipe(fd);
if (fork() == 0) {
  write(fd[1], "abc", 3);
  close(fd[1]);
} else {
  char buf[100];
  while (read(fd[0], buf, 100) > 0) {
    // ...
  }
}

вызовет бесконечный цикл (потому что fd[1] все еще открыт в родительском процессе), пока это:

int fd[2];
pipe(fd);
if (fork() == 0) {
  write(fd[1], "abc", 3);
  close(fd[1]);
} else {
  close(fd[1]);

  char buf[100];
  while (read(fd[0], buf, 100) > 0) {
    // ...
  }
}

должен прекратить.

Другие вопросы по тегам