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

22  stdineof = 0;

23  for (;;) {

24   /* блокирование до готовности сокета */

25   dopoll.dp_timeout = -1;

26   dopoll.dp_nfds = 2;

27   dopoll.dp_fds = pollfd;

28   result = Ioctl(wfd, DP_POLL, &dopoll);

29   /* цикл по готовым дескрипторам */

30   for (i = 0; i < result; i++) {

31    if (dopoll.dp_fds[i].fd == sockfd) {

32     /* сокет готов к чтению */

33     if ((n = Read(sockfd, buf, MAXLINE)) == 0) {

34      if (stdineof == 1)

35       return; /* нормальное завершение */

36      else

37       err_quit("str_cli: server terminated prematurely");

38     }

39     Write(fileno(stdout), buf, n);

40    } else {

41     /* дескриптор готов к чтению */

42     if ((n = Read(fileno(fp), buf, MAXLINE)) == 0) {

43      stdineof = 1;

44      Shutdown(sockfd, SHUT_WR); /* отправка FIN */

45      continue;

46     }

47     Writen(sockfd, buf, n);

48    }

49   }

50  }

51 }

Составление списка дескрипторов для /dev/poll

14-21
 Заполнив массив структур
pollfd
, мы передаем его в
/dev/poll
. В нашем примере используются только два файловых дескриптора, так что мы помещаем их в статический массив. На практике программы, использующие
/dev/poll
, обычно следят за сотнями или даже тысячами дескрипторов одновременно, поэтому массив выделяется динамически.

Ожидание данных

24-28
 Программа не вызывает
select
, а блокируется в вызове
ioctl
в ожидании поступления данных. Возвращаемое значение представляет собой количество готовых к чтению дескрипторов файлов.

Цикл по дескрипторам

30-49
 Наша программа относительно проста, потому что мы знаем, что дескрипторов всего два. В большой программе цикл будет более сложным. Возможно даже разделение программы на потоки для обработки данных, полученных по разным дескрипторам.

Интерфейс kqueue

Система FreeBSD версии 4.1 предложила сетевым программистам новый интерфейс, получивший название

kqueue
. Этот интерфейс позволяет процессу зарегистрировать фильтр событий, описывающий интересующие данный процесс события
kqueue
. К событиям этого типа относятся операции ввода-вывода с файлами и тайм-ауты, а также асинхронный ввод-вывод, уведомление об изменении файлов и обработка сигналов.

#include <sys/types.h>

#include <sys/event.h>

#include <sys/time.h>

int kqueue(void);

int kevent(int <i>kq</i>, const struct kevent *<i>changelist</i>, int <i>nchanges</i>,

 struct kevent *<i>eventlist</i>, int <i>nevents</i>, const struct timespec *<i>timeout</i>);

void EV_SET(struct kevent *<i>kev</i>, uintptr_t <i>ident</i>, short <i>filter</i>,

 u_short <i>flags</i>, u_int <i>fflags</i>, intptr_t <i>data</i>, void *<i>udata</i>);

Функция

kqueue
возвращает новый дескриптор
kqueue
, который может использоваться в последующих вызовах
kevent
. Функция
kevent
применяется для регистрации интересующих событий, а также для получения уведомлений об этих событиях. Параметры
changelist
и
nchanges
описывают изменения в предыдущем варианте списка событий. Если
nchanges
отлично от нуля, выполняются все запрошенные в структуре
changelist
изменения. Функция
kevent
возвращает количество событий или нуль, если произошел выход по тайм-ауту. В аргументе
timeout
хранится значение тайм-аута, обрабатываемое подобно тому, как при вызове
select
(
NULL
для блокирования, ненулевое значение для задания конкретного тайм- аута, а нулевое значение трактуется как необходимость неблокирующего вызова). Обратите внимание, что параметр
timeout
имеет тип
struct timespec
, отличающийся от
struct timeval
в вызове
select
тем, что первый имеет наносекундное разрешение, а второй — микросекундное.

Структура

kevent
определяется в заголовочном файле
&lt;sys/event.h&gt;
:

struct kevent {

 uintptr_t ident;  /* идентификатор (например, дескриптор файла) */

 short     filter; /* тип фильтра (например, EVFILT_READ) */

 u_short   flags;  /* флаги действий (например, EV_ADD); */

 u_int     fflags; /* флаги, относящиеся к конкретным фильтрам */

 intptr_t  data;   /* данные, относящиеся к конкретным фильтрам */

 void      uidata; /* непрозрачные пользовательские данные */

};

Действия по смене фильтра и флаговые возвращаемые значения приведены в табл. 14.5.

Таблица 14.5. Флаги для операций kevent

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