Как проверить, открыт ли stdin по-прежнему без блокировки?



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



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



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



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



P.S. данные не предполагаются, но могут поступать в stdin. Способ неблокирующего считывания would быть ответом на вопрос.
616   5  

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() определенно выполнят эту работу.

Что не так с feof(stdin) ?

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

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

Comments

    Ничего не найдено.