Выберите всё что не включено в систему программирования


SELECT(2) Руководство программиста Linux SELECT(2) 
 select. Pselect, FD_CLR. FD_ISSET, FD_SET. FD_ZERO - синхронно Мультиплексирование ввода-вывода 
  выберите инт(инт N на единицу больше, fd_set *ограничить readfds, fd_set *ограничить writefds, fd_set *ограничить показывает сколько времени прошло, структуры timeval. Которая *ограничить время ожидания); в Void FD_CLR(int и значение FD, fd_set *набор); инт теперь fd_isset(int и красители FD, fd_set *набор); пустота FD_SET(int и значение FD, fd_set *набор); пустота FD_ZERO(fd_set *набор); почти инт(инт N на единицу больше, fd_set *ограничить readfds, fd_set *ограничить writefds, fd_set *ограничить показывает сколько времени прошло

, константные структуры struct timespec *ограничить время ожидания, как const sigset_t *ограничить параметром sigmask, равным); Требования к макросам тестирования функций для glibc (см. feature_test_macros(7)): pselect():

ОПИСАНИЕ топ

 select() позволяет программе отслеживать несколько файловых дескрипторов, ожидая. Пока один или несколько файловых дескрипторов не станут 

Файловый дескриптор считается готовым. Если можно выполнить соответствующую операцию ввода-вывода (например , чтение(2)или достаточно малую запись(2)) без блокировки. select() может отслеживать только номера файловых дескрипторов . Которые меньше FD_SETSIZE; poll(2) и epoll(7) не имеют этого ограничения. См. ОШИБКИ. Наборы файловых дескрипторов Основными аргументами select() являются три fd_set), которые позволяют вызывающему объекту ждать трех классов событий на указанном наборе файловых дескрипторов. Каждый из аргументов fd_set может быть указан как NULL. Если для соответствующего класса событий не требуется наблюдение за файловыми дескрипторами . Обратитевнимание : По возвращении каждый из наборов файловых дескрипторов изменяется на месте. Чтобы указать. Какие файловые дескрипторы в данный момент Таким образом. При использовании select() в цикле наборы он должен быть повторно инициализирован перед каждым вызовом. Реализация аргументов fd_set в качестве аргументов value-result -это ошибка проектирования. Которой можно избежать в poll(2) и epoll(7). Содержимым набора файловых дескрипторов можно манипулировать с помощью следующих макросов: FD_ZERO() Этот макрос очищает (удаляет все файловые дескрипторы из набора) набор. Его следует использовать в качестве первого шага при инициализации набора файловых дескрипторов. FD_SET() Этот макрос добавляет файловый дескриптор fd для установки. Добавление файлового дескриптора. Который уже присутствует в наборе. Является no-op и не приводит к ошибке. FD_CLR() Этот макрос удаляет файловый дескриптор fd из набора. Удаление дескриптора файла. Отсутствующего в наборе . Не является операцией no-op и не приводит к ошибке. FD_ISSET() select() изменяет содержимое наборов в соответствии с правилами. Описанными ниже. После вызова select(), FD_ISSETмакрос () можно использовать для проверки наличия файлового дескриптора в наборе. Функция FD_ISSET() возвращает ненулевое значение . Если файловый дескриптор fd присутствует в set, и ноль. Если его нет. Аргументы Аргументы функции select() следующие: readfds Файловые дескрипторы в этом наборе отслеживаются. Чтобы увидеть. Готовы ли они к чтению. Файловый дескриптор готов к чтению. Если операция чтения не блокируется; в частности. Файловый дескриптор также готов к чтению в конце файла. После того как select() вернется, readfds будет очищен от всех файловых дескрипторов. За исключением тех. Которые готовы к чтению. writefds Файловые дескрипторы в этом наборе отслеживаются. Чтобы увидеть. Готовы ли они к записи. Файловый дескриптор готов к записи. Если операция записи не блокируется. Однако даже если файловый дескриптор указывает как доступный для записи. Большая запись все равно может быть заблокирована. После возврата функции select () writefds будут очищены от всех файловых дескрипторов. За исключением тех. Которые готовы к записи. exceptfds Файловые дескрипторы в этом наборе отслеживаются на наличие Примеры некоторых исключительных условий см. в разделе Обсуждение POLLPRI в опрос(2). После того как select() вернется, exceptfds будет очищен от всех файловых дескрипторов. За исключением тех. Для которых возникло исключительное условие. nfds Этот аргумент должен быть установлен на самый высокий номер файлового дескриптора в любом из трех наборов плюс 1. Указанные файловые дескрипторы в каждом наборе проверяются вплоть до этого предела (но см. тайм-аут Аргумент timeout-это временная структура (показана ниже) это определяет интервал выбора() должен блокировать ожидание готовности файлового дескриптора. Вызов будет заблокирован до тех пор. Пока либо: • файловый дескриптор становится готовым; • вызов прерывается обработчиком сигнала; или • тайм-аут истекает. Обратите внимание. Что интервал тайм-аута будет округлен до детализации системных часов. А задержки планирования ядра означают. Что интервал блокировки может превысить небольшую величину. Если оба поля временной структуры равны нулю, то select() возвращается немедленно. (Это полезно для опроса.) Если timeout указан как NULL, select() блокирует бесконечное ожидание готовности файлового дескриптора. pselect() Системный вызов pselect() позволяет приложению безопасно ждать . Пока файловый дескриптор не будет готов или пока не будет пойман сигнал. Операция select() и pselect() идентична, кроме этих трех различий: • select() использует тайм-аут, который является временным интервалом структуры (с секундами и микросекундами), в то время как pselect() использует структуру timespec (с секундами и наносекундами). • select() может обновить аргумент timeout, чтобы указать, сколько времени осталось. pselect() не изменяет этот аргумент. • select() не имеет аргумента sigmask и ведет себя как pselect() вызывается с нулевой сигма-маской . sigmask-указатель на маску сигнала (см. sigprocmask(2)); если он не равен NULL, то pselect() сначала заменяет текущую маску сигнала на маску, на которую указывает sigmask, затем выполняет функцию (Если sigmask равен NULL, то маска сигнала не изменяется во время вызова pselect().) Помимо разницы в точности аргумента timeout , следующий вызов pselect() : ready = pselect(nfds, &readfds, &writefds, &exceptfds. Timeout, &sigmask); эквивалентно атомарно выполнение следующих вызовов: sigset_t origmask; pthread_sigmask(SIG_SETMASK, &sigmask, &origmask); ready = select(nfds, &readfds, &writefds, &exceptfds. Timeout); pthread_sigmask(SIG_SETMASK. &origmask, NULL); Причина, по которой pselect() необходима. Заключается в том. Что если кто -то хочет дождаться либо сигнала. Либо готовности файлового дескриптора. То для предотвращения условий гонки необходим атомарный тест. (Предположим. Обработчик сигнала устанавливает глобальный флаг и возвращает. Затем проверка этого глобального флага с последующим вызовом select() может висеть бесконечно. Если сигнал поступил сразу после теста. Но непосредственно перед вызовом. Напротив, pselect() позволяет сначала блокировать сигналы. Обрабатывать поступившие сигналы. А затем вызывать pselect() с нужной сигмаской, избегая гонки.) Тайм-аут Аргумент timeout для select() представляет собой структуру следующего типа: struct timeval { time_t tv_sec; /* секунды */ Соответствующий аргумент для pselect() имеет следующий тип: struct timespec { time_t tv_sec; /* секунды */ В Linux select() изменяет тайм-аут, чтобы отразить количество времени . Которое не спало; большинство других реализаций этого не делают. (POSIX.1 допускает любое поведение.) Это вызывает проблемы как при переносе кода Linux. Считывающего тайм-аут, в другие операционные системы. Так и при переносе кода в Linux. Который повторно использует структуру timeval для множественного выбора()s в цикле без его повторной инициализации. Считать тайм-аут будет неопределенным после возврата функции select().

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

 При успешном выполнении select() и pselect() возвращают количество файловых дескрипторов. Содержащихся в трех возвращенных наборах дескрипторов (то есть общее количество битов. Установленных в readfds, writefds, exceptfds). Возвращаемое значение может быть равно нулю. Если тайм-аут истек до того. Как какие-либо файловые дескрипторы были готовы. При ошибке возвращается -1, а errno указывает на ошибку; наборы дескрипторов файлов не изменяются, а время ожидания становится неопределенным. 
 EBADF В одном из наборов был задан недопустимый файловый дескриптор. (Возможно. Файловый дескриптор. Который уже был закрыт, или файл. В котором произошла ошибка.) Однако см. ОШИБКИ. EINTR Сигнал был пойман; см. сигнал(7). EINVAL nfds отрицателен или превышает предел ресурса RLIMIT_NOFILE (см. getrlimit(2)). EINVAL Значение. Содержащееся в таймауте, является недопустимым. ENOMEM Не может выделить память для внутренних таблиц. 
 pselect() был добавлен в Linux в ядре 2.6.16. До этого pselect() эмулировался в glibc (но см. ОШИБКИ). 
 select() соответствует POSIX.1-2001, POSIX.1-2008 и 4.4 BSD (select() впервые появился в версии 4.2 BSD). Обычно переносимые в/из систем. Отличных от BSD. Поддерживающих клоны уровня сокетов BSD (включая варианты System V). Однако обратите внимание. Что вариант System V обычно устанавливает переменную timeout перед возвратом. А вариант BSD-нет. функция pselect() определена в POSIX.1g. А также в POSIX.1-2001 и POSIX.1-2008. 
 fd_set-это буфер фиксированного размера. Выполнение функцииFD_CLR () или FD_SET() при значении fd, которое отрицательно или равно или больше FD_SETSIZE, это приведет к неопределенному поведению. Более того, POSIX требуется, чтобы fd был допустимым файловым дескриптором. Флаг O_NONBLOCK не влияет на работу select () и pselect() . В некоторых других системах UNIX функция select() может завершиться ошибкой EAGAIN, если система не может выделить внутренние ресурсы ядра. А не ENOMEM, как это делает Linux. POSIX указывает эту ошибку для опроса(2), но не для select(). Портативные программы могут захотеть проверить EAGAIN и loop. Как и в EINTR. Трюк с собственной трубой На системах. Которые не имеют pselect(), надежный (и более портативный) улавливание сигнала может быть достигнуто с помощью трюка с собственной трубой. В этом методе обработчик сигнала записывает байт в канал. Другой конец которого контролируется select() в основной программе. (Чтобы избежать возможной блокировки при записи в канал. Который может быть заполнен . Или при чтении из канала. Который может быть пустым. Неблокирующий ввод-вывод используется при чтении и записи в канал.) Эмуляция usleep(3) До появления usleep(3)в некотором коде использовался вызов select() со всеми тремя наборами пустыми , nfds нулевыми и ненулевыми тайм-аут как довольно портативный способ сна с подсекундной точностью. Соответствие между уведомлениями select() и poll()  В источнике ядра Linux мы находим следующие определения . Которые показывают соответствие между уведомлениями о читаемых. Доступных для записи и исключительных условиях select() и уведомлениями о событиях . Предоставленными poll(2) и epoll(7): #define POLLIN_SET (EPOLLRDNORM | EPOLLRDBAND | EPOLLIN | EPOLLHUP | EPOLLERR) /* Готов к чтению */ #define POLLOUT_SET (EPOLLWRBAND | EPOLLWRNORM | EPOLLOUT | EPOLLERR) /* Готов к написанию */ #define POLLEX_SET (EPOLLPRI) /* Исключительное состояние */ Многопоточные приложения Если файловый дескриптор отслеживается select() закрывается в другом потоке. Результат не указан. В некоторых системах UNIX функция select() разблокируется и возвращается с указанием того. Что файловый дескриптор готов (последующая операция ввода-вывода. Скорее всего. Завершится ошибкой. Если только другой процесс снова не откроет файловый дескриптор между моментом возврата select() и выполнением операции ввода -вывода). В Linux (и некоторых других системах) закрытие файлового дескриптора в другом потоке не влияет на select(). Таким образом. Любое приложение. Которое полагается на определенное поведение в этом сценарии. Должно считаться багги. C библиотека/различия ядра Ядро Linux допускает наборы файловых дескрипторов произвольного размера. Определяя длину проверяемых наборов по значению nfds. Однако в реализации glibc тип fd_set фиксирован по размеру. См. также ОШИБКИ. Интерфейс pselect(), описанный на этой странице. Реализован glibc. Базовый системный вызов Linux называется pselect6(). Этот системный вызов ведет себя несколько иначе . Чем функция-оболочка glibc. Системный вызов Linux pselect6() изменяет свой аргумент timeout. Однако функция-оболочка glibc скрывает это поведение. Используя локальную переменную для аргумента timeout. Передаваемого системному вызову. Таким образом. Функция glibc pselect() не изменяет свой аргумент timeout; это поведение требуется POSIX.1-2001. Последний аргумент системного вызова pselect6 () не является sigset_t * указатель. Но вместо этого является структурой вида: struct { const kernel_sigset_t *ss; /* Указатель на набор сигналов */ Это позволяет системному вызову получить как указатель на набор сигналов. Так и его размер. Принимая во внимание тот факт. Что большинство архитектур поддерживают максимум 6 аргументов системного вызова. См. sigprocmask(2) для обсуждения разницы между ядром и libc - понятием набора сигналов. Исторические детали glibc Glibc 2.0 предоставил неверную версию функции pselect(), которая не принимала аргумент сигмаски. В glibc версии 2.1 - 2.2.1 необходимо определить _GNU_SOURCE, чтобы получить объявление pselect() из . 
 POSIX позволяет реализации определить верхний предел. Объявленный через константу FD_SETSIZE, в диапазоне файловых дескрипторов. Которые могут быть указаны в наборе файловых дескрипторов. Ядро Linux не накладывает фиксированного ограничения, но реализация glibc делает fd_set типом фиксированного размера, с FD_SETSIZE, определенным как 1024, и макросы FD_*(), работающие в соответствии с этим ограничением. Чтобы отслеживать файловые дескрипторы, превышающие 1023, используйте вместо этого poll(2) или epoll(7). Согласно POSIX, выберите() следует проверить все указанные файловые дескрипторы в трех наборах файловых дескрипторов. Вплоть до предела нфдс-1. Однако текущая реализация игнорирует любой файловый дескриптор в этих наборах. Превышающий максимальное число файловых дескрипторов. Открытых в данный момент процессом. Согласно POSIX. Любой такой файловый дескриптор. Указанный в одном из наборов. Должен привести к ошибке EBADF. Начиная с версии 2.1, glibc предоставил эмуляцию pselect(), которая была реализована с помощью sigprocmask(2) и select(). Эта реализация оставалась уязвимой к самому состоянию расы. Которое pselect() был разработан. Чтобы предотвратить. Современные версии glibc используют системный вызов (race-free) pselect() для ядер. Где он предусмотрен. В Linux выберите() может сообщить файловый дескриптор сокета как Это может. Например, произойти. Когда данные поступили. Но при проверке имеет неправильную контрольную сумму и отбрасывается. Могут быть и другие обстоятельства. При которых файловый дескриптор ложно сообщается как готовый. Таким образом. Может быть безопаснее использовать O_NONBLOCK на сокетах. Которые не должны блокировать. В Linux select() также изменяет тайм-аут, если вызов прерывается обработчиком сигнала (например, EINTR возврат ошибки). Это не разрешено POSIX.1. Системный вызов Linux pselect() имеет такое же поведение. Но оболочка glibc скрывает это поведение. Внутренне копируя тайм-аут в локальную переменную и передавая эту переменную системному вызову. 
int main(void) { fd_set rfds; struct timeval tv; int retval; /* Следите за stdin (fd 0). Чтобы увидеть. Когда он имеет вход. */ FD_ZERO(&rfds); FD_SET(0, &rfds); /* Подождите до пяти секунд. */ tv.tv_sec = 5; tv.tv_usec = 0; retval = select(1, &rfds, NULL, NULL, &tv); /* Не полагайтесь сейчас на ценность телевидения! */ if (retval == -1) perror( иначе если (retval) printf(/* FD_ISSET(0, &rfds) будет true. */ else printf(

СМ. ТАКЖЕ топ

 accept(2), connect(2), poll(2), read(2), recv(2), restart_syscall(2), send(2), sigprocmask(2), write(2), epoll(7), time(7) Учебник с обсуждением и примерами см. в разделе select_tut(2). 
 Эта страница является частью выпуска 5.11 проекта man-pages Linux. Описание проекта. Информацию о сообщениях об ошибках и последнюю версию этой страницы можно найти по адресу https://www.kernel.org/doc/man-pages/. 

Страницы, которые ссылаются на эту страницу: трассированием(1), принимать(2), сигнализация(2), подключения(2), вызов epoll_wait(2), eventfd(2), вызов fcntl(2), фьютекс(2), ioctl_tty(2), migrate_pages(2), открытые(2), пауза(2), perf_event_open(2), perfmonctl(2), личность(2), pidfd_open(2), опрос(2), вызов prctl(2), Читать(2), вызовов recv(2), restart_syscall(2), select_tut(2), отправить(2), signalfd(2), розетка(2), системные вызовы(2), timerfd_create(2), userfaultfd(2), написать(2), avc_netlink_loop(3), ldap_get_option(3), ldap_result(3), на PCAP(3pcap), pcap_get_required_select_timeout(3pcap), pcap_get_selectable_fd(3pcap), pmrecord(3), pmtime(3), протокол RPC(3), sctp_connectx(3), ualarm(3), usleep(3), случайные(4), РТЦ(4), учеб(5), файла slapd-asyncmeta(5), файла slapd-LDAP-соединение(5), файла slapd-мета(5), команду systemd.метод exec(5), в epoll(7), механизм fanotify(7), в inotify(7), mq_overview(7), труба(7), Пти(7), сигнал(7), сигнал-безопасность(7), гнездо(7), system_data_types(7), в TCP(7), time(7), udp(7), setarch(8)


Авторские права и лицензия на данную страницу руководства