short events; /* события на дескрипторе, которые нас интересуют */
short revents; /* события, произошедшие на дескрипторе fd */
};
Проверяемые условия задаются элементом events
, и состояние этого дескриптора функция возвращает в соответствующем элементе revents
. (Наличие двух переменных для каждого дескриптора, одна из которых — значение, а вторая — результат, дает возможность обойтись без аргументов типа «значение-результат». Вспомните, что три средних аргумента функции select
имеют тип «значение-результат».) Каждый из двух элементов состоит из одного или более битов, задающих определенное условие. В табл. 6.2 перечислены константы, используемые для задания флага events
и для проверки флага revents
.
Таблица 6.2. Различные значения флагов events и revents для функции poll
Константа | На входе (events) | На выходе (revents) | Описание |
---|---|---|---|
POLLIN | • | • | Можно считывать обычные или приоритетные данные |
POLLRDNORM | • | • | Можно считывать обычные данные |
POLLRDBAND | • | • | Можно считывать приоритетные данные |
POLLPRI | • | • | Можно считывать данные с высоким приоритетом |
POLLOUT | • | • | Можно записывать обычные данные |
POLLWRNORM | • | • | Можно записывать обычные данные |
POLLWRBAND | • | • | Можно записывать приоритетные данные |
POLLERR | • | Произошла ошибка | |
POLLHUP | • | Произошел разрыв соединения | |
POLLNVAL | • | Дескриптор не соответствует открытому файлу |
Мы разделили эту таблицу на три части: первые четыре константы относятся ко вводу, следующие три — к выводу, а последние три — к ошибкам. Обратите внимание, что последние три константы не могут устанавливаться в элементе events, но всегда возвращаются в revents, когда выполняется соответствующее условие.
Существует три класса данных, различаемых функцией poll
: обычные, приоритетные и данные с высоким приоритетом. Эти термины берут начало в реализациях, основанных на потоках (см. рис. 31.5).
Константа POLLIN может быть задана путем логического сложения констант POLLRDNORM и POLLRDBAND. Константа POLLIN существовала еще в реализациях SVR3, которые предшествовали полосам приоритета в SVR4, то есть эта константа существует в целях обратной совместимости. Аналогично, константа POLLOUT эквивалентна POLLWRNORM, и первая из них предшествовала второй.
Для сокетов TCP и UDP при описанных условиях функция poll
возвращает указанный флаг revent
. К сожалению, в определении функции poll
стандарта POSIX имеется множество слабых мест (неоднозначностей):
■ Все регулярные данные TCP и все данные UDP считаются обычными.
■ Внеполосные данные TCP (см. главу 24) считаются приоритетными.
■ Когда считывающая половина соединения TCP закрывается (например, если получен сегмент FIN), это также считается равнозначным обычным данным, и последующая операция чтения возвратит нуль.
■ Наличие ошибки для соединения TCP может расцениваться либо как обычные данные, либо как ошибка (POLLERR
). В любом случае последующая функция read возвращает -1, что сопровождается установкой переменной errno
в соответствующее значение. Это происходит при получении RST или истечении таймера.
■ Информация о доступности нового соединения на прослушиваемом сокете может считаться либо обычными, либо приоритетными данными. В большинстве реализаций эта информация рассматривается как обычные данные.
Число элементов в массиве структур задается аргументом nfds
.
Исторически этот аргумент имел тип long без знака, что является некоторым излишеством. Достаточно будет типа int без знака. В Unix 98 для этого аргумента определяется новый тип — nfds_t.
Аргумент timeout
определяет, как долго функция находится в ожидании перед завершением. Положительным значением задается количество миллисекунд — время ожидания. В табл. 6.3 показаны возможные значения аргумента timeout
.
Таблица 6.3. Значения аргумента timeout для функции poll
Значение аргумента timeout | Описание |
---|---|
INFTIM | Ждать вечно |
0 | Возвращать управление немедленно, без блокирования |
>0 | Ждать в течение указанного числа миллисекунд |
Константа INFTIM
определена как отрицательное значение. Если таймер в данной системе не обеспечивает точность порядка миллисекунд, значение округляется в большую сторону до ближайшего поддерживаемого значения.
POSIX требует, чтобы константа INFTIM была определена в заголовочном файле <poll.h>, но многие системы все еще определяют ее в заголовочном файле <sys/stropts.h>.
Как и в случае функции select, любой тайм-аут, установленный для функции poll, ограничивается снизу разрешающей способностью часов в конкретной реализации (обычно 10 мс).
Функция poll
возвращает -1, если произошла ошибка, 0 — если нет готовых дескрипторов до истечения времени таймера, иначе возвращается число дескрипторов с ненулевым элементом revents
.