Проверка наличия файлов, готовы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 ) ...
0
до (width - 1). Значение width должно быть не меньше чем: NULL
или указатель на объект fd_set, который содержит дескрипторы для проверки файлов, готовых к чтению. Функция заменяет массив файловыми дескрипторами, готовыми к чтению.NULL
, или указатель на объект fd_set, который содержит дескрипторы для проверки файлов, готовых к записи. Функция заменяет массив файловыми дескрипторами, готовыми к записи.NULL
, или указатель на объект fd_set, который содержит дескрипторы для проверки файлов, которые имеют исключительные события (обычно это ошибки). Функция заменяет массив файловыми дескрипторами, у которых имеются исключения.NULL
или указатель на struct timeval, который определяет предельное время ожидания событий.libc
Функция select() проверяет наборы файловых дескрипторов, адреса которых переданы в массивах readfds, writefds и excludefds, для того, чтобы узнать, готовы ли некоторые из них к чтению или записи, либо же в них зарегистрировано исключительное событие (обычно это ошибка). Любой из массивов readfds, writefds и exceptfds может быть указателем на NULL
.
![]() | select() и связанные с ним макросы определенны в <sys/select.h> , который также подключает <sys/time.h> . |
Функция select() заменяет заданные наборы дескрипторов подмножествами, состоящими лишь из тех перечисленных дескрипторов, на которых обнаружено выполнение соответствующих условий (готовность к чтению, записи или наличие исключений) и возвращает общее количество готовых файловых дескрипторов во всех наборах.
Если timeout не NULL
, то он задает максимальный время ожидания событий в наборах дескрипторов. Если timeout равен NULL
, select() блокируется до тех пор, пока не выполнится одно из выбранных условий. Чтобы выполнить опрос без фактической блокировки, аргумент timeout должен быть действительным указателем и указывать на struct timeval с нулевым значением.
![]() | Из-за характера измерения времени фактическое ожидание может превысить указанное время. |
Если текущая поддерживается большее количество открытых файлов, чем указано в FD_SETSIZE
, вы можете увеличить количество дескрипторов открытых файлов, используемых с помощью select(), изменив FD_SETSIZE
перед включением <sys/select.h>
или <sys/time.h>
.
Если вы используете select() с таймаутом, его необходимо отдельно сбросить после вызова select().
![]() | Если вы используете select() в сочетании с API сетевых сокетов, обратите внимание, что ожидание доступности для чтения на дескрипторе сокета, на котором был выполнен listen(), указывает на то, что последующий accept() на этом дескрипторе не будет блокирующим. |
Управление наборами файловых дескрипторов
В <sys/select.h>
определены следующие макросы для управления наборами дескрипторов файлов:
0
в ином случае. Поведение макросов не определено, если значение дескриптора меньше нуля, либо больше или равно FD_SETSIZE
.
Число дескрипторов в заданном наборе, для которых выполнено указанное условие. Если возникла ошибка функция возвращает -1
, код ошибки записывается в errno.
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 системной библиотеки