Вопрос по nonblocking, c, stdin, stream – Как проверить, открыт ли stdin без блокировки?

9

Мне нужна моя программа, написанная на чистом C, чтобы остановить выполнение, когда stdin закрыт.

В основном цикле программы выполняется неопределенная работа, и я не могу использовать блокирующие проверки (например,getc()) (данные не должны поступать на стандартный ввод данных - он остается открытым в течение неизвестного времени).

Я намереваюсь использовать описанную функциональность при реализации сетевого демона, размещенного в inetd, xinetd или их аналогах - он должен выдавать данные на стандартный вывод, пока соединение остается открытым, и корректно завершать работу после его закрытия. Теперь моя программа убита хостингом, так как она выигралаt останавливаться после прекращения соединения.

Интересно, еслиfctntl() сO_NONBLOCK флаг, примененный к дескриптору стандартного ввода, позволит мне использоватьread() функционировать в неблокирующем режиме? Должен ли я использоватьselect() каким-то образом?

Постскриптум Данные не предполагаются, но могут поступать в стандартный ввод данных. Способ неблокирующего считывания мог бы стать ответом на этот вопрос.

Ваш Ответ

5   ответов
1

можете ли вы установить O_NONBLOCK на стандартный ввод, ноselect() или жеpoll() определенно выполню работу

Да, вы можете установить O_NONBLOCK на стандартный ввод. Если ваш stdin передан из другой программы, эта программа может не справиться с тем, что ее дескриптор исходящего файла становится неблокирующим. ephemient
0

select (с нулевым таймаутом). Ты неt необходимо установить неблокирующий дескриптор файла, хотя - еслиselect сообщает, что файловый дескриптор доступен для чтения, а затемread на нем точно не будет блокады.

Итак, дескриптор файла опроса 0 иногдаselectи если эточитабельно,read Это. Еслиread возвращает 0, то это значит, чтобыл закрыт.

2

позволит ли функция fctntl () с флагом O_NONBLOCK, примененной к дескриптору стандартного ввода, использовать функцию read () в неблокирующем режиме?

Запуск stdin с O_NONBLOCK имеет преимущества перед select. Select говорит, что есть некоторые данные, но не сколько. Есть моменты, когда вы хотите получить все доступные данные, но не блокировать, независимо от того, сколько в очереди. Запуск выбора для каждого персонажа кажется большой работой ... O_NONBLOCK не сработал для меня. Это внутренний флаг, не показанный в большинстве драйверов tty.

Проверьте ioctl (..., FIONBIO). Похоже, работа сделана.

7

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

#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_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;
}
</sys></stdio.h>

Теперь вы можете проверить дескриптор файла перед использованием, например, чтобы очистить дескриптор файла:

void empty_fd(int fd) {
    char buffer[1024];
    while (is_ready(fd)) {
        read(fd, buffer, sizeof(buffer));
    }
}

В вашем случае используйтеfileno (STDIN) чтобы получить файловый дескриптор стандартного ввода:

if (is_ready(fileno(stdin))) {
    /* read stuff from stdin will not block */
}
poll это именно то, что хочет OP, и его интерфейс немного проще, чемselect при работе с небольшим фиксированным набором файловых дескрипторов. ephemient
0

feof(stdin)

Что выигралне работает, если ты неt прочитать все данные. Как мне прочитать все данные (например, корзину), не блокируя операции? Basilevs
EOF может быть введен в открытый ввод (например, через Ctrl-D в Linux). Это неЭто означает, что стандартный ввод закрыт. Kerrek SB

Похожие вопросы