¿Cuáles son las diferencias entre sondeo y selección?

Respuestas:

90

Creo que esto responde a tu pregunta:

De Richard Stevens ([email protected]):

La diferencia básica es que fd_set de select () es una máscara de bits y, por lo tanto, tiene un tamaño fijo. Es posible que el kernel no limite este tamaño cuando se compila el kernel, lo que permite que la aplicación defina FD_SETSIZE a lo que quiera (como implican los comentarios en el encabezado del sistema hoy) pero requiere más trabajo. El núcleo de 4.4BSD y la función de biblioteca de Solaris tienen este límite. Pero veo 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 debería presentar un informe de error de Solaris sobre esto y ver si alguna vez se soluciona.

Sin embargo, con poll (), el usuario debe asignar una matriz de estructuras pollfd y pasar el número de entradas en esta matriz, por lo que no hay un límite fundamental. Como señala Casper, menos sistemas tienen poll () que select, por lo que este último es más portátil. Además, con las implementaciones originales (SVR3) no puede establecer el descriptor en -1 para decirle al núcleo que ignore una entrada en la estructura pollfd, lo que dificulta la eliminación de entradas de la matriz; SVR4 soluciona esto. Personalmente, siempre uso select () y rara vez sondeo (), porque también transfiero mi código a entornos BSD. Alguien podría escribir una implementación de poll () que use select (), para estos entornos, pero nunca he visto uno. POSIX 1003.1g está estandarizando tanto select () como poll ().

Actualización de octubre de 2017:

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

Para el desarrollo moderno, probablemente no desee utilizarlo select(), aunque no hay nada explícitamente malo en ello. poll(), y es una evolución más moderna epoll(), proporciona las mismas características (y más) que select()sin sufrir las limitaciones en él.

akappa
fuente
15
¿Cuándo se escribió la respuesta de Stevens? ¿Sigue siendo válido el comentario sobre poll () que no está disponible en BSD? MacOS X (que se basa en parte en BSD) tiene poll (), y el estándar POSIX (POSIX 2008) lo requiere.
Jonathan Leffler
12
Rich Stevens falleció en septiembre de 1999, por lo que la respuesta tiene que ser más antigua que eso. Menciona haber visto un nuevo cambio en BSD / OS 2.1, que se lanzó en enero de 1996, probablemente en ese momento.
alanc
2
No lo creo Respuesta publicada hace 5 años, me topé con ella, la dejé abierta en el navegador. Al día siguiente, el autor edita y mejora la respuesta. SO me notifica con la actualización en la página usando AJAX / websocket. es por eso que SO es genial
Steven Lu
9
@StevenLu Sí, pero desafortunadamente no se sabe si AJAX / websocket está usando selecto poll:(
Christopher Schultz
> Alguien podría escribir una implementación de poll () que use select (), para estos entornos, pero nunca he visto una. Java lo hace ;-)
Sergey Mashkov
229

La select()llamada hace que cree tres máscaras de bits para marcar qué conectores y descriptores de archivos desea observar para leer, escribir y errores, y luego el sistema operativo marca cuáles de hecho han tenido algún tipo de actividad; poll()tiene que crear una lista de ID de descriptores, y el sistema operativo marca cada uno de ellos con el tipo de evento que ocurrió.

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

  1. Por lo general, hay más de mil descriptores de archivo potenciales disponibles para un proceso. Si un proceso de larga duración solo tiene 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 select()debe ser lo suficientemente grande como para acomodar ese descriptor más alto, por lo que se obtendrán rangos enteros de cientos de bits asegúrese de que el sistema operativo tenga que recorrer cada select()llamada solo para descubrir que no están configurados.

  2. Una vez que select()regresa, la persona que llama tiene que recorrer 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 están marcadas con la lista de descriptores de archivos que desea escuchar. Debe reconstruir toda la máscara de bits a partir de alguna otra lista que tenga en la memoria, o debe mantener 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 select()llamada.

Por lo tanto, el poll()enfoque funciona mucho mejor porque puede seguir reutilizando la misma estructura de datos.

De hecho, poll()ha inspirado otro mecanismo en los núcleos modernos de Linux: epoll()que mejora aún más el mecanismo para permitir otro salto en la 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()en este punto se considera tan ineficiente y anticuado que ni siquiera aparece 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 brinda aún más detalles sobre las diferencias:

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

Brandon Rhodes
fuente
1
Y +1 para vincular a un ejemplo de uso de epoll en python: parece que hay algunos ejemplos interesantes allí, y voy a tener que probarlos ...
Allen George
+1 por explicar la respuesta; -1 por mencionar epoll pero no kqueue
Good Person
Esta respuesta hace que parezca que epoll siempre es preferible
user3467349
0

Ambos son lentos y en su mayoría iguales , ¡pero diferentes en tamaño y algún tipo de características!

Cuando escribes un iterador, ¡debes copiar el conjunto de selectcada vez! Si bien se pollha solucionado este tipo de problema para tener un código hermoso. Otra diferencia es que pollpuede manejar más de 1024 descriptores de archivo (FD) de forma predeterminada. pollpuede manejar diferentes eventos para hacer que el programa sea más legible en lugar de tener muchas variables para manejar este tipo de trabajo. Las operaciones en polly selectson lineales y lentas debido a que tiene muchas comprobaciones.

Amir Fo
fuente