Provided by: manpages-ru_0.98-4_all bug

НАЗВАНИЕ

       select,  pselect,  FD_CLR,  FD_ISSET,  FD_SET,  FD_ZERO  -  синхронное мультиплексирование
       ввода-вывода

КРАТКАЯ СВОДКА

       #include <sys/time.h>
       #include <sys/types.h>
       #include <unistd.h>

       int select(int n, fd_set *readfds, fd_set *writefds,  fd_set  *exceptfds,  struct  timeval
       *timeout);

       int  pselect(int  n,  fd_set  *readfds,  fd_set *writefds, fd_set *exceptfds, const struct
       timespec *timeout, sigset_t * sigmask);

       FD_CLR(int fd, fd_set *set);
       FD_ISSET(int fd, fd_set *set);
       FD_SET(int fd, fd_set *set);
       FD_ZERO(fd_set *set);

ОПИСАНИЕ

       Функции select и pselect ждут изменения статуса нескольких файловых дескрипторов.

       Они почти идентичны, только

       (i)    select использует тайм-аут в виде struct timeval (с  секундами  и  микросекундами),
              тогда как pselect использует struct timespec (с секундами и наносекундами).

       (ii)   Функция  select  может  обновить  параметр timeout, чтобы сообщить, сколько времени
              осталось.  Функция pselect не изменяет этот параметр.

       (iii)  Функция select не содержит параметра sigmask, и ведет себя как pselect с параметром
              sigmask, равным NULL.

       Отслеживаются  три  независимых  набора  дескрипторов.   Те,  что  перечислены в параметре
       readfds, будут отслеживаться на предмет появления новых  символов,  доступных  для  чтения
       (говоря  точнее,  операция чтения не будет блокирована -- в частности, файловый дескриптор
       находится в конце файла); те, что указаны в параметре  writefds,  будут  отслеживаться  на
       предмет  того,  что операция записи не будет заблокирована; те же, что указаны в параметре
       exceptfds, будут отслеживаться  на  предмет  исключительных  ситуаций.   При  возврате  из
       функции  наборы  дескрипторов  модифицируются,  чтобы показать, какие из них изменили свой
       статус.

       Для манипуляций наборами существуют четыре  макроса:  FD_ZERO  очищает  набор.   FD_SET  и
       FD_CLR  добавляют или удаляют заданный дескриптор из набора.  FD_ISSET проверяет, является
       ли дескриптор частью набора; этот макрос полезен после возврата из функции select.

       n на единицу больше самого большого номера дескриптора из всех наборов.

       timeout -- это верхняя граница времени, которое пройдет перед возвратом из select.   Можно
       использовать ноль, при этом select завершится немедленно.  (Это полезно для периодического
       опроса.)  Если timeout равен NULL (нет  тайм-аута),  то  select  будет  ожидать  изменений
       неопределенное время.

       sigmask  --  это  указатель на маску сигналов (см.  sigprocmask(2)); если этот параметр не
       равен NULL, то pselect сначала замещает текущую маску сигналов на ту, на которую указывает
       sigmask, затем выполняет select, и восстанавливает исходную маску сигналов.

       Идея  pselect  в том, что если нужно подождать события: сигнала или активности на файловом
       дескрипторе,  то  требуется  атомарная  проверка,  чтобы  предотвратить  race   condition.
       (Предположим,  обработчик  сигнала  устанавливает глобальный флаг и возвращает управление.
       Тогда проверка этого глобального флага, за которой  следует  select(),  может  привести  к
       подвисанию, если сигнал появляется сразу после проверки, но прямо перед вызовом select.  С
       другой стороны, pselect позволяет  сначала  заблокировать  сигналы,  обработать  пришедшие
       сигналы,  а затем вызвать pselect() с желаемой sigmask, тем самым избегая race condition.)
       Так как  Linux  в  настоящее  время  не  содержит  системного  вызова  pselect(),  текущая
       реализация этой процедуры в glibc все еще содержит race condition.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

       При успешном завершении select и pselect возвращают количество дескрипторов, находящихся в
       наборах дескрипторов,  причем  это  количество  может  быть  равным  нулю,  если  тайм-аут
       истекает,  а  интересующие  нас события так и не произошли.  При ошибке возвращается -1, а
       errno устанавливается должным образом; наборы дескрипторов и значение  timeout  становятся
       неопределены, поэтому при ошибке нельзя полагаться на их значение.

ОШИБКИ

       EBADF  В одном из наборов находится неверный файловый дескриптор.

       EINTR  Был пойман незаблокированный сигнал.

       EINVAL n отрицательно.

       ENOMEM Функция select не смогла выделить участок памяти для внутренних таблиц.

ЗАМЕЧАНИЕ

       В некоторых программах select вызывается с тремя пустыми наборами файлов, n равным нулю, и
       ненулевым значением timeout, что является довольно переносимым способом сделать задержку с
       миллисекундной точностью.

       Под  Linux  timeout  изменяется,  чтобы  сообщить  количество  времени,  которое  не  было
       использовано; большинство других реализаций не делают этого.  Это приводит к проблемам как
       в  коде  под  Linux,  который  читает значение timeout и переносится в другие операционные
       системы, так и когда код переносится под Linux и использует при этом  struct  timeval  для
       нескольких  функций  select  в  цикле без повторной инициализации.  Считайте, что параметр
       timeout неопределен после возврата из функции select.

ПРИМЕР

       #include <stdio.h>
       #include <sys/time.h>
       #include <sys/types.h>
       #include <unistd.h>

       int
       main(void)
       {
           fd_set rfds;
           struct timeval tv;
           int retval;

           /* Ждем, пока на стандартном вводе (fd 0) что-нибудь
              появится. */
           FD_ZERO(&rfds);
           FD_SET(0, &rfds);
           /* Ждем не больше пяти секунд. */
           tv.tv_sec = 5;
           tv.tv_usec = 0;

           retval = select(1, &rfds, NULL, NULL, &tv);
           /* Не полагаемся на значение tv! */

           if (retval)
               printf("Данные доступны.\n");
               /* Теперь FD_ISSET(0, &rfds) вернет истинное значение. */
           else
               printf("Данные не появились в течение пяти секунд.\n");

           exit(0);
       }

СООТВЕТСТВИЕ СТАНДАРТАМ

       4.4BSD (функция select впервые  появилась  в  4.2BSD).   Обычно  переносится  с/на  не-BSD
       системы, поддерживающие уровень BSD-сокетов (включая варианты System V).  Однако заметьте,
       что варианты System V обычно устанавливают значение переменной timeout  перед  выходом,  а
       вариант BSD -- нет.

       Функция  pselect определена в IEEE Std 1003.1g-2000 (POSIX.1g).  Ее можно найти в glibc2.1
       и позднее.  Glibc2.0 содержит функцию с таким именем, но без параметра sigmask.

СМОТРИ ТАКЖЕ

       accept(2), connect(2), poll(2), read(2), recv(2), send(2), sigprocmask(2), write(2)

ПЕРЕВОД

       Copyright (C) Alexey Mahotkin <alexm@hsys.msk.ru> 2000-2001