2008-11-12 10 views
6
while (xxx) { 
    timeout.tv_sec=TIMEOUT; 
    timeout.tv_usec=0; 
    FD_ZERO(&set); 
    FD_SET(sd,&set); 

    switch (select(FD_SETSIZE,&set,NULL,NULL,&timeout)) 
    xxxxx 
} 

funciona bien, sin embargoirritante seleccionan la conducta() en c

FD_ZERO(&set); 
FD_SET(sd,&set); 

while (xxx) { 
    timeout.tv_sec=TIMEOUT; 
    timeout.tv_usec=0; 

    switch (select(FD_SETSIZE,&set,NULL,NULL,&timeout)) 
    xxxxx 
} 

no lo hace. Funciona la primera vez, pero la próxima vez que se ejecuta a través del ciclo while obtiene un tiempo de espera incluso si el socket sd recibe datos. Me parece una pérdida de recursos tener que vaciar y llenar todo el tiempo.

¿Alguien tiene una buena explicación de por qué esto es, y mejor aún, tal vez una sugerencia de cómo evitarlo?

+0

Creo que parte del código que sacó puede ser importante para entender por qué esto se está comportando como está. – SoapBox

Respuesta

12

select modifica sus argumentos. Realmente tiene que volver a inicializarlo cada vez.

Si le preocupan los gastos generales, el costo de procesar el FD_SET completo en el kernel es algo más significativo que el costo de FD_ZERO. Solo querría pasar su fd máxima, no FD_SETSZIZE, para minimizar el procesamiento del kernel. En su ejemplo:

switch (select((sd + 1),&set,NULL,NULL,&timeout)) 

Para un caso más complejo, con múltiples FDS, por lo general terminan manteniendo una variable max:

FD_SET(sd,&set); 
if (sd > max) max = sd; 
... repeat many times... 

switch (select((max + 1),&set,NULL,NULL,&timeout)) 


Si usted tiene un gran número de descriptores de archivos y está Preocupado por la sobrecarga de traficar con ellos, debe mirar algunas de las alternativas para seleccionar(). Usted no menciona el sistema operativo que está usando, pero para sistemas operativos basados ​​en Unix hay algunas:

  • para Linux, epoll()
  • para FreeBSD/NetBSD/OpenBSD/MacOS X, kqueue ()
  • para Solaris,/dev/sondeo

Las APIs son diferentes, pero todos ellos son esencialmente una interfaz del núcleo con estado para mantener un conjunto de descripciones de archivos activos. Una vez que se agrega un fd al conjunto, se le notificarán los eventos en ese fd sin tener que volver a pasarlo continuamente.

+0

Gracias por una gran respuesta :) – deadcyclo

+1

Para una alternativa para seleccionar(), ¿por qué no sondear() que, a diferencia de los que menciona, es el mismo en muchos Unices? – bortzmeyer

+1

encuesta() es mejor porque no tiene que reiniciar su matriz cada vez, pero todavía está copiando una estructura grande dentro y fuera del kernel en cada llamada. Si tiene muchos fds, las otras alternativas evitan esta sobrecarga constante modificando el conjunto de fd en el kernel. – DGentry

7

Lea la página de selección de man. El conjunto devuelto es solo los descriptores de archivos que están listos para ser utilizados. Se supone que debes usar FD_ISSET para verificar cada uno si está configurado o no.

Inicialice siempre el fd_set justo antes de usarlo.

+0

Conozco el FD_ISSET, pero aún no lo he incluido, porque a partir de ahora solo estoy enumerando un socket (más adelante voy a agregar más sockets). Entonces, ¿ahora hay forma de poder "reutilizar" sin tener que establecer fd_set primero? – deadcyclo

+0

El comportamiento documentado de select() incluye la modificación de los conjuntos en su lugar. Para citar The Pragmatic Programmer, "'select' no está roto". – bk1e

0

Así es como funciona la selección. Funciona mejor, y tiene más sentido, si tiene más de un socket. Ese es el punto: estás seleccionando en muchos sockets. Si quieres leer desde un socket, solo léelo o recúbelo.

+1

La lectura no ofrece tiempo de espera. De ahí el uso de select. + el hecho de que agregaré un segundo socket más adelante en la etapa de desarrollo. – deadcyclo

+0

Solo para seguir ofreciendo alternativas: si sd es un socket, puede usar setsockopt (sd, SO_RCVTIMEO, ...) para agregar un tiempo de espera de lectura.Sin embargo, si va a agregar un segundo socket más adelante, seleccione es la mejor opción para seguir. – DGentry

Cuestiones relacionadas