POLL(2)

ИМЯ
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 *timeout_ts, 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
        Состояние ошибки (указывается только как результат).

    POLLHUP
        Повесили трубку (hang up) (указывается только как результат).

    POLLNVAL
        Неверный запрос: дескриптор fd не открыт (указывается только как результат).

При компилировании с установленным _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, timeout_ts, &sigmask);
эквивалентен атомарному выполнению следующих вызовов:
    sigset_t origmask;
    int timeout;
    timeout = (timeout_ts == NULL) ? -1 :
              (timeout_ts.tv_sec * 1000 + timeout_ts.tv_nsec / 1000000);
    sigprocmask(SIG_SETMASK, &sigmask, &origmask);
    ready = poll(&fds, nfds, timeout);
    sigprocmask(SIG_SETMASK, &origmask, NULL);

Смотрите в pselect(2) пояснения о необходимости ppoll(). Если значение аргумента sigmask равно NULL, то изменение маски сигналов не происходит (и поэтому ppoll() отличается от poll() только в точности аргумента timeout). В аргументе timeout_ts указывается верхняя граница промежутка времени, на который будет заблокирован ppoll(). Этот аргумент представляет собой указатель на структуру следующего вида:
struct timespec {
    long    tv_sec;         /* секунды */
    long    tv_nsec;        /* наносекунды */
};
Если значение timeout_ts равно 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. Вызов ppoll() есть только в Linux.

ЗАМЕЧАНИЯ
В некоторых реализациях определена нестандартная константа INFTIM со значением -1 для использования в качестве значения timeout в poll(). Эта константа отсутствует в glibc. Обсуждение того, что может случиться, если файловый дескриптор отслеживается poll() и при этом закрывается в другой нити, смотрите в select(2).

  Отличия между библиотекой C и ABI ядра
В Linux системный вызов ppoll() изменяет свой аргумент timeout_ts. Однако, обёрточная функция glibc скрывает это поведение с помощью локальной переменной для аргумента timeout, которая передаётся в системный вызов. Поэтому glibc функция ppoll() не изменяет свой аргумент timeout_ts. Ядерный системный вызов ppoll() имеет пятый аргумент, size_t sigsetsize, в котором указывается размер аргумента sigmask в байтах. В обёрточной функции glibc ppoll() в этом аргументе передаётся постоянная величина (равная sizeof(sigset_t)).

ДЕФЕКТЫ
Смотрите описание ложных уведомлений о готовности в разделе ДЕФЕКТЫ справочной страницы select(2).

СМОТРИТЕ ТАКЖЕ
restart_syscall(2), select(2), select_tut(2), time(7)