Pregunta

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 embargo

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 un desperdicio de recursos tener que vaciar y llenar el juego cada vez.

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

¿Fue útil?

Solución

select modifica sus argumentos. Realmente tienes que reiniciarlo cada vez.

Si le preocupa la sobrecarga, el costo de procesar el FD_SET completo en el núcleo es algo más significativo que el costo de FD_ZERO. Solo querrá pasar su fd máximo, no FD_SETSZIZE, para minimizar el procesamiento del kernel. En tu ejemplo:

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

Para un caso más complejo con múltiples fds, generalmente terminas manteniendo una variable máxima:

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

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


Si va a tener una gran cantidad de descriptores de archivos y le preocupa la sobrecarga de leerlos, debe buscar algunas de las alternativas para seleccionar (). No menciona el sistema operativo que está utilizando, pero para sistemas operativos tipo Unix hay algunos:

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

Las API son diferentes, pero todas son esencialmente una interfaz de 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á de los eventos en ese fd sin tener que pasarlo de nuevo continuamente.

Otros consejos

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

Siempre inicialice el fd_set justo antes de usarlo.

Así es como funciona select. Funciona mejor y tiene más sentido si tiene más de un socket. Ese es el punto: estás seleccionando muchos zócalos. Si desea leer desde un socket, solo léalo o recíbalo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top