Неблокирующая труба с использованием popen? - PullRequest
17 голосов
/ 15 ноября 2009

Я бы хотел открыть канал, используя popen() и получить неблокируемый доступ к нему для чтения.

Как мне этого добиться?

(все примеры, которые я нашел, были блокирующими / синхронными)

Ответы [ 4 ]

27 голосов
/ 15 ноября 2009

Настроить так:

FILE *f = popen("./output", "r");
int d = fileno(f);
fcntl(d, F_SETFL, O_NONBLOCK);

Теперь вы можете читать:

ssize_t r = read(d, buf, count);
if (r == -1 && errno == EAGAIN)
    no data yet
else if (r > 0)
    received data
else
    pipe closed

Когда вы закончите, очистите:

pclose(f);
6 голосов
/ 15 ноября 2009

popen() внутренне вызывает pipe(), fork(), dup2() (чтобы указать fds 0/1/2 дочернего процесса на каналы) и execve(). Рассматривали ли вы использовать их вместо этого? В этом случае вы можете установить канал, который вы читаете, как неблокирующий, используя fcntl().

update : Вот пример, только для иллюстрации:

int read_pipe_for_command(const char **argv)
{
   int p[2];

   /* Create the pipe. */
   if (pipe(p))
   {
      return -1;
   }

   /* Set non-blocking on the readable end. */
   if (fcntl(p[0], F_SETFL, O_NONBLOCK))
   {
      close(p[0]);
      close(p[1]);
      return -1;
   }

   /* Create child process. */
   switch (fork())
   {
      case -1:
          close(p[0]);
          close(p[1]);
          return -1;
      case 0:
          /* We're the child process, close read end of pipe */
          close(p[0]);
          /* Make stdout into writable end */
          dup2(p[1], 1);
          /* Run program */
          execvp(*argv, argv);
          /* If we got this far there was an error... */
          perror(*argv);
          exit(-1);
      default:
          /* We're the parent process, close write end of pipe */
          close(p[1]);
          return p[0];
   }
}
2 голосов
/ 15 ноября 2009

Никогда не пробовал, но я не понимаю, почему вы не можете получить дескрипторы файлов с помощью fileno (), использовать fcntl (), чтобы установить неблокирование, и использовать read () / write (). Стоит попробовать.

0 голосов
/ 15 ноября 2009

Вы просматривали раздел "см. Также" на странице руководства для popen ()?

Быстрый поиск в Google показал эту страницу: http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#blocking Рассказывает о блокировании и неблокировании доступа к файловым дескрипторам.

...