select()

Проверка наличия файлов, готовыx к чтению или записи

Прототип:

#include <sys/select.h>
int select( int width,
fd_set *readfds,
fd_set *writefds,
fd_set *exceptfds,
struct timeval *timeout );
#define FD_SET( int fd, fd_set * fdset ) ...
#define FD_CLR( int fd, fd_set * fdset ) ...
#define FD_ISSET( int fd, fd_set * fdset ) ...
#define FD_ZERO( fd_set * fdset ) ...

Аргументы:

width
Число дескрипторов для опроса, которые содержатся в заданных массивах. Проверяются только дескрипторы от 0 до (width - 1). Значение width должно быть не меньше чем:
(файловый дескриптор с наивысшим значением в массивах) + 1
readfds
NULL или указатель на объект fd_set, который содержит дескрипторы для проверки файлов, готовых к чтению. Функция заменяет массив файловыми дескрипторами, готовыми к чтению.
writefds
NULL, или указатель на объект fd_set, который содержит дескрипторы для проверки файлов, готовых к записи. Функция заменяет массив файловыми дескрипторами, готовыми к записи.
exceptfds
NULL, или указатель на объект fd_set, который содержит дескрипторы для проверки файлов, которые имеют исключительные события (обычно это ошибки). Функция заменяет массив файловыми дескрипторами, у которых имеются исключения.
timeout
NULL или указатель на struct timeval, который определяет предельное время ожидания событий.

Библиотека:

libc

Описание:

Функция select() проверяет наборы файловых дескрипторов, адреса которых переданы в массивах readfds, writefds и excludefds, для того, чтобы узнать, готовы ли некоторые из них к чтению или записи, либо же в них зарегистрировано исключительное событие (обычно это ошибка). Любой из массивов readfds, writefds и exceptfds может быть указателем на NULL.


Note: select() и связанные с ним макросы определенны в <sys/select.h>, который также подключает <sys/time.h>.

Функция select() заменяет заданные наборы дескрипторов подмножествами, состоящими лишь из тех перечисленных дескрипторов, на которых обнаружено выполнение соответствующих условий (готовность к чтению, записи или наличие исключений) и возвращает общее количество готовых файловых дескрипторов во всех наборах.

Если timeout не NULL, то он задает максимальный время ожидания событий в наборах дескрипторов. Если timeout равен NULL, select() блокируется до тех пор, пока не выполнится одно из выбранных условий. Чтобы выполнить опрос без фактической блокировки, аргумент timeout должен быть действительным указателем и указывать на struct timeval с нулевым значением.


Note: Из-за характера измерения времени фактическое ожидание может превысить указанное время.

Если текущая поддерживается большее количество открытых файлов, чем указано в FD_SETSIZE, вы можете увеличить количество дескрипторов открытых файлов, используемых с помощью select(), изменив FD_SETSIZE перед включением <sys/select.h> или <sys/time.h>.

Если вы используете select() с таймаутом, его необходимо отдельно сбросить после вызова select().


Note: Если вы используете select() в сочетании с API сетевых сокетов, обратите внимание, что ожидание доступности для чтения на дескрипторе сокета, на котором был выполнен listen(), указывает на то, что последующий accept() на этом дескрипторе не будет блокирующим.

Управление наборами файловых дескрипторов

В <sys/select.h> определены следующие макросы для управления наборами дескрипторов файлов:

FD_ZERO( &fdset )
Установка набора дескрипторов fdset в нулевое значение.
FD_SET( fd, &fdset )
Добавление дескриптора файла fd в набор fdset.
FD_CLR( fd, &fdset )
Удаление fd из набора fdset.
FD_ISSET( fd, &fdset )
Возвращает ненулевое значение, если fd является членом набора fdset и 0 в ином случае.

Поведение макросов не определено, если значение дескриптора меньше нуля, либо больше или равно FD_SETSIZE.

Возвращаемое значение:

Число дескрипторов в заданном наборе, для которых выполнено указанное условие. Если возникла ошибка функция возвращает -1, код ошибки записывается в errno.

Коды ошибок:

EBADF
В одном из наборов указан недопустимый дескриптор.
EFAULT
Один из указателей, указанных в вызове, ссылался на несуществующую часть адресного пространства процесса.
EINTR
До наступления любого из выбранных событий (а также до истечения таймаута) получен сигнал.
EINVAL
Компонент находится вне допустимого диапазона: t_sec должно быть в диапазоне от 0 до 10^8, включительно; t_usec должен быть больше или равен 0 и меньше 10^6.

Примеры:

/*
* This example opens a console and a serial port for
* read mode and calls select() with a 5 second timeout.
* It waits for data to be available on either descriptor.
*/
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/select.h>
int main( void )
{
int console, serial;
struct timeval tv;
fd_set rfd;
int n;
if ( ( console = open( "/dev/con1", O_RDONLY ) ) == -1 ||
( serial = open( "/dev/ser1", O_RDONLY ) ) == -1 )
{
perror( "open" );
return (EXIT_FAILURE);
}
/*
* Clear the set of read file descriptors and
* add the two we just got from the open calls.
*/
FD_ZERO( &rfd );
FD_SET( console, &rfd );
FD_SET( serial, &rfd );
/*
* Set a 5 second timeout.
*/
tv.tv_sec = 5;
tv.tv_usec = 0;
switch ( n = select( 1 + max( console, serial ), &rfd, 0, 0, &tv ) )
{
case -1:
perror( "select" );
return (EXIT_FAILURE);
case 0:
puts( "select timed out" );
break;
default:
printf( "%d descriptors ready ...\n", n );
if ( FD_ISSET( console, &rfd ) )
puts( " -- console descriptor has data pending" );
if ( FD_ISSET( serial, &rfd ) )
puts( " -- serial descriptor has data pending" );
}
return (EXIT_SUCCESS);
}

Классификация:

POSIX 1003.1

Безопасность использования
Точка остановки потока
Нет
Обработчик прерываний
Нет
Обработчик сигналов
Нет
В потоке
Смотри ниже

Предупреждения:

Функция select() работает только с "сырыми" дескрипторами файлов (см. ICANON в описании функции tcgetattr()).

Функция select() является потокобезопасной до тех пор, пока используемые каждым потоком наборы fd указывают на память, которая специфична для этого потока.

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

Тематические ссылки:

struct timeval, errno, fcntl(), read(), sysconf(), tcsetattr(), write()




Предыдущий раздел: Описание API системной библиотеки