Как предотвратить блокировку fgets, когда в файловом потоке нет новых данных

У меня есть функция popen(), которая выполняет tail -f sometextfile. Пока в файловом потоке есть данные, очевидно, я могу получить данные через fgets(). Теперь, если из хвоста не приходят новые данные, fgets() зависает. Я пробовал ferror() и feof() безрезультатно. Как я могу убедиться, что fgets() не пытается прочитать данные, когда в файловом потоке нет ничего нового?

Одним из предложений было select(). Поскольку это для платформы Windows, выбор не работает, поскольку анонимные каналы, похоже, не работают для нее (см. это сообщение).


person SinisterDex    schedule 29.09.2008    source источник


Ответы (5)


В Linux (или любой ОС Unix-y) вы можете пометить базовый файловый дескриптор, используемый popen(), как неблокирующий.

#include <fcntl.h>

FILE *proc = popen("tail -f /tmp/test.txt", "r");
int fd = fileno(proc);

int flags;
flags = fcntl(fd, F_GETFL, 0);
flags |= O_NONBLOCK;
fcntl(fd, F_SETFL, flags);

Если нет доступных входных данных, fgets вернет NULL с errno, установленным в EWOULDBLOCK.

person DGentry    schedule 29.09.2008

fgets() — чтение с блокировкой, предполагается ожидание доступности данных, если данных нет.

Вы захотите выполнить асинхронный ввод-вывод, используя select(), poll() или epoll(). А затем выполните чтение из файлового дескриптора, когда будут доступны данные.

Эти функции используют файловый дескриптор дескриптора FILE*, полученный с помощью: int fd = fileno(f);

person Sufian    schedule 29.09.2008
comment
Обязательно используйте select() — если у вас есть ФАЙЛ * и вам нужен файловый дескриптор, используйте fileno(). Если у вас есть файловый дескриптор и вам нужен ФАЙЛ *, используйте fdopen(). - person plinth; 29.09.2008
comment
К сожалению, я думаю, что select() не работает с каналами под Windows. - person Roddy; 30.09.2008
comment
Смешивать select() и fgets() опасно. FILE* содержит внутренние буферы, о которых select() не знает. Правильный ответ O_NONBLOCK. - person Alcaro; 25.06.2019

я решил свои проблемы с помощью потоков, в частности _beginthread , _beginthreadex.

person SinisterDex    schedule 01.10.2008
comment
Если вы ответили на свой вопрос, установите его как ответ и, возможно, опубликуйте свое решение. - person Jared Burrows; 25.12.2013

Вместо этого вы можете попробовать прочитать какой-нибудь текстовый файл, используя низкоуровневые функции ввода-вывода (open(), read() и т. д.), как это делает сам хвост. Когда читать больше нечего, read() возвращает ноль, но в следующий раз все равно попытается прочитать больше, в отличие от функций FILE*.

person Lev    schedule 29.09.2008
comment
это был просто пример. идея состоит в том, чтобы извлекать данные и передавать их через объект мьютекса во флэш-экземпляр. - person SinisterDex; 29.09.2008

Если бы вы использовали функции POSIX для ввода-вывода вместо функций библиотеки C, вы могли бы использовать select или опрос.

person Kasprzol    schedule 29.09.2008