modelos select, poll y epoll

El último artículo presentó 5 modelos IO para la programación de redes Unix. Este artículo presenta los modelos select, poll y epoll ampliamente utilizados en la multiplexación IO. La idea principal de la multiplexación IO es que ya no existe. La aplicación monitorea las conexiones del cliente por sí misma, en su lugar, el kernel monitorea los archivos de la aplicación

Seleccione

/* @Param:
   nfds: 		监控的文件描述符集里最大文件描述符加1,因为此参数会告诉内核检测前多少个文件描述符的状态
   readfds:	监控读数据文件描述符集合,传入传出参数
   writefds:	监控写数据文件描述符集合,传入传出参数
   exceptfds:	监控异常发生文件描述符集合,如带外数据到达异常,传入传出参数
   timeout:	定时阻塞监控时间,3种情况: 
                   1. NULL(永远等下去); 
                   2. 设置timeval,等待固定时间; 
                   3. 设置timeval里时间均为0,检查描述字后立即返回,轮询
 */
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
  1. No hay mucha diferencia entre usar el modelo de selección para procesar solicitudes de E / S y el modelo de bloqueo síncrono. Hay incluso más operaciones adicionales para agregar sockets de monitoreo y llamar a la función de selección. La eficiencia es peor, pero el modelo seleccionado puede procesar E / S de múltiples sockets al mismo tiempo en una solicitud de subproceso, es decir, si el número de conexiones procesadas no es muy alto, el servidor web que usa select no es necesariamente mejor que el servidor web que usa multi-subprocesos + bloqueo de IO, y el retraso puede ser mayor . La ventaja de seleccionar no es para una sola conexión. Procesamiento más rápido, pero en poder manejar más conexiones
  2. Cada vez que llama a select, necesita copiar la colección fd_set del modo de usuario al modo kernel. Si la colección fd_set es grande, la sobrecarga también es muy alta.
  3. Select usa un modelo de sondeo. Cada vez que llama a select, debe recorrer todo el fd_set pasado en el kernel. Si la colección fd_set es grande, la sobrecarga también es alta
  4. Para reducir el daño de rendimiento causado por la copia y el sondeo de datos fd_set, el kernel limita el tamaño del conjunto fd_set monitoreado. Esto está controlado por la macro FD_SETSIZE. Generalmente, es 1024 para plataformas de 32 bits y 2048 para 64 bits. plataformas. Simplemente cambia el proceso. La cantidad de descriptores de archivos abiertos no cambia la cantidad de archivos de monitoreo seleccionados

encuesta

/*  @Param
	struct pollfd {
		int fd;           /* 文件描述符 */
		short events;     /* 监控的事件 */
		short revents;    /* 监控事件中满足条件返回的事件 */
	};

*/

int poll(struct pollfd *fds, nfds_t nfds, int timeout);
  1. Poll es esencialmente lo mismo que select, pero no tiene límite en el número máximo de conexiones. La razón es que se almacena en base a una lista vinculada. Copia los descriptores de archivo pasados ​​por el usuario al espacio del kernel y luego consulta el fd correspondiente Si el dispositivo está listo, agregue un elemento a la cola de espera del dispositivo y continúe atravesando. Si no se encuentra ningún dispositivo listo después de atravesar todos los fd, el proceso actual se suspenderá hasta que el dispositivo esté listo o se agote el tiempo de espera activo, y tienen que ser despertados Traverse fd de nuevo
  2. El sondeo solo resuelve el límite del número de descriptores de archivos que seleccionan monitores y no cambia la sobrecarga de rendimiento causada por copiar descriptores de archivos del espacio del programa (espacio del usuario) al espacio del kernel y sondear todos los descriptores de archivos en la parte inferior del kernel para cada uno. llamada.

epoll

/* 创建一个epoll句柄,参数size用来告诉内核监听的文件描述符的个数,跟内存大小有关 */
int epoll_create(int size);

/* 控制某个epoll监控的文件描述符上的事件:注册、修改、删除 */
/*  @Param
    epfd:	epoll_creat的句柄
    op:	表示动作,用3个宏来表示:
			EPOLL_CTL_ADD (注册新的fd到epfd),
			EPOLL_CTL_MOD (修改已经注册的fd的监听事件),
			EPOLL_CTL_DEL (从epfd删除一个fd);
    event:	告诉内核需要监听的事件
            struct epoll_event {
			    __uint32_t events; // Epoll events 
			    epoll_data_t data; // User data variable 
		    };
			typedef union epoll_data {
				void *ptr;
				int fd;
				uint32_t u32;
				uint64_t u64;
			} epoll_data_t;
*/
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

/* 等待所监控文件描述符上有事件的产生 */
/*  @Param
    epfd:	    epoll_creat的句柄
    events:	用来存内核得到事件的集合
	maxevents:	告之内核这个events有多大,这个maxevents的值不能大于创建epoll_create()时的size
	timeout:	是超时时间
			    -1:	阻塞
			     0:	立即返回,非阻塞
			    >0:	指定毫秒
    返回值:	    成功返回有多少文件描述符就绪,时间到时返回0,出错返回-1
*/
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
  1. Epoll es una versión mejorada de IO multiplexing select / poll en Linux. Puede mejorar significativamente la utilización de la CPU del sistema en el caso de una gran cantidad de conexiones simultáneas y solo una pequeña cantidad de programas activos, porque reutiliza conjuntos de descriptores de archivos para ofrecer resultados. En lugar de obligar a los desarrolladores a preparar el conjunto de descriptores de archivo que se escucharán cada vez antes de esperar un evento, otra razón es que cuando se adquieren eventos, no es necesario atravesar todo el conjunto de descriptores escuchados, siempre y cuando los atraviese. que están siendo escuchados por el kernel. El evento IO se activa de forma asincrónica y se une al conjunto de descriptores de la cola Ready (utilizando un mecanismo de devolución de llamada, no un método de sondeo, y la eficiencia no disminuirá a medida que aumenta el número de FD). y los FD disponibles llamarán a la función de devolución de llamada)
  2. Aunque epoll se ve muy bien en la superficie, el rendimiento de select y poll puede ser mejor que epoll cuando el número de conexiones es pequeño y las conexiones son muy activas, porque epoll se basa en una gran cantidad de devoluciones de llamada de funciones.
  3. Además de proporcionar disparadores de nivel para eventos de E / S de selección / sondeo (Disparo por nivel, siempre que haya datos), epoll también proporciona disparos por flanco (Disparo por flanco, que se dispara solo cuando llegan datos, independientemente de si el búfer todavía está disponible). data), lo que hace posible que los programas de espacio de usuario almacenen en caché el estado de IO, reduzcan la llamada de epoll_wait / epoll_pwait y mejoren la eficiencia de la aplicación

Artículo de referencia:
[1] ¿Por qué son tan populares Redis, Nginx y Netty?
[2]. IO-Síncrona, Asíncrona, Bloqueo, No-bloqueo (Remedio)
[3]. Programación de Red Unix Síncrona / Asíncrona / Bloqueo / Sin Bloqueo
[4]. Programación de Red UNIX-Socket Síncrono / Asíncrono Bloqueo / No- bloqueo

Si hay alguna infracción, comuníquese para eliminarla. Si hay un error, corríjame, gracias

Supongo que te gusta

Origin blog.csdn.net/xiao_ma_nong_last/article/details/105236406
Recomendado
Clasificación