stringtranslate.com

выберите (Unix)

select — это системный вызов и интерфейс прикладного программирования (API) в Unix-подобных и POSIX -совместимых операционных системах для проверки состояния файловых дескрипторов открытых каналов ввода/вывода. [1] Системный вызов select похож на функцию poll , представленную в UNIX System V и более поздних операционных системах. Однако с проблемой c10k и select, и poll были заменены такими функциями, как kqueue , epoll , /dev/poll и портами завершения ввода/вывода . [2]

Одним из распространенных вариантов использования select за пределами его заявленного использования для ожидания файловых дескрипторов является реализация переносимого субсекундного sleep . Этого можно добиться, передав NULL для всех трех аргументов fd_set и продолжительность желаемого sleep в качестве аргумента тайм-аута.

В языке программирования C системный вызов select объявляется в заголовочном файле sys/select.h или unistd.h и имеет следующий синтаксис:

int select ( int nfds , fd_set * readfds , fd_set * writefds , fd_set * errorfds , struct timeval * timeout );           

fd_set typeАргументами можно управлять с помощью четырех служебных макросов: FD_SET(), FD_CLR(), FD_ZERO() и FD_ISSET() .

Select возвращает общее количество битов, установленных в readfds, writefds и errorfds , или ноль, если время ожидания истекло, и -1 в случае возникновения ошибки.

Наборы файловых дескрипторов, используемые в select, имеют конечный размер в зависимости от операционной системы. Более новый системный вызов poll обеспечивает более гибкое решение.

Пример

#include <stdio.h> #include <stdlib.h> #include <string.h>   #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h>    #include <sys/select.h> #include <fcntl.h> #include <unistd.h> #include <err.h> #include <errno.h>     #определить ПОРТ "9421"/* прототипы функций */ void die ( const char * );  int main ( int argc , char ** argv ) { int sockfd , new , maxfd , on = 1 , nready , i ;              struct addrinfo * res0 , * res , подсказки ;     буфер символов [ BUFSIZ ];  fd_set master , readfds ;   ошибка int ;  ssize_t nbytes ;  ( void ) memset ( & hints , '\0' , sizeof ( struct addrinfo ));    подсказки . ai_family = AF_INET ; подсказки . ai_socktype = SOCK_STREAM ; подсказки . ai_protocol = IPPROTO_TCP ; подсказки . ai_flags = AI_PASSIVE ;            если ( 0 != ( ошибка = getaddrinfo ( NULL , PORT , & hints , & res0 ))) errx ( EXIT_FAILURE , "%s" , gai_strerror ( ошибка ));            for ( res = res0 ; res ; res = res -> ai_next ) { if ( -1 == ( sockfd = сокет ( res -> ai_family , res -> ai_socktype , res -> ai_protocol ))) { perror ( "socket( )" ); продолжать ; }                     если ( -1 == ( setsockopt ( sockfd , SOL_SOCKET , SO_REUSEADDR , ( char * ) & on , sizeof ( int )))) { perror ( "setsockopt()" ); продолжить ; }            если ( -1 == ( bind ( sockfd , res -> ai_addr , res -> ai_addrlen ))) { perror ( "bind()" ); продолжить ; }          перерыв ; } если ( -1 == sockfd ) выход ( EXIT_FAILURE );     freeaddrinfo ( res0 ); если ( -1 == ( listen ( sockfd , 32 ))) умереть ( "listen()" );      если ( -1 == ( fcntl ( sockfd , F_SETFD , O_NONBLOCK ))) die ( "fcntl()" );       FD_ZERO ( & master ); FD_ZERO ( & readfds );  FD_SET ( sockfd , & master );  maxfd = sockfd ;   while ( 1 ) { memcpy ( & readfds , & master , sizeof ( master ));      ( void ) printf ( "выполняется select() \n " ); если ( -1 == ( nready = select ( maxfd + 1 , & readfds , NULL , NULL , NULL ))) die ( "select()" );           ( void ) printf ( "Количество готовых дескрипторов: %d \n " , nready );  для ( i = 0 ; i <= maxfd && nready > 0 ; i ++ ) { если ( FD_ISSET ( i , & readfds )) { nready -- ;            if ( i == sockfd ) { ( void ) printf ( "Попытка принять() новое(ие) соединение(я) \n " );      если ( -1 == ( новый = принять ( sockfd , NULL , NULL ))) { если ( EWOULDBLOCK != errno ) умереть ( "принять()" );              перерыв ; }  еще {  если ( -1 == ( fcntl ( новый , F_SETFD , O_NONBLOCK ))) die ( "fcntl()" );       FD_SET ( новый , & главный );  если ( maxfd < новый ) maxfd = новый ; } }         else { ( void ) printf ( "recv() данные из одного из дескрипторов \n " );   nbytes = recv ( i , buffer , sizeof ( buffer ), 0 ); если ( nbytes <= 0 ) { если ( EWOULDBLOCK != errno ) die ( "recv()" );                перерыв ; }  буфер [ nbytes ] = '\0' ; printf ( "%s" , буфер );     ( void ) printf ( "получено %zi байт. \n " , nbytes );  закрыть ( i ); FD_CLR ( i , & master );   } }  } } вернуть 0 ; }  void die ( const char * msg ) { perror ( msg ); выход ( EXIT_FAILURE ); }     

Смотрите также

Ссылки

  1. ^ Computer Systems Research Group (1994). "select, pselect — синхронное мультиплексирование ввода-вывода". BSD Cross Reference . NetBSD .
  2. ^ "Методы обработки соединений". nginx .org .

Внешние ссылки