12 static long cntread[QSIZE +1]; /* диагностический счетчик */
13 static int iget; /* следующий элемент для обработки в основном цикле */
14 static int iput; /* следующий элемент для считывания обработчиком
сигналов */
15 static int nqueue; /* количество дейтаграмм в очереди на обработку
в основном цикле */
16 static socklen_t clilen; /* максимальная длина sockaddr{} */
17 static void sig_io(int);
18 static void sig_hup(int);
3-12
SIGIO
помещает приходящие дейтаграммы в очередь. Эта очередь является массивом структур
DG
, который интерпретируется как кольцевой буфер. Каждая структура содержит указатель на принятую дейтаграмму, ее длину и указатель на структуру адреса сокета, содержащую адрес протокола клиента и размер адреса протокола. В памяти размещается столько этих структур, сколько указано в
QSIZE
(в данном случае 8), и в листинге 25.2 будет видно, что функция
dg_echo
для размещения в памяти всех структур дейтаграмм и адресов сокетов вызывает функцию
malloc
. Также происходит выделение памяти под диагностический счетчик
cntread
, который будет рассмотрен чуть ниже. На рис. 25.2 приведен массив структур, при этом предполагается, что первый элемент указывает на 150-байтовую дейтаграмму, а длина связанного с ней адреса сокета равна 16.Рис. 25.2
. Структуры данных, используемые для хранения прибывающих дейтаграмм и структур адресов их сокетов13-15
iget
является индексом следующего элемента массива для обработки в основном цикле, а переменная
iput
— это индекс следующего элемента массива, в котором сохраняется результат действия обработчика сигнала. Переменная
nqueue
обозначает полное количество дейтаграмм, предназначенных для обработки в основном цикле.В листинге 25.2 показан основной цикл сервера — функция
dg_echo
.Листинг 25.2
. Функция dg_echo: основной обрабатывающий цикл сервера//sigio/dgecho01.c
19 void
20 dg_echo(int sockfd_arg, SA *pcliaddr, socklen_t clilen_arg)
21 {
22 int i;
23 const int on = 1;
24 sigset_t zeromask, newmask, oldmask;
25 sockfd = sockfd_arg;
26 clilen = clilen_arg;
27 for (i = 0; i QSIZE; i++) { /* инициализация очереди */
28 dg[i].dg_data = Malloc(MAXDG);
29 dg[i].dg_sa = Malloc(clilen);
30 dg[i].dg_salen = clilen;
31 }
32 iget = iput = nqueue = 0;
33 Signal(SIGHUP, sig_hup);
34 Signal(SIGIO, sig_io);
35 Fcntl(sockfd, F_SETOWN, getpid);
36 Ioctl(sockfd, FIOASYNC, on);
37 Ioctl(sockfd. FIONBIO, on);
38 Sigemptyset(zeromask); /* инициализация трех наборов сигналов */
39 Sigemptyset(oldmask);
40 Sigemptyset(newmask);
41 Sigaddset(newmask, SIGIO); /* сигнал, который хотим блокировать*/
42 Sigprocmask(SIG_BLOCK, newmask, oldmask);
43 for (;;) {
44 while (nqueue == 0)
45 sigsuspend(zeromask); /* ждем дейтаграмму для обработки */
46 /* разблокирование SIGIO */
47 Sigprocmask(SIG_SETMASK, oldmask, NULL);
48 Sendto(sockfd, dg[iget].dg_data, dg[iget].dg_len, 0,
49 dg[iget].dg_sa, dg[iget].dg_salen);
50 if (++iget = QSIZE)
51 iget = 0;
52 /* блокировка SIGIO */
53 Sigprocmask(SIG_BLOCK, newmask, oldmask);
54 nqueue--;
55 }
56 }
27-32