stringtranslate.com

seleccionar (Unix)

select es una llamada del sistema y una interfaz de programación de aplicaciones (API) ensistemas operativos similares a Unix y compatibles con POSIX para examinar el estado de los descriptores de archivos de canales de entrada/salida abiertos. [1] La llamada del sistema select es similar a la función poll introducida en UNIX System V y sistemas operativos posteriores. Sin embargo, con el problema c10k , tanto select como poll han sido reemplazados por funciones como kqueue , epoll , /dev/poll y puertos de finalización de E/S . [2]

Un uso común de select fuera de su uso indicado de esperar en los manejadores de archivos es implementar un modo de suspensión portátil de menos de un segundo . Esto se puede lograr pasando NULL para los tres argumentos de fd_set y la duración del modo de suspensión deseado como argumento de tiempo de espera.

En el lenguaje de programación C , la llamada al sistema select se declara en el archivo de encabezado sys/select.h o unistd.h , y tiene la siguiente sintaxis:

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

fd_set typeLos argumentos se pueden manipular con cuatro macros de utilidad: FD_SET(), FD_CLR(), FD_ZERO() y FD_ISSET() .

Select devuelve el número total de bits establecidos en readfds, writefds y errorfds , o cero si expiró el tiempo de espera y -1 en caso de error.

Los conjuntos de descriptores de archivos que se utilizan en select tienen un tamaño finito, según el sistema operativo. La nueva llamada al sistema poll ofrece una solución más flexible.

Ejemplo

#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>     #define PUERTO "9421"/* prototipos de funciones */ void die ( const char * );  int principal ( int argc , char ** argv ) { int sockfd , nuevo , maxfd , on = 1 , nready , i ;              struct addrinfo * res0 , * res , sugerencias ;     búfer de caracteres [ BUFSIZ ];  fd_set maestro , readfds ;   int error ;  tamaño_t nbytes ;  ( void ) memset ( & sugerencias , '\0' , sizeof ( struct addrinfo ));    sugerencias . ai_family = AF_INET ; sugerencias . ai_socktype = SOCK_STREAM ; sugerencias . ai_protocol = IPPROTO_TCP ; sugerencias . ai_flags = AI_PASSIVE ;            si ( 0 != ( error = getaddrinfo ( NULL , PUERTO , & sugerencias , & res0 ))) errx ( ERROR_DE_SALIDA , "%s" , gai_strerror ( error ));            para ( res = res0 ; res ; res = res -> ai_next ) { si ( -1 == ( sockfd = socket ( res -> ai_family , res -> ai_socktype , res -> ai_protocol ))) { perror ( "socket()" ); continuar ; }                     si ( -1 == ( setsockopt ( sockfd , SOL_SOCKET , SO_REUSEADDR , ( char * ) & on , sizeof ( int )))) { perror ( "setsockopt()" ); continuar ; }            si ( -1 == ( enlazar ( sockfd , res -> ai_addr , res -> ai_addrlen ))) { perror ( "bind()" ); continuar ; }          romper ; } si ( -1 == sockfd ) salir ( EXIT_FAILURE );     freeaddrinfo ( res0 ); si ( -1 == ( escuchar ( sockfd , 32 ))) morir ( "escuchar()" );      si ( -1 == ( fcntl ( sockfd , F_SETFD , O_NONBLOCK ))) morir ( "fcntl()" );       FD_ZERO ( & maestro ); FD_ZERO ( & readfds );  FD_SET ( sockfd , y maestro );  maxfd = calcetín ;   mientras ( 1 ) { memcpy ( & readfds , & master , sizeof ( master ));      ( void ) printf ( "ejecutando select() \n " ); si ( -1 == ( nready = seleccionar ( maxfd + 1 , & readfds , NULL , NULL , NULL ))) morir ( "seleccionar()" );           ( void ) printf ( "Número de descriptores listos: %d \n " , nready );  para ( i = 0 ; i <= maxfd && nready > 0 ; i ++ ) { si ( FD_ISSET ( i , & readfds )) { nready -- ;            if ( i == sockfd ) { ( void ) printf ( "Intentando aceptar() nuevas conexiones \n " );      si ( -1 == ( nuevo = aceptar ( sockfd , NULL , NULL ))) { si ( EWOULDBLOCK != errno ) morir ( "aceptar()" );              romper ; }  demás {  si ( -1 == ( fcntl ( nuevo , F_SETFD , O_NONBLOCK ))) morir ( "fcntl()" );       FD_SET ( nuevo , & maestro );  si ( maxfd < nuevo ) maxfd = nuevo ; } }         else { ( void ) printf ( "recv() datos de uno de los descriptores \n " );   nbytes = recv ( i , buffer , sizeof ( buffer ), 0 ); si ( nbytes <= 0 ) { si ( EWOULDBLOCK != errno ) morir ( "recv()" );                romper ; }  buffer [ nbytes ] = '\0' ; printf ( "%s" , buffer );     ( void ) printf ( "%zi bytes recibidos. \n " , nbytes );  cerrar ( i ); FD_CLR ( i , & master );   } }  } } devuelve 0 ; }  void die ( const char * msg ) { perror ( msg ); salir ( FALLO_SALIDA ); }     

Véase también

Referencias

  1. ^ Computer Systems Research Group (1994). «select, pselect — multiplexación de E/S sincrónica». Referencia cruzada BSD . NetBSD .
  2. ^ "Métodos de procesamiento de conexión". nginx .org .

Enlaces externos