välj (Unix)
select är ett systemanrop och applikationsprogrammeringsgränssnitt (API) i Unix-liknande och POSIX- kompatibla operativsystem för att undersöka statusen för filbeskrivningar för öppna in-/utgångskanaler. Välj systemanropet liknar pollningsfunktionen som introduceras i UNIX System V och senare operativsystem. Men med c10k-problemet har både select och poll ersatts av sådana som kqueue , epoll , /dev/poll och I/O-kompletteringsportar .
En vanlig användning av select utanför den angivna användningen av att vänta på filhandtag är att implementera en bärbar undersekundssömn . Detta kan uppnås genom att skicka NULL för alla tre fd_set-argument, och varaktigheten av den önskade sömnen som timeout-argument.
I programmeringsspråket C deklareras det valda systemanropet i rubrikfilen sys/select.h eller unistd.h och har följande syntax:
int select ( int nfds , fd_set * readfds , fd_set * writefds , fd_set * errorfds , struct timeval * timeout );
argument | beskrivning |
---|---|
nfds | Detta är ett heltal ett mer än maxvärdet för någon filbeskrivning i någon av uppsättningarna. Med andra ord, medan du lägger till filbeskrivningar till var och en av uppsättningarna måste du beräkna det maximala heltalsvärdet för dem alla, sedan öka detta värde med ett och sedan skicka detta som nfds. |
readfds | fd_set -typ som innehåller filbeskrivningarna som ska kontrolleras för att vara redo att läsa, och vid utdata indikerar vilka filbeskrivningar som är redo att läsas. Kan vara NULL . |
skrivfds | fd_set- typ som håller fildeskriptorerna som ska kontrolleras för att vara redo att skriva, och på utdata indikerar vilka filbeskrivningar som är redo att skriva. Kan vara NULL . |
errorfds | fd_set- typ som innehåller filbeskrivningarna som ska kontrolleras för feltillstånd som väntar, och vid utdata indikerar vilka filbeskrivningar som har feltillstånd väntande. Kan vara NULL . |
Paus | struktur av typen struct timeval som anger ett maximalt intervall att vänta på att valet ska slutföras. Om timeout-argumentet pekar på ett objekt av typen struct timeval vars medlemmar är 0, blockeras inte select() . Om timeout-argumentet är NULL, blockerar select() tills en händelse gör att en av maskerna returneras med ett giltigt (ej noll) värde. Linux kommer att uppdatera timeouten på plats för att indikera hur mycket tid som förflutit, även om detta beteende inte delas av de flesta andra Unix-system. |
fd_set-
typargument kan manipuleras med fyra verktygsmakron: FD_SET(), FD_CLR(), FD_ZERO() och FD_ISSET() .
Select returnerar det totala antalet bitar som ställts in i readfds, writefds och errorfds , eller noll om timeouten löpte ut, och -1 vid fel.
Uppsättningarna av filbeskrivningar som används i select är ändliga i storlek, beroende på operativsystem. Den nyare systemanropsundersökningen ger en mer flexibel lösning.
Exempel
0
0 0
0
0
0
#inkludera <stdio.h> #inkludera <stdlib.h> #inkludera <string.h> #inkludera <sys/types.h> #inkludera <sys/socket.h> #inkludera <netinet/in.h> #inkludera <netdb.h> #include <sys/select.h> #include <fcntl.h> #include <unistd.h> #include <err.h> #include <errno.h> #define PORT "9421" /* funktionsprototyper */ void die ( const char * ); int main ( int argc , char ** argv ) { int sockfd , new , maxfd , on = 1 , nready , i ; struct addrinfo * res0 , * res , tips ; char buffer [ BUFSIZ ]; fd_set master , readfds ; int fel ; ssize_t nbytes ; ( void ) memset ( & tips , '\0' , sizeof ( struct addrinfo )); tips . ai_family = AF_INET ; tips . ai_socktype = SOCK_STREAM ; tips . ai_protocol = IPPROTO_TCP ; tips . ai_flags = AI_PASSIVE ; if ( != ( error = getaddriinfo ( NULL , PORT , & hints , & res0 ))) errx ( EXIT_FAILURE , "%s" , gai_strerror ( error )); for ( res = res0 ; res ; res = res -> ai_next ) { if ( -1 == ( sockfd = socket ( res -> ai_family , res -> ai_socktype , res -> ai_protocol ))) { perror ( "socket( )" ); fortsätta ; } if ( -1 == ( setsockopt ( sockfd , SOL_SOCKET , SO_REUSEADDR , ( char * ) & on , sizeof ( int )))) { perror ( "setsockopt()" ); fortsätta ; } if ( -1 == ( bind ( sockfd , res -> ai_addr , res -> ai_addrlen ))) { perror ( "bind()" ); fortsätta ; } bryta ; } if ( -1 == sockfd ) avsluta ( EXIT_FAILURE ); freeaddrinfo ( res0 ); if ( -1 == ( lyssna ( sockfd , 32 ))) die ( "lyssna()" ); if ( -1 == ( fcntl ( sockfd , F_SETFD , O_NONBLOCK ))) dör ( "fcntl()" ); FD_ZERO ( & master ); FD_ZERO ( & readfds ); FD_SET ( sockfd , & master ); maxfd = sockfd ; while ( 1 ) { memcpy ( & readfds , & master , sizeof ( master )); ( void ) printf ( "kör select() \n " ); if ( -1 == ( nready = select ( maxfd + 1 , & readfds , NULL , NULL , NULL ))) die ( "select()" ); ( void ) printf ( "Antal redo deskriptor: %d \n " , nready ); for ( i = ; i <= maxfd && nready > ; i ++ ) { if ( FD_ISSET ( i , & readfds )) { nready -- ; if ( i == sockfd ) { ( void ) printf ( "Försöker acceptera() nya anslutning(ar) \n " ); if ( -1 == ( new = accept ( sockfd , NULL , NULL ))) { if ( EWOULDBLOCK != errno ) die ( "accept()" ); bryta ; } else { if ( -1 == ( fcntl ( new , F_SETFD , O_NONBLOCK ))) die ( "fcntl()" ); FD_SET ( ny , & master ); if ( maxfd < new ) maxfd = new ; } } else { ( void ) printf ( "recv() data från en av deskriptorerna \n " ); nbytes = recv ( i , buffert , storlek på ( buffert ), ); if ( nbytes <= ) { if ( EWOULDBLOCK != errno ) die ( "recv()" ); bryta ; } buffert [ nbytes ] = '\0' ; printf ( "%s" , buffert ); ( void ) printf ( "%zi bytes mottagna. \n " , nbytes ); nära ( i ); FD_CLR ( i , & master ); } } } } returnera ; } void die ( const char * msg ) { perror ( msg ); avsluta ( EXIT_FAILURE ); }
Se även
externa länkar
- The Single UNIX Specification , Version 4 från The Open Group – System Interfaces Reference,
- man-sidor för
select(2)
i FreeBSD, NetBSD, OpenBSD och DragonFly BSD