Как проверить, открыт ли stdin по-прежнему без блокировки?
Мне нужно, чтобы моя программа, написанная на чистом языке Си, останавливала выполнение при закрытии stdin.
В основном цикле программы выполняется неопределенная работа, и я никак не могу использовать блокирующие проверки (например, getc()) (данные не должны поступать на stdin - он просто остается открытым в течение неизвестного времени).
Я намерен использовать описанную функциональность в реализации сетевого демона, размещенного в inetd, xinetd или их аналогах - он должен выдавать данные на stdout, пока соединение остается открытым и корректным. закончите работу, когда она закроется. Теперь моя программа убита хостингом, так как она не остановится после завершения соединения.
Интересно, если fctntl() с флагом O_NONBLOCK, примененным к дескриптору stdin, позволит мне использовать функцию read() в неблокирующем режиме? Должен ли я как-то использовать select()?
P.S. данные не предполагаются, но могут поступать в stdin. Способ неблокирующего считывания would быть ответом на вопрос.
5 ответов:
Select () делает именно то, что вы хотите: сигнализирует, что операция (чтение, в данном случае) на файловом дескрипторе (файл, сокет, что угодно) не будет заблокирована.
#include <stdio.h> #include <sys/select.h> int is_ready(int fd) { fd_set fdset; struct timeval timeout; int ret; FD_ZERO(&fdset); FD_SET(fd, &fdset); timeout.tv_sec = 0; timeout.tv_usec = 1; //int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); return select(fd+1, &fdset, NULL, NULL, &timeout) == 1 ? 1 : 0; }Теперь вы можете проверить файловый дескриптор перед использованием, например, чтобы очистить файловый дескриптор:
void empty_fd(int fd) { char buffer[1024]; while (is_ready(fd)) { read(fd, buffer, sizeof(buffer)); } }В вашем случае используйте fileno (stdin) , чтобы получить файловый дескриптор stdin:
if (is_ready(fileno(stdin))) { /* read stuff from stdin will not block */ }
Интересно, позволит ли fctntl () с флагом O_NONBLOCK, примененным к дескриптору stdin, использовать функцию read () в неблокирующем режиме?
Запуск stdin с O_NONBLOCK имеет преимущества перед select. Select говорит, что есть некоторые данные, но не сколько. Бывают случаи, когда вы хотите получить все доступные данные, но не блокировать, независимо от того, сколько в очереди. Запуск select для каждого персонажа кажется очень напряженной работой... O_NONBLOCK не работал на меня. Это внутренний флаг, не выставляемый в большинстве драйверов tty.
Проверьте ioctl(..., FIONBIO). Кажется, он справляется с работой.
Я не уверен, что вы можете установить O_NONBLOCK на stdin, но
select()илиpoll()определенно выполнят эту работу.
Да, вы можете использовать
select(с нулевым таймаутом). Вам не нужно устанавливать файловый дескриптор неблокирующим, хотя-еслиselectговорит вам, что файловый дескриптор читаем, тоreadна нем определенно не заблокируется.Итак, опросите файловый дескриптор 0 occaisionally с
select, и если он читаем,readего. Еслиreadвозвращает 0, то это означает, что он был закрыт.
Comments