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