Aumentar el límite de FD_SETSIZE y seleccionar

Quiero boost el valor de macro FD_SETSIZE para mi sistema. ¿Hay alguna manera de boost FD_SETSIZE para que la selección no falle?

Según los estándares, no hay forma de boost FD_SETSIZE . Algunos progtwigs y bibliotecas (libevent viene a la mente) tratan de evitar esto asignando espacio adicional para el objeto fd_set y pasando valores mayores que FD_SETSIZE a las macros FD_* , pero esta es una muy mala idea ya que las implementaciones robustas pueden llevar a cabo la comprobación de límites en el argumento y abortar si está fuera de rango.

Tengo una solución alternativa que siempre debería funcionar (aunque los estándares no lo requieran). En lugar de un único objeto fd_set , asigne una matriz de ellos lo suficientemente grande como para contener el máximo fd que necesitará, luego use FD_SET(fd%FD_SETSIZE, &fds_array[fd/FD_SETSIZE]) etc. para acceder al conjunto.

También sugiero usar una poll si es posible. Y existen varias bibliotecas de procesamiento de “eventos” como libevent o libev (o las habilidades de eventos de Glib de GTK, o QtCore , etc.) que deberían ayudarte. También hay cosas como epoll . Y tu problema está relacionado con C10k

Sería mejor (y fácil) reemplazar con una encuesta. Generalmente poll () es un simple reemplazo directo para select () y no está limitado por el 1024 de FD_SETSIZE …

 fd_set fd_read; int id = 42; FD_ZERO(fd_read); FD_SET(id, &fd_read); struct timeval tv; tv.tv_sec = 5; tv.tv_usec = 0; if (select(id + 1, &fd_read, NULL, NULL, &tv) != 1) { // Error. } 

se convierte en:

 struct pollfd pfd_read; int id = 42; int timeout = 5000; pfd_read.fd = id; pfd_read.events = POLLIN; if (poll(&pfd_read, 1, timeout) != 1) { // Error } 

Necesita incluir poll.h para la estructura pollfd.

Si necesita escribir y leer, configure la bandera de eventos como POLLIN | POLLOUT.

Es posible boost FD_SETSIZE superando __FD_SETSIZE (definido en sys/types.h ) antes de incluir sys/select.h .

Procediendo así, podemos establecer FD_SETSIZE en 2048 :

 #include  #undef __FD_SETSIZE #define __FD_SETSIZE 2048 #include  #include  int main() { printf("FD_SETSIZE:%d sizeof(fd_set):%d\n",FD_SETSIZE,sizeof(fd_set)); return 0; } 

se imprimirá:

FD_SETSIZE: 2048 sizeof (fd_set): 128

Sin embargo, si FD_SETSIZE sigue el valor modificado, sizeof (fd_set) debe ser 256 (2048/8) y no 128 (1024/8). Esto es porque incluir sys/types.h ya define fd_set con 1024.


Para usar un fd_set más fd_set , es posible definir uno más grande como este:

 #include  #include  #define EXT_FD_SETSIZE 2048 typedef struct { long __fds_bits[EXT_FD_SETSIZE / 8 / sizeof(long)]; } ext_fd_set; int main() { ext_fd_set fd; int s; printf("FD_SETSIZE:%d sizeof(fd):%ld\n", EXT_FD_SETSIZE, sizeof(fd)); FD_ZERO(&fd); while ( ((s=dup(0)) != -1) && (s < EXT_FD_SETSIZE) ) { FD_SET(s, &fd); } printf("select:%d\n", select(EXT_FD_SETSIZE,(fd_set*)&fd, NULL, NULL, NULL)); return 0; } 

Esto imprime:

FD_SETSIZE: 2048 sizeof (fd): 256

seleccionar: 2045


Para abrir más de 1024 descriptores de archivo, es necesario boost el límite utilizando, por ejemplo, ulimit -n 2048 .

de hecho, HAY una forma de boost FD_SETSIZE en Windows. está definido en winsock.h y por microsoft en sí mismo puede boostlo simplemente definiéndolo ANTES de incluir winsock.h

http://support.microsoft.com/kb/111855

Lo hago todo el tiempo y no he tenido problemas El mayor valor que he usado fue de alrededor de 5000 para un servidor que estaba desarrollando