У меня есть дескриптор fd, который я могу использовать для чтения, вызывая read(fd, buffer,...)
. Теперь я хочу проверить, есть ли что-нибудь для чтения, прежде чем делать вызов, потому что вызов блокируется. Как это сделать?
Неблокирующий вызов для чтения дескриптора
Ответ 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;
}