Системный вызов se le c t () предоставляет механизм для реализации синхронного
мультиплексированного ввода-вывода:
finclude
#include
finclude
int select (int n,
fd s e t *readfds,
fd s e t *writefds.
fd set *exceptfds,
struct timeval *timeout):
FD_CLR(int fd, fd set *set):
FD_ISSET(int fd. fd s e t *set);
FD_SET(int fd. fd set *set);
FD_ZERO(fd_set *set);
Вызов se le c tO блокируется до тех пор, пока указанный дескриптор файла
не становится готовым к выполнению ввода-вывода, или же до тех пор, пока не
истекает необязательный интервал тайм-аута.
Наблюдаемые файловые дескрипторы разбиваются на три набора, в каждом
из которых ожидается свое событие. Дескрипторы файла в наборе readfds наблюдаются
в ожидании момента, когда данные станут доступными для чтения
(то есть можно будет выполнить операцию считывания без блокировки). Дескрипторы файла в наборе writefds наблюдаются в ожидании момента, когда
можно будет завершить без блокировки операцию записи. Наконец, файловые
дескрипторы в наборе exceptfds наблюдаются с тем, чтобы отлавливать
создание исключений или появление внеполосных данных (эти состояния распространяются
только на сокеты). Каждый набор может содержать значение
NULL, и в этом случае вызов select( ) не отслеживает соответствующее событие.
В случае успешного возвращения вызовом результата каждый набор модифицируется,
и в нем остаются только дескрипторы файла, готовые к операции
ввода-вывода, относящейся к этому набору. Например, предположим, что два
дескриптора файла со значениями 7 и 9 помещены в набор readfds. Когда вызов
возвращает результат, если 7 все еще находится в наборе, эго означает, что соответствующий
дескриптор файла готов к чтению без блокировки. Если значение
9 удалено из набора, вероятно, считать соответствующий файл без блокировки
невозможно. (Я говорю ≪вероятно≫, потому что данные вполне могут
стать доступными уже после того, как вызов завершится. В этом случае повторный
вызов selectO вернет файловый дескриптор как готовый к считыванию1.)
Первый параметр, п, на единицу превышает максимальное во всех наборах
значение дескриптора файла. Следовательно, вызывающий функцию sel ect О
должен проверить, у какого дескриптора максимальное значение, прибавить
к нему единицу и передать полученное в качестве первого параметра.
Параметр timeout - это указатель на структуру timeval, которая определяется
следующим образом:
#include
struct timeval {
long tvsec: /* секунды */
long tvusec: /* микросекунды */
}: