Литмир - Электронная Библиотека
Содержание  
A
A

Мы поговорим о функции

pselect
более подробно и приведем ее пример в разделе 20.5. Функцию
pselect
мы используем в листинге 20.3, а в листинге 20.4 показываем простую, хотя и не вполне корректную реализацию этой функции.

ПРИМЕЧАНИЕ

Есть одно незначительное различие между функциями select и pselect. Первый элемент структуры timeval является целым числом типа long со знаком, в то время как первый элемент структуры timspec имеет тип time_t. Число типа long со знаком в первой функции также должно было относиться к типу time_t, но мы не меняли его тип, чтобы не разрушать существующего кода. Однако в новой функции это можно было бы сделать.

6.10. Функция poll

Функция

poll
появилась впервые в SVR3, и изначально ее применение ограничивалось потоковыми устройствами (STREAMS devices) (см. главу 31). В SVR4 это ограничение было снято, что позволило функции
poll
работать с любыми дескрипторами. Функция
poll
предоставляет функциональность, аналогичную функции
select
, но позволяет получать дополнительную информацию при работе с потоковыми устройствами.

#include <poll.h>

int poll(struct pollfd *<i>fdarray</i>, unsigned long <i>nfds</i>, int <i>timeout</i>);

<i>Возвращает: количество готовых дескрипторов, 0 в случае тайм-аута, -1 в случае ошибки</i>

Первый аргумент — это указатель на первый элемент массива структур. Каждый элемент массива — это структура

pollfd
, задающая условия, проверяемые для данного дескриптора
fd
.

struct pollfd {

 int fd;        /* дескриптор, который нужно проверить */

 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
.

72
{"b":"225366","o":1}