Я хотел бы открыть трубку, используя popen()
и иметь неблокирующий доступ для чтения.Неблокирующая труба с использованием всплывающих окон?
Как я могу это достичь?
(примеры, которые я нашел, были все блокировки/синхронная)
Я хотел бы открыть трубку, используя popen()
и иметь неблокирующий доступ для чтения.Неблокирующая труба с использованием всплывающих окон?
Как я могу это достичь?
(примеры, которые я нашел, были все блокировки/синхронная)
Setup так:
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);
Вы смотрели на «смотри также» раздел страницы человека для POPEN()?
Быстрый поиск google выявил эту страницу: http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#blocking Говорит о блокировании и неблокирующем доступе к дескрипторам файлов.
Никогда не пробовал, но я не понимаю, почему вы не смогли захватить дескрипторы файла с помощью fileno(), используйте fcntl(), чтобы установить неблокирование, и используйте read()/write(). Стоит попробовать.
popen()
внутренне называет pipe()
, fork()
, dup2()
(указать FDS дочернего процесса 0/1/2 к трубам) и execve()
. Рассматривали ли вы их использование? В этом случае вы можете настроить канал, который вы считаете, неблокирующим, используя fcntl()
.
обновление: Вот пример, только для целей иллюстрации:
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 parent process, close the writable part of the pipe */
close(p[1]);
return p[0];
default:
/* Close readable 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);
}
}
Прекрасно работает ... спасибо! – jldupont
Труба, являющаяся указателем FILE, по сути буферизуется, есть ли уверенность в том, что, используя дескриптор файла напрямую, вы не пропустите что-то, что было вложено в буфер файлов, или это можно гарантировать, пока вы не 'сначала вызвать fget/fread/etc? – stu