Linux
2019-08-02
Aliases: ppoll(2), ppoll(2), ppoll(2), ppoll(2), ppoll(2), ppoll(2)
man-pages-ru
Russian man pages from the Linux Documentation Project
manpages-dev
Manual pages about using GNU/Linux for development
man-pages
Linux kernel and C library user-space interface documentation
ИМЯ
poll, 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) задачу: он ждёт пока один дескриптор из набора файловых дескрипторов не станет готов выполнить операцию ввода-вывода.
Заметим, что интервал timeout будет округлён с точностью системных часов, а из-за задержки при планировании в ядре блокирующий интервал будет немного больше. Отрицательное значение в timeout означает бесконечное ожидание. Значение timeout, равное нулю, приводит к немедленному завершению poll(), даже если ни один файловый дескриптор не готов.
В Linux также есть POLLMSG, но он не используется.
Отслеживаемый набор файловых дескрипторов задаётся в аргументе fds, который представляет собой массив структур:
struct pollfd {
int fd; /* файловый дескриптор */
short events; /* запрашиваемые события */
short revents; /* возвращённые события */ };
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() в ожидании готовности файлового дескриптора. Вызов будет заблокирован пока:
* | файловый дескриптор не станет готов; |
* | вызов не прервётся обработчиком сигнала; |
* | не истечёт время ожидания. |
Вот возможные биты, описанные в <poll.h>, которые могут быть установлены/получены в events и revents:
POLLIN | Есть данные для чтения. | ||||||
POLLPRI | |||||||
Исключительное состояние файлового дескриптора. Может быть из-за:
|
|||||||
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 | |||||||
Можно писать приоритетные данные. |
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);
(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);
Приведённый выше сегмент кода показывает ближайший эквивалент, так как отрицательное значение timeout в poll() рассматривается как бесконечное ожидание, а отрицательное значение в *tmo_p привело бы к ошибке ppoll().
Смотрите в pselect(2) пояснения о необходимости ppoll().
Если значение аргумента sigmask равно NULL, то изменение маски сигналов не происходит (и поэтому ppoll() отличается от poll() только в точности аргумента timeout).
В аргументе tmo_p указывается верхняя граница промежутка времени, на который будет заблокирован ppoll(). Этот аргумент представляет собой указатель на структуру следующего вида:
struct timespec {
long tv_sec; /* секунды */
long tv_nsec; /* наносекунды */ };
long tv_sec; /* секунды */
long tv_nsec; /* наносекунды */ };
Если значение tmo_p равно NULL, то ppoll() может оставаться заблокированным бесконечно.
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении возвращается положительное значение; оно означает количество структур, в которых поля revents имеют ненулевое значение (другими словами, тех дескрипторов, для которых возникли события или ошибки). Значение 0 означает, что время ожидания истекло, и нет готовых файловых дескрипторов. В случае ошибки возвращается -1, а errno устанавливается в соответствующее значение.
ОШИБКИ
EFAULT | Указанный аргументом массив содержится вне адресного пространства вызывающей программы. |
EINTR | Получен сигнал раньше какого-либо запрашиваемого события; смотрите signal(7). |
EINVAL | Значение nfds превышает значение RLIMIT_NOFILE. |
EINVAL | (ppoll()) Время ожидания в *ip некорректно (отрицательное). |
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.
ЗАМЕЧАНИЯ
На операции poll() и ppoll() флаг O_NONBLOCK не влияет.
В некоторых системах UNIX вызов poll() может завершаться с ошибкой EAGAIN, если системе не удаётся выделить внутренние ресурсы ядра, вместо ошибки ENOMEM как это происходит в Linux. В POSIX допускается такое поведение. Переносимые программы должны ожидать EAGAIN в цикле, как для EINTR.
В некоторых реализациях определена нестандартная константа 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(kernel_sigset_t)). Описание различий sigset между ядерным и библиотечным вызовом смотрите в sigprocmask(2).
ДЕФЕКТЫ
Смотрите описание ложных уведомлений о готовности в разделе ДЕФЕКТЫ справочной страницы select(2).
СМОТРИТЕ ТАКЖЕ
REFERENCED BY
ldap_get_option(3), ldap_set_option(3), pcap(3pcap), sctp_connectx(3), accept(2), connect(2), epoll_ctl(2), eventfd(2), fcntl(2), futex(2), ioctl_tty(2), perf_event_open(2), perfmonctl(2), prctl(2), ptrace(2), recv(2), restart_syscall(2), select(2), select_tut(2), sigaction(2), signalfd(2), timerfd_create(2), userfaultfd(2), rtime(3), random(4), proc(5), cgroups(7), epoll(7), fanotify(7), inotify(7), mq_overview(7), pipe(7), signal(7), socket(7), spufs(7), udp(7), slapd-ldap(5), slapd-meta(5), ivykis(3), tntnet.xml(7), nfsd(7), tty_ioctl(4), rt_sigsuspend(2), rds(7), open(2), pcap_get_required_select_timeout(3pcap), pcap_get_selectable_fd(3pcap), pidfd_open(2), io_uring_enter(2)