resfriado - porque es malo el cafe con leche
comportamiento irritante select() en c (3)
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. 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 aún mejor, tal vez una sugerencia de cómo evitarlo?
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 en muchos sockets. Si quieres leer desde un socket, solo léelo o recúbelo.
Lee la página de selección de manual. 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.
Siempre inicialice el fd_set justo antes de usarlo.
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 tu ejemplo:
switch (select((sd + 1),&set,NULL,NULL,&timeout))
Para un caso más complejo con múltiples fds, generalmente se termina 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 los tramos, debería ver 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 kernel 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.