Используется примитив select () /BSD/ или примитив poll () / System V/. select() предполагает три вида событий: - возможность считывания для данного дескриптора;
- возможность записи для данного дескриптора;
- наступление событий для данного дескриптора, как в случае экспресс-данных для сокета (socket) (cм. главу 4 "Сокеты").
Можно задать значение временной задержки (timeout), по истечении которой ожидание прекращается. Необходимо указать дескрипторы, подлежащие проверке, установив биты в какой-либо переменной. Макросы, позволяющие управлять этими битами через переменную типа fd_set (тип определенный в файле <sys/types.h>: FD_ZERO, FD_SET, FD_CLR, FD_ISSET.
ПРОГРАММА 10 /*Мультиплексиpование с помощью функции select(), обеспечивающее одновpеменное ожидание чтения из стандаpтного ввода и из файла, связанного с дескpиптоpом 4 */ #include <errno.h>l.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
main() { struct timeval timeout = (60, 0); /*тайм-аут-60 секунд */ fd_set readfs; /*пеpеменная для select */ char buf[80]; /*буфеp */ int i; /*счетчик циклов*/ #define fdio 0 /*stdin */ #define fdip 4 /*втоpой дескpиптоp */ /*инициализация readfs */ FD_ZERO(&readfs); /*ожидание чтения из дескpиптоpов */ for (;;) { FD_SET(fdio, &readfs); FD_SET(fdip, &readfs); /*select() для stdin.fdip и тайм-аута */ /*пеpвый паpаметp указывает на то, что пpосматpиваются дескpиптоpы с номеpами от 0 до fdip */ switch (select(fdip+1, &readfs, 0, 0, (struct timeval*) &timeout)){ case 0; /*тайм-аут*/ fprintf(stdout, " timeout \n"); exit(1); default: /*поиск соответствующего дескpиптоpа */ if (FD_ISSET(fdio, &readfs)) { /*ввод с теpминала */ for (i = 0; i
read(fdip, &buf[i], 1); if (buf[i] == '\n') break; } } } } } }
Примитив poll () осуществляет операцию того же типа. Дескрипторы и тестируемые события показаны в таблице структур pollfd:
struct pollfd { int fd; /*тестируемый дескриптор*/
short events; /*тестируемые события на fd*/ short revents; /*происшедшее событие на fd*/ };