чтение из именованных каналов в linux vs OS X

Программа ниже хорошо работает под OS X, но не в Linux. Он продолжает прокручивать строку perror («read error»), без байтов в буфере чтения, а EWOULDBLOCK не является errno (errno = 0);

В OS X программа работает так, как ожидалось, что она читает из трех именованных каналов и выводит любые данные из любого из них на консоль.

#include  #include  #include  #include  #include  #include  #include  #include  #include  int readPipe(int fd) { ssize_t bytes; size_t total_bytes = 0; char buffer[100*1024]; printf("\nReading pipe descriptor # %d\n",fd); for(;;) { bytes = read(fd, buffer, sizeof(buffer)); if (bytes > 0) { total_bytes += (size_t)bytes; printf("%s", buffer); } else { if (errno == EWOULDBLOCK) { break; // recieve buffer is empty so return to main loop } else { perror("read error"); return EXIT_FAILURE; } } } return EXIT_SUCCESS; } int main(int argc, char* argv[]) { int fd_a, fd_b, fd_c; // file descriptors for each pipe int nfd; // select() return value fd_set read_fds; // file descriptor read flags struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 10000; // create pipes to monitor (if they don't already exist) system("mkfifo /tmp/PIPE_A"); system("mkfifo /tmp/PIPE_B"); system("mkfifo /tmp/PIPE_C"); system("chmod 666 /tmp/PIPE_*"); // open file descriptors of named pipes to watch fd_a = open("/tmp/PIPE_A", O_RDONLY | O_NONBLOCK); // the O_RDWR flag is undefined on a FIFO. if (fd_a == -1) { perror("open error"); return EXIT_FAILURE; } fd_b = open("/tmp/PIPE_B", O_RDONLY | O_NONBLOCK); if (fd_b == -1) { perror("open error"); return EXIT_FAILURE; } fd_c = open("/tmp/PIPE_C", O_RDONLY | O_NONBLOCK); if (fd_c == -1) { perror("open error"); return EXIT_FAILURE; } // check for new data in each of the pipes for(;;) { // clear fds read flags FD_ZERO(&read_fds); // PIPE_A FD_SET(fd_a, &read_fds); nfd = select(fd_a+1, &read_fds, NULL, NULL, &tv); if (nfd != 0) { if (nfd == -1) { perror("select error"); return EXIT_FAILURE; } if (FD_ISSET(fd_a, &read_fds)) { readPipe(fd_a); } } // PIPE_B FD_SET(fd_b, &read_fds); nfd = select(fd_b+1, &read_fds, NULL, NULL, &tv); if (nfd != 0) { if (nfd == -1) { perror("select error"); return EXIT_FAILURE; } if (FD_ISSET(fd_b, &read_fds)){ readPipe(fd_b); } } // PIPE_C FD_SET(fd_c, &read_fds); nfd = select(fd_c+1, &read_fds, NULL, NULL, &tv); if (nfd != 0) { if (nfd == -1) { perror("select error"); return EXIT_FAILURE; } if (FD_ISSET(fd_c, &read_fds)){ readPipe(fd_c); } } } return EXIT_SUCCESS; } 

Допускается (и ожидается), что чтение может вернуть 0. Это означает, что труба возвращает EOF. Вы не выполняете это условие. Содержимое errno не имеет значения, если вызов не выполняется и возвращает -1.

 for (;;) { bytes = read(fd, buffer, sizeof(buffer)); if (bytes > 0) { total_bytes += (size_t)bytes; printf("%s", buffer); } if (bytes == 0) return //something appropriate if (bytes == -1) { if (errno == EWOULDBLOCK) break; // recieve buffer is empty so return to main loop else { perror("read error"); return EXIT_FAILURE; } } } 

Вы пытаетесь вернуть разные коды, но вы не обращаете на них внимания в main .

Кроме того, что происходит с тремя select ? Я думал, что это было выяснено в предыдущем вопросе.

редактировать

 for (;;) { // clear fds read flags FD_ZERO(&read_fds); FD_SET(fd_a, &read_fds); FD_SET(fd_b, &read_fds); FD_SET(fd_c, &read_fds); tv.tv_sec = 0; tv.tv_usec = 10000; nfd = select(fd_c + 1, &read_fds, NULL, NULL, &tv); if (nfd == 0) //timeout - continue or do something else for a bit continue; if (nfd == -1) { perror("select error"); return EXIT_FAILURE; } if (FD_ISSET(fd_a, &read_fds)) readPipe(fd_a); if (FD_ISSET(fd_b, &read_fds)) readPipe(fd_b); if (FD_ISSET(fd_c, &read_fds)) readPipe(fd_c); }