ready = 0
timeout after select(): 0.000
Вызов select() немедленно возвращается, не найдя ни одного готового дескриптора.
В следующем примере мы отслеживаем два файловых дескриптора с номерами 0 (для ввода) и 1 (для вывода). Аргументу timeout присваивается значение NULL (первый аргумент командной строки равен знаку минус), что говорит о бесконечном времени ожидания:
$ ./t_select — 0r 1w
ready = 1
0:
1: w
Вызов select() немедленно возвращается, информируя нас о возможности вывода для дескриптора 1.
59.2.2. Системный вызов poll()
Системный вызов poll() может выполнять действие, сравнимое с select(). Главное отличие между этими двумя операциями состоит в том, каким способом задаются дескрипторы для мониторинга. Вызов select() предоставляет три набора; каждый из них должен сигнализировать о готовности тех или иных дескрипторов. Вызов poll() предоставляет один список; каждый дескриптор в нем имеет набор событий, которые нас интересуют.
#include
int poll(struct pollfd
Возвращает количество готовых файловых дескрипторов, 0, если истекло время ожидания, или -1 при ошибке
Аргумент fds и массив pollfd (nfds) обозначают файловые дескрипторы, которые нужно отслеживать. Аргумент timeout можно использовать, чтобы задать максимальный отрезок времени, на протяжении которого будет блокироваться вызов poll(). Каждый из представленных аргументов подробно описывается ниже.
Массив pollfd
Аргумент fds содержит список файловых дескрипторов, за которыми вызов poll() должен наблюдать. Это массив структур типа pollfd, определяемых следующим образом:
struct pollfd {
int fd; /* Файловый дескриптор */
short events; /* Битовая маска с заданными событиями */
short revents; /* Битовая маска с возвращаемыми событиями */
};
Аргумент nfds обозначает количество элементов в массиве fds. Тип данных nfds_t, применяемый в аргументе nfds, представляет собой беззнаковое целое число.
Поля events и revents структуры pollfd являются битовыми масками. Вызывающий процесс инициализирует events, указывая события, которые нужно отслеживать для файлового дескриптора fd. Во время возвращения вызова poll() полю revents присваивается значение, сигнализирующее о событиях, на самом деле произошедших в этом дескрипторе.
В табл. 59.2 перечислены биты, которые могут содержаться в полях events и revents. Первая группа битов (POLLIN, POLLRDNORM, POLLRDBAND, POLLPRI и POLLRDHUP) относится к событиям ввода, а вторая (POLLOUT, POLLWRNORM и POLLWRBAND) — к событиям вывода. Третья группа (POLLERR, POLLHUP и POLLNVAL) содержит биты, устанавливаемые в поле revents для получения дополнительных сведений о файловом дескрипторе. Любой из этих трех битов будет проигнорирован, если указать его в поле events. Последний бит, POLLMSG, не используется в вызове poll(), реализованном в Linux.
В UNIX-системах, предоставляющих механизм STREAMS для символьных устройств, бит POLLMSG уведомляет о том, что сообщение с сигналом SIGPOLL достигло начала потока. Linux не использует бит POLLMSG, так как не поддерживает механизм STREAMS.
Таблица 59.2. Значения битовых масок для полей events и revents структуры pollfd
Бит — Передается в events? — Возвращается из revents? — Описание
POLLIN — * — * — Данные (не считая высокоприоритетных) могут быть прочитаны
POLLRDNORM — * — * — Эквивалент бита POLLIN
POLLRDBAND — * — * — Приоритетные данные могут быть прочитаны (не используется в Linux)
POLLPRI — * — * — Высокоприоритетные данные могут быть прочитаны
POLLRDHUP — * — * — Удаленный сокет был закрыт
POLLOUT — * — * — Обычные данные могут быть записаны
POLLWRNORM — * — * — Эквивалент бита POLLOUT
POLLWRBAND — * — * — Приоритетные данные могут быть записаны
POLLERR — * — Произошла ошибка
POLLHUP — * — Произошел разрыв соединения
POLLNVAL — * — Файловый дескриптор не открыт
POLLMSG — Не используется в Linux (и не входит в стандарт SUSv3)
При отсутствии надобности в событиях для конкретного файлового дескриптора полю events можно присвоить 0. Кроме того, если указать отрицательное значение для fd (например, путем умножения номера дескриптора на –1, при условии, что тот не равен нулю), соответствующее поле events будет проигнорировано, а events в любом случае вернет 0. Любой из вариантов можно использовать, чтобы отключить мониторинг определенного файлового дескриптора (возможно, временно) без необходимости заново создавать весь список fds.
Стоит отметить следующие аспекты реализации вызова poll() в Linux.
• Биты POLLIN и POLLRDNORM определены отдельно, но являются синонимами.
• Биты POLLOUT и POLLWRNORM определены отдельно, но являются синонимами.
• Бит POLLRDBAND обычно не применяется, то есть игнорируется в поле events и не указывается в revents.
Бит POLLRDBAND указывается только в коде, реализующем (устаревший) сетевой протокол DECnet.