¿Cuáles son las diferencias entre poll y select?


Me refiero al estándar POSIX select y poll llamadas a la API del sistema C.

 144
Author: Steven Lu, 2009-06-09

2 answers

Creo que esto responde a tu pregunta:

De Richard Stevens ([email protected]):

La diferencia básica es que el fd_set de select () es una máscara de bits y por lo tanto tiene algún tamaño fijo. Sería posible que el kernel no limitar este tamaño cuando se compila el núcleo, permitiendo la aplicación para definir FD_SETSIZE a lo que quiera (como los comentarios en el encabezado del sistema implican hoy) pero se necesita más trabajo. 4.4 BSD kernel y la función de biblioteca Solaris tiene este límite. Pero yo vea que BSD / OS 2.1 ahora se ha codificado para evitar este límite, por lo que es factible, solo una pequeña cuestión de programación. :- ) Alguien debe presentar una Solaris informe de error sobre esto, y ver si alguna vez se arregla.

Con poll(), sin embargo, el usuario debe asignar una matriz de pollfd estructuras, y pasar el número de entradas en esta matriz, por lo que hay sin límite fundamental. Como señala Casper, menos sistemas tienen poll () que seleccionar, así que este último es más portátil. También, con original implementations (SVR3) no se pudo establecer el descriptor en -1 para tell el núcleo ignoraba una entrada en la estructura pollfd, que lo hacía es difícil eliminar entradas de la matriz; SVR4 evita esto. Personalmente, siempre uso select () y rara vez poll (), porque código para entornos BSD también. Alguien podría escribir una implementación de poll () que usa select (), para estos entornos, pero nunca he visto uno. Ambos select () y poll () están siendo estandarizados por POSIX 1003,1 g.

Actualización de octubre de 2017:

El correo electrónico mencionado anteriormente es al menos tan antiguo como 2001; el comando poll() ahora (2017) es compatible con todos los sistemas operativos modernos, incluido BSD. De hecho, algunas personas creen que select() debe estar en desuso . Dejando de lado las opiniones, los problemas de portabilidad en torno a poll() ya no son una preocupación en los sistemas modernos. Además, epoll() se ha desarrollado desde entonces (puede leer la página de manual ), y continúa aumentando en popularidad.

Para el desarrollo moderno probablemente no quieras usar select(), aunque no hay nada explícitamente malo en ello. poll(), y es la evolución más moderna epoll(), proporcionan las mismas características (y más) que select() sin sufrir las limitaciones en ellas.

 76
Author: akappa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-18 05:21:03

La llamada select() le hace crear tres máscaras de bits para marcar qué sockets y descriptores de archivo desea vigilar la lectura, escritura y errores, y luego el sistema operativo marca cuáles de hecho han tenido algún tipo de actividad; poll() le hace crear una lista de identificadores de descriptores, y el sistema operativo marca cada uno de ellos con el tipo del evento que ocurrió.

El método select() es bastante torpe e ineficiente.

  1. Por lo general, hay más de un miles de descriptores de archivo potenciales disponibles para un proceso. Si un proceso de larga duración tiene solo unos pocos descriptores abiertos, pero al menos a uno de ellos se le ha asignado un número alto, entonces la máscara de bits pasada a select() tiene que ser lo suficientemente grande como para acomodar ese descriptor más alto - por lo que se desactivarán rangos enteros de cientos de bits que el sistema operativo tendrá que recorrer en bucle en cada llamada select() solo para descubrir que están desactivados.

  2. Una vez que select() regresa, el llamante tiene que hacer un bucle las tres máscaras de bits para determinar qué eventos tuvieron lugar. En muchas aplicaciones típicas, solo uno o dos descriptores de archivo obtendrán tráfico nuevo en un momento dado, sin embargo, las tres máscaras de bits deben leerse hasta el final para descubrir qué descriptores son.

  3. Debido a que el sistema operativo le indica sobre la actividad reescribiendo las máscaras de bits, se arruinan y ya no se marcan con la lista de descriptores de archivos que desea escuchar. O tienes que reconstruir la máscara de bits completa de alguna otra lista que guardes en memoria, o tienes que guardar una copia duplicada de cada máscara de bits y memcpy() el bloque de datos encima de las máscaras de bits arruinadas después de cada llamada select().

Así que el enfoque poll() funciona mucho mejor porque puede seguir reutilizando la misma estructura de datos.

De hecho, poll() ha inspirado otro mecanismo en los núcleos de Linux modernos: epoll() que mejora aún más el mecanismo para permitir otro salto en escalabilidad, ya que los servidores de hoy en día a menudo quieren manejar decenas de miles de conexiones a la vez. Esta es una buena introducción al esfuerzo:

Http://scotdoyle.com/python-epoll-howto.html

Si bien este enlace tiene algunos gráficos agradables que muestran los beneficios de epoll() (notará que select() es en este punto considerado tan ineficiente y anticuado que ni siquiera obtiene una línea en estos gráficos!):

Http://lse.sourceforge.net/epoll/index.html


Actualización: Aquí hay otra pregunta de desbordamiento de pila, cuya respuesta da aún más detalles sobre las diferencias:

Advertencias de los reactores select/poll vs. epoll en Twisted

 214
Author: Brandon Rhodes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:31:35