Используем select для мониторинга доступности данных

Функция select используется для проверки доступности данных в открытом дескрипторе.
Для использования функции в linux необходимо подключить заголовочные файлы:

#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

или согласно POSIX.1-2001:

#include <sys/select.h>

В Windows функция определена в winsock.h и winsock2.h. Используется аналогично.
Но учтите, что в новой редакции функция имеет уже немного другой формат и называется pselect().
Прототип функции имеет вид:

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

Кроме того вам придётся использовать такие функции:

void FD_SET(int fd, fd_set *set);
void FD_ZERO(fd_set *set);

С помощью этих функций задаётся поток.
Обратите внимание, что в функции select используется параметр int nfds — наивысший дескриптор. Его можно получить при помощи добавления 1 к полученному выше дескриптору.

Следующие три параметра функции select используються для задания отслеживаемых данных. Если дескриптор установлен в позиции fd_set *readfds дескриптор будет проверятся на возможность считывания данных; fd_set *writefds — доступность записи; fd_set *exceptfds — исключения.

Дискриптор будет проверятся в течении времени заданного в struct timeval, которая имеет вид:

struct timeval {
       long    tv_sec;         /* секунды */
       long    tv_usec;        /* милисекунды */
};

Если данные не доступны будет возвращён «-1». Иначе будет возвращено количество дескрипторов «готовых» из трёх заданных.

Рассмотрим пример. Напишем программу, которая проверит доступность для чтения данных в потоке ввода.
Определим необходимые заголовочные файлы:

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

Определим необходимые переменные:

fd_set rfds;
struct timeval tv;
int retval;

Определим поток ввода данных (stdin — fd 0). При этом сначала необходимо обнулить rfds при помощи FD_ZERO():

FD_ZERO(&rfds);
FD_SET(0, &rfds);

Укажем время ожидания данных:

tv.tv_sec = 5;
tv.tv_usec = 0;

Вызовем функцию select:

retval = select(1, &rfds, NULL, NULL, &tv);

Осталось проверить результат операции:

if (retval == -1)
       perror("select()");  //выводим сообщение об ошибке
    else if (retval)
        printf("Данные доступны.\n");
    else
        printf("Нет данных в течении 5 сек.\n");

Ну и конец каждой С программы:

exit(EXIT_SUCCESS);

После компиляции, в течении 5 секунд, введите данные и нажмите Enter, будет выведено сообщение о доступности данных, иначе через 5 секунд выведется сообщение о их недоступности. Учтите всё это произойдёт только если не будет возвращён -1 — ошибка выполнения функции.
ps эта функция очень полезна при работе с сокетами.

 

Похожий код:

Фото аватара
Алексей Петров

Программист, разработчик с 5 летним опытом работы. Учусь на разработчика игр на Unity и разработчика VR&AR реальности (виртуальной реальности). Основные языки программирования: C#, C++.

Оцените автора
Бла, бла код
Добавить комментарий