Nano Hash - криптовалюты, майнинг, программирование

Как проверить, открыт ли стандартный ввод без блокировки?

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

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

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

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

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

20.10.2009

Ответы:


1

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), чтобы получить файловый дескриптор стандартного ввода:

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

  • 2

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

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

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

    05.07.2012

    3

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

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

  • 4

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

    20.10.2009
  • Это не сработает, если вы не прочитаете все данные. Как прочитать все данные (например, мусор) без блокировки операций? 20.10.2009
  • EOF можно внедрить в открытый стандартный ввод (например, через Ctrl-D в Linux). Это не означает, что стандартный ввод закрыт. 15.04.2017

  • 5

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

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

    20.10.2009
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..