Уильям Стивенс - UNIX: разработка сетевых приложений
- Название:UNIX: разработка сетевых приложений
- Автор:
- Жанр:
- Издательство:Питер
- Год:2007
- Город:Санкт-Петербург
- ISBN:5-94723-991-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Уильям Стивенс - UNIX: разработка сетевых приложений краткое содержание
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
UNIX: разработка сетевых приложений - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
6.9. Функция pselect
Функция pselect
была введена в POSIX и в настоящий момент поддерживается множеством версий Unix.
#include
#include
#include
int pselect(int maxfdp1 , fd_set * readset , fd_set * writeset , fd_set * exceptset ,
const struct timespec * timeout , const sigset_t * sigmask );
Возвращает: количество готовых дескрипторов, 0 в случае тайм-аута, -1 в случае ошибки
Функция pselect
имеет два отличия от обычной функции select
:
1. Функция pselect
использует структуру timespec
, нововведение стандарта реального времени POSIX, вместо структуры timeval
.
struct timespec {
time_t tv_sec; /* секунды */
long tv_nsec; /* наносекунды */
};
Эти структуры отличаются вторыми элементами: элемент tv_nsec
новой структуры задает наносекунды, в то время как элемент tv_usec
прежней структуры задает микросекунды.
2. В функции pselect
добавляется шестой аргумент — указатель на маску сигналов. Это позволяет программе отключить доставку ряда сигналов, проверить какие-либо глобальные переменные, установленные обработчиками этих отключенных сигналов, а затем вызвать функцию pselect
, сообщив ей, что нужно переустановить маску сигналов.
В отношении второго пункта рассмотрим следующий пример (описанный на с. 308–309 [110]). Обработчик сигнала нашей программы для сигнала SIGINT
просто устанавливает глобальную переменную intr_flag
и возвращает управление. Если наш процесс блокирован в вызове функции select, возвращение из обработчика сигнала заставляет функцию завершить работу, присвоив errno
значение EINTR
. Код вызова select
выглядит следующим образом:
if (intr_flag)
handle_intr(); /* обработка этого сигнала */
if ((nready = select(...)) < 0) {
if (errno == EINTR) {
if (intr_flag)
handle_intr();
}
...
}
Проблема заключается в том, что если сигнал придет в промежутке между проверкой переменной intr_flag
и вызовом функции select
, он будет потерян в том случае, если функция select
заблокирует процесс навсегда. С помощью функции pselect
мы можем переписать этот пример так, чтобы он работал более надежно:
sigset_t newmask, oldmask, zeromask;
sigemptyset(&zeromask);
sigemptyset(&newmask);
sigaddset(&newmask, SIGINT);
sigprocmask(SIG_BLOCK, &newmask, &oldmask); /* блокирование сигнала SIGINT */
if (intr_flag)
handle_intr(); /* обработка этого сигнала */
if ((nready = pselect(..., &zeromask)) < 0) {
if (errno == EINTR) {
if (intr_flag)
handle_intr();
}
...
}
Перед проверкой переменной intr_flag
мы блокируем сигнал SIGINT
. Когда вызывается функция pselect
, она заменяет маску сигналов процесса пустым набором ( zeromask
), а затем проверяет дескрипторы, возможно, переходя в состояние ожидания. Но когда функция pselect
возвращает управление, маске сигналов процесса присваивается то значение, которое предшествовало вызову функции pselect
(то есть сигнал SIGINT
блокируется).
Мы поговорим о функции 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
int poll(struct pollfd * fdarray , unsigned long nfds , int timeout );
Возвращает: количество готовых дескрипторов, 0 в случае тайм-аута, -1 в случае ошибки
Первый аргумент — это указатель на первый элемент массива структур. Каждый элемент массива — это структура 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).
Интервал:
Закладка: