Чтение из двух каналов до бесконечности, а затем печать на стандартный вывод в C - PullRequest
1 голос
/ 21 ноября 2011

У меня есть два канала, которые оба получают разные данные в случайных точках.Я хочу напечатать содержимое из обоих каналов на stdout .

              __________________
   pipe1     |                  |
]==============>               -----------.
             |                  |          \
             |     process1     |           -----> stdout
   pipe2     |                  |          /
]==============>               -----------´
             |__________________|

Мой код выглядит так в процессе1:

while (1) {
  read(pipe1[0], &buff, sizeof(char));  
  write(1, &buff, sizeof(char));
  read(pipe2[0], &buff2, sizeof(char)); 
  write(1, &buff2, sizeof(char));
}

Однако это не такРаботать так, как один read() может быть заблокирован (если данные не поступают), когда данные поступают из другого канала.

Как можно распечатать одновременно из обоих каналов, не блокируя в одномтруба?Или любое другое предложение о том, как решить эту проблему, приветствуется.

Ответы [ 2 ]

3 голосов
/ 21 ноября 2011

Используйте select для ожидания на обоих сокетах. Когда данные будут готовы, вам сообщат, по каким каналам есть данные.

void setnonblocking(int fd) {
    int opts;

    opts = fcntl(fd,F_GETFL);
    if (opts < 0) {
        perror("Couldn't get file descriptor flags");
        exit(EXIT_FAILURE);
    }
    opts = (opts | O_NONBLOCK);
    if (fcntl(fd,F_SETFL,opts) < 0) {
        perror("Couldn't set file descriptor to non-blocking");
        exit(EXIT_FAILURE);
    }
    return;
}

#ifndef BUFSIZE
#  define BUFSIZE 1024
#endif
void cat(fd_set* waiting, int fd) {
   static char buf[BUFSIZE];

   int readCnt;
   if (FD_ISSET(fd, waiting)) {
       while ((readCnt = read(fd, buf, BUFSIZE)) > 0) {
           write(stdout, buf, readCnt);
       }
       if (readCnt < 0) {
           perror("Error reading from pipe");
       }
   }
}

...
{
    fd_set pipes, readable;

    setnonblocking(pipes1[0]);
    setnonblocking(pipes2[0]);

    FD_ZERO(&pipes);
    FD_SET(pipe1[0],&pipes);
    FD_SET(pipe2[0],&pipes);

    int ready;
    while (1) {
        if ((ready = select(2, &pipes, NULL, NULL, NULL)) > 0) {
            cat(&pipes, pipe1[0]);
            cat(&pipes, pipe2[0]);
        } else {
            // no time limit, so there was an error
            perror("Error waiting for input");
            exit(EXIT_FAILURE);
        }
        FD_SET(pipe1[0],&pipes);
        FD_SET(pipe2[0],&pipes);
    }
}

Обратите внимание, что вышеописанное работает вечно, если только нет ошибки. Вы, вероятно, захотите, чтобы ваша программа остановилась в какой-то момент.

2 голосов
/ 21 ноября 2011

Вам необходимо мультиплексировать входы.Соответствующий системный вызов: poll или select (или ppoll или pselect).Полезно прочитать учебник .

...