poll - ожидает некоторое событие над файловым дескриптором
poll(2)
ожидает некоторое событие над файловым дескриптором
Other Alias
ppoll
ОБЗОР
#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
#define _GNU_SOURCE /* смотрите feature_test_macros(7) */
#include <signal.h>
#include <poll.h>
int ppoll(struct pollfd *fds, nfds_t nfds,
const struct timespec *tmo_p, const sigset_t *sigmask);
ОПИСАНИЕ
Вызов
poll() выполняет сходную с
select(2) задачу: он ждёт пока один
дескриптор из набора файловых дескрипторов не станет готов выполнить
операцию ввода-вывода.
Отслеживаемый набор файловых дескрипторов задаётся в аргументе fds,
который представляет собой массив структур:
struct pollfd {
int fd; /* файловый дескриптор */
short events; /* запрашиваемые события */
short revents; /* возвращённые события */
};
Вызывающий должен указать количество элементов в массиве fds в аргументе
nfds.
В поле fd содержится файловый дескриптор открытого файла. Если значение
поля отрицательно, то соответствующее поле events игнорируется, а полю
revents возвращает ноль (простой способ игнорирования файлового
дескриптора в одиночном вызове poll(): просто сделать значение поля fd
отрицательным. Заметим, что это нельзя использовать для игнорирования
файлового дескриптора 0).
Поле events представляет собой входной параметр — битовую маску,
указывающую на события, происходящие с файловым дескриптором fd, которые
важны для приложения. Если это поле равно нулю, то возвращаемыми событиями в
revents могут быть POLLHUP, POLLERR и POLLNVAL (смотрите ниже).
Поле revents представляет собой параметр-результат, в который ядро
помещает информацию о произошедших событиях. В revents могут содержаться
любые битовые флаги из задаваемых в events, или там может быть одно из
значений: POLLERR, POLLHUP или POLLNVAL. Эти три битовых флага не
имеют смысла в поле events, но будут установлены в поле revents, если
соответствующее условие истинно.
Если ни одно из запрошенных событий с файловыми дескрипторами не произошло
или не возникло ошибок, то poll() блокируется до их появления.
В аргументе timeout указывается количество миллисекунд, на которые будет
блокироваться poll() в ожидании готовности файлового дескриптора. Вызов
будет заблокирован пока:
файловый дескриптор не станет готов;
вызов не прервётся обработчиком сигнала;
не истечёт время ожидания.
Заметим, что интервал timeout будет округлён с точностью системных часов,
а из-за задержки при планировании в ядре блокирующий интервал будет немного
больше. Отрицательное значение в timeout означает бесконечное
ожидание. Значение timeout, равное нулю, приводит к немедленному
завершению poll(), даже если ни один файловый дескриптор не готов.
Вот возможные биты, описанные в <poll.h>, которые могут быть
установлены/получены в events и revents:
POLLIN
Есть данные для чтения.
POLLPRI
Есть срочные данные для чтения (например, внеполосные данные в сокете TCP;
мастер псевдотерминала в пакетном режиме увидел изменение состояния
подчинённого терминала).
POLLOUT
Теперь запись возможна, но запись данных больше, чем доступно места в сокете
или канале, по-прежнему приводит к блокировке (если не указан
O_NONBLOCK).
POLLRDHUP (начиная с Linux 2.6.17)
Удалённая сторона потокового сокета закрыла соединение, или отключила запись
в одну сторону. Для использования данного определения должен быть определён
макрос тестирования свойств _GNU_SOURCE (до включения каких-либо
заголовочных файлов).
POLLERR
Состояние ошибки (возвращается только в revents; игнорируется в
events).
POLLHUP
Зависание (hang up, возвращается только в revents; игнорируется в
events). Заметим, что при чтении из канала, такого как канал (pipe) или
потоковый сокет, это событие всего-навсего показывает, что партнёр закрыл
канал со своего конца. Дальнейшее чтение из канала будет возвращать 0 (конец
файла) только после потребления всех неполученных данных в канале.
POLLNVAL
Неверный запрос: fd не открыт (возвращается только в revents;
игнорируется в events).
При компилировании с установленным _XOPEN_SOURCE также определены
следующие значения, которые не передают дополнительной информации вне
упомянутых выше битов:
POLLRDNORM
Эквивалентно POLLIN.
POLLRDBAND
Доступны для чтения приоритетные внутриполосные данные (в Linux, обычно, не
используется).
POLLWRNORM
Эквивалентно POLLOUT.
POLLWRBAND
Можно писать приоритетные данные.
В Linux также есть POLLMSG, но он не используется.
ppoll()
Отношения между poll() и ppoll() аналогичны родству select(2) и
pselect(2): как pselect(2), ppoll() позволяет приложению безопасно
ждать, пока файловый дескриптор не станет готов или пока не будет получен
сигнал.
Кроме различия в точности аргумента timeout вызов ppoll()
ready = ppoll(&fds, nfds, tmo_p, &sigmask);
эквивалентен атомарному выполнению следующих вызовов:
sigset_t origmask;
int timeout;
timeout = (tmo_p == NULL) ? -1 :
(tmo_p->tv_sec * 1000 + tmo_p->tv_nsec / 1000000);
pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
ready = poll(&fds, nfds, timeout);
pthread_sigmask(SIG_SETMASK, &origmask, NULL);
Смотрите в pselect(2) пояснения о необходимости ppoll().
Если значение аргумента sigmask равно NULL, то изменение маски сигналов
не происходит (и поэтому ppoll() отличается от poll() только в
точности аргумента timeout).
В аргументе tmo_p указывается верхняя граница промежутка времени, на
который будет заблокирован ppoll(). Этот аргумент представляет собой
указатель на структуру следующего вида:
struct timespec {
long tv_sec; /* секунды */
long tv_nsec; /* наносекунды */
};
Если значение tmo_p равно NULL, то ppoll() может оставаться
заблокированным бесконечно.
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении возвращается положительное значение; оно означает
количество структур, в которых поля revents имеют ненулевое значение
(другими словами, тех дескрипторов, для которых возникли события или
ошибки). Значение 0 означает, что время ожидания истекло, и нет готовых
файловых дескрипторов. В случае ошибки возвращается -1, а errno
устанавливается в соответствующее значение.
ОШИБКИ
EFAULT
Указанный аргументом массив содержится вне адресного пространства вызывающей
программы.
EINTR
Получен сигнал раньше какого-либо запрашиваемого события; смотрите
signal(7).
EINVAL
Значение nfds превышает значение RLIMIT_NOFILE.
ENOMEM
Нет места под таблицы файловых дескрипторов.
ВЕРСИИ
Системный вызов poll() появился в Linux 2.1.23. Для старых ядер, в
которых этот вызов отсутствует, glibc (и старая Linux libc) предоставляет
обёрточную функцию poll(), которая эмулируется с помощью select(2).
Системный вызов ppoll() был добавлен в ядро Linux в версии
2.6.16. Библиотечный вызов ppoll() был добавлен в glibc 2.4.
СООТВЕТСТВИЕ СТАНДАРТАМ
Вызов poll() соответствует POSIX.1-2001 и POSIX.1-2008. Вызов ppoll()
есть только в Linux.
ЗАМЕЧАНИЯ
В некоторых реализациях определена нестандартная константа INFTIM со
значением -1 для использования в качестве значения timeout в
poll(). Эта константа отсутствует в glibc.
Обсуждение того, что может случиться, если файловый дескриптор отслеживается
poll() и при этом закрывается в другой нити, смотрите в select(2).
Отличия между библиотекой C и ядром
В Linux системный вызов ppoll() изменяет свой аргумент tmo_p. Однако,
обёрточная функция glibc скрывает это поведение с помощью локальной
переменной для аргумента timeout, которая передаётся в системный
вызов. Поэтому glibc функция ppoll() не изменяет свой аргумент tmo_p.
Ядерный системный вызов ppoll() имеет пятый аргумент, size_t
sigsetsize, в котором указывается размер аргумента sigmask в байтах. В
обёрточной функции glibc ppoll() в этом аргументе передаётся постоянная
величина (равная sizeof(sigset_t)).
ДЕФЕКТЫ
Смотрите описание ложных уведомлений о готовности в разделе ДЕФЕКТЫ
справочной страницы select(2).