Неблокирующий вызов для чтения дескриптора - PullRequest
33 голосов
/ 11 апреля 2011

У меня есть дескриптор fd, с которого я могу читать, вызывая read(fd, buffer,...). Теперь я хочу проверить, есть ли что-то, что нужно прочитать, прежде чем делать вызов, потому что вызов блокируется. Как мне это сделать?

Ответы [ 7 ]

55 голосов
/ 11 апреля 2011
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);

Приведенный выше фрагмент кода настроит такой дескриптор для неблокирующего доступа.Если данные недоступны при вызове read, системный вызов завершится с ошибкой, возвращающим значение -1, и для errno будет установлено значение EAGAIN.Для получения дополнительной информации см. Справочные страницы fnctl .

В качестве альтернативы, вы можете использовать select с настраиваемым тайм-аутом для проверки и / или ожидания указанного интервала времени для получения дополнительных данных.,Этот метод, вероятно, то, что вы хотите, и может быть гораздо более эффективным.

12 голосов
/ 11 апреля 2011

Используйте select или poll, чтобы запросить, есть ли в дескрипторе файла данные, доступные для чтения:

fd_set fds;
FD_ZERO(&fds);
FD_SET(&fds, fd);
if (select(fd+1, &fds, 0, 0)==1) /* there is data available */
6 голосов
/ 11 апреля 2011

Хорошо, STDIN можно читать в неблокирующем режиме, как вам хотелось бы. Сначала вам нужно будет установить сокет в неблокирующий режим, как в

int flags = fcntl(fd, F_GETFL, 0);
if(fcntl(fd, F_SETFL, flags | O_NONBLOCK))
    ;// some kind of fail

Когда вы будете готовы прочитать данные из буфера, вы можете попытаться выполнить чтение следующим образом:

int count;
char buffer[1024];
count = read(fd, buffer, 1024);
if(count < 0 && errno == EAGAIN) {
    // If this condition passes, there is no data to be read
}
else if(count >= 0) {
    // Otherwise, you're good to go and buffer should contain "count" bytes.
}
else {
    // Some other error occurred during read.
}

Обратите внимание, что, конечно, размер буфера 1024 является произвольным.

3 голосов
/ 11 апреля 2011

Я думаю, вы должны использовать функции select или poll, чтобы проверить, есть ли что-то, что можно прочитать из дескриптора.

1 голос
/ 19 сентября 2017
use poll for timeout:

struct pollfd p;
            int n;
            while ((n = poll(&p, 1, iTo)) < 0) 
              {
               if (errno == EAGAIN || errno == EINTR)
                   continue;
            }

            if (!n) {
                 errno = ETIMEDOUT;
                   }

        while ((len = read(Fd, anyBuff, sizeof(anyenter code hereBuff))) < 0) {
            if (errno == EAGAIN || errno == EINTR)
                continue;

        }
1 голос
/ 29 сентября 2013

Проверьте API или систему / инструмент, который вы используете для своих конкретных целей программирования.(дескрипторы / файловые дескрипторы имеют много применений в программировании Linux, таких как программирование сокетов, манипулирование файлами, shared_memory и т. д.)

Например, однажды я использовал inotify (для мониторинга событий файловой системы).Этот API дает вам возможность создавать неблокирующий файл с первой точки, и нет необходимости использовать fcntl или такие API для изменения дескриптора созданного файла.

Возможно, другие инструменты или API, которые вы собираетесь использоватьу вас есть такая функциональность, и вы можете установить такую ​​опцию в их инициации или в таких шагах (сначала проверьте это).

Но обычно да, использование fcntl - это ответ, и было бы интересно знать, что само inotify тоже использует fcntl.(см. справочные страницы Linux)

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

1 голос
/ 11 апреля 2011

В зависимости от того, что вы делаете, вы можете вывернуть проблему наизнанку и использовать select, чтобы сообщить вам, когда дескриптору вашего файла есть, что прочитать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...