Подтвердить что ты не робот

Неблокирующий вызов для чтения дескриптора

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

4b9b3361

Ответ 1

int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);

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

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

Ответ 2

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

fd_set fds;
FD_ZERO(&fds);
FD_SET(&fds, fd);
if (select(fd+1, &fds, 0, 0)==1) /* there is data available */

Ответ 3

Хорошо, 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 произволен.

Ответ 4

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

Ответ 5

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

Ответ 6

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

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

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

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

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

Ответ 7

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;

        }