Quelles sont les différences entre poll et select?

Réponses:

90

Je pense que cela répond à votre question:

De Richard Stevens ([email protected]):

La différence fondamentale est que le fd_set de select () est un masque de bits et a donc une taille fixe. Il serait possible pour le noyau de ne pas limiter cette taille lors de la compilation du noyau, permettant à l'application de définir FD_SETSIZE à ce qu'elle veut (comme les commentaires dans l'en-tête du système l'impliquent aujourd'hui) mais cela demande plus de travail. 4.4 Le noyau de BSD et la fonction de bibliothèque Solaris ont tous deux cette limite. Mais je vois que BSD / OS 2.1 a maintenant été codé pour éviter cette limite, donc c'est faisable, juste une petite question de programmation. :-) Quelqu'un devrait déposer un rapport de bogue Solaris à ce sujet, et voir si cela est jamais corrigé.

Avec poll (), cependant, l'utilisateur doit allouer un tableau de structures pollfd et transmettre le nombre d'entrées dans ce tableau, il n'y a donc pas de limite fondamentale. Comme le note Casper, moins de systèmes ont poll () que select, donc ce dernier est plus portable. De plus, avec les implémentations d'origine (SVR3), vous ne pouviez pas définir le descripteur sur -1 pour indiquer au noyau d'ignorer une entrée dans la structure pollfd, ce qui rendait difficile la suppression des entrées du tableau; SVR4 contourne cela. Personnellement, j'utilise toujours select () et rarement poll (), car je porte aussi mon code dans les environnements BSD. Quelqu'un pourrait écrire une implémentation de poll () qui utilise select (), pour ces environnements, mais je n'en ai jamais vu. Les deux select () et poll () sont normalisés par POSIX 1003.1g.

Mise à jour d'octobre 2017:

L'e-mail référencé ci-dessus est au moins aussi vieux que 2001; la poll()commande est désormais (2017) prise en charge sur tous les systèmes d'exploitation modernes, y compris BSD. En fait, certaines personnes pensent que cela select() devrait être déconseillé . Opinions mises à part, les problèmes de portabilité poll()ne sont plus un problème sur les systèmes modernes. De plus, epoll()a depuis été développé (vous pouvez lire la page de manuel ), et continue de gagner en popularité.

Pour le développement moderne, vous ne voulez probablement pas utiliser select(), bien qu'il n'y ait rien de mal à cela. poll(), et c'est une évolution plus moderne epoll(), offrent les mêmes fonctionnalités (et plus) que select()sans souffrir des limitations qui s'y trouvent.

Akappa
la source
15
Quand la réponse de Stevens a-t-elle été écrite? Le commentaire sur la non-disponibilité de poll () sur BSD s'applique-t-il toujours? MacOS X (qui est en partie basé sur BSD) a poll (), et le standard POSIX (POSIX 2008) l'exige.
Jonathan Leffler
12
Rich Stevens est décédé en septembre 1999, donc la réponse doit être plus ancienne que cela. Il mentionne avoir vu un nouveau changement dans BSD / OS 2.1, qui a été publié en janvier 1996, donc probablement à l'époque.
alanc
2
Je n'y crois pas. Réponse postée il y a 5 ans, je tombe dessus, la laisse ouverte dans le navigateur. Le lendemain, l'auteur modifie et améliore la réponse. SO me notifie avec mise à jour sur la page en utilisant AJAX / websocket. c'est pourquoi SO est génial
Steven Lu
9
@StevenLu Oui, mais malheureusement aucun mot sur le fait que AJAX / websocket utilise selectou poll:(
Christopher Schultz
> Quelqu'un pourrait écrire une implémentation de poll () qui utilise select (), pour ces environnements, mais je n'en ai jamais vu. Java le fait ;-)
Sergey Mashkov
229

L' select()appel vous demande de créer trois masques de bits pour marquer les sockets et les descripteurs de fichiers que vous souhaitez surveiller pour la lecture, l'écriture et les erreurs, puis le système d'exploitation marque ceux qui ont en fait eu une sorte d'activité; poll()avez-vous créé une liste d'identifiants de descripteurs et que le système d'exploitation marque chacun d'eux avec le type d'événement qui s'est produit.

La select()méthode est plutôt maladroite et inefficace.

  1. Il existe généralement plus d'un millier de descripteurs de fichiers potentiels disponibles pour un processus. Si un processus de longue durée n'a que quelques descripteurs ouverts, mais qu'au moins l'un d'entre eux a reçu un nombre élevé, alors le masque de bits transmis select()doit être suffisamment grand pour accueillir ce descripteur le plus élevé - des plages entières de centaines de bits ne pas indiquer que le système d'exploitation doit effectuer une boucle à chaque select()appel juste pour découvrir qu'ils ne sont pas définis.

  2. Une fois select()retourné, l'appelant doit boucler les trois masques de bits pour déterminer quels événements ont eu lieu. Dans de très nombreuses applications typiques, seuls un ou deux descripteurs de fichier recevront du nouveau trafic à un moment donné, mais les trois masques de bits doivent être lus jusqu'à la fin pour découvrir de quels descripteurs il s'agit.

  3. Étant donné que le système d'exploitation vous signale l'activité en réécrivant les masques de bits, ils sont ruinés et ne sont plus marqués avec la liste des descripteurs de fichiers que vous souhaitez écouter. Soit vous devez reconstruire le masque de bits entier à partir d'une autre liste que vous gardez en mémoire, soit vous devez conserver une copie en double de chaque masque de bits et memcpy()du bloc de données au-dessus des masques de bits ruinés après chaque select()appel.

L' poll()approche fonctionne donc beaucoup mieux car vous pouvez continuer à réutiliser la même structure de données.

En fait, poll()a inspiré encore un autre mécanisme dans les noyaux Linux modernes: epoll()ce qui améliore encore plus le mécanisme pour permettre un autre saut dans l'évolutivité, car les serveurs d'aujourd'hui veulent souvent gérer des dizaines de milliers de connexions à la fois. Ceci est une bonne introduction à l'effort:

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

Bien que ce lien présente de jolis graphiques montrant les avantages de epoll()(vous noterez qu'à select()ce stade, il est considéré comme si inefficace et démodé qu'il n'obtient même pas de ligne sur ces graphiques!):

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


Mise à jour: Voici une autre question Stack Overflow, dont la réponse donne encore plus de détails sur les différences:

Mises en garde concernant les réacteurs Select / Poll vs Epoll dans Twisted

Brandon Rhodes
la source
1
Et +1 pour créer un lien vers un exemple d'utilisation d'epoll en python - on dirait qu'il y a quelques exemples intéressants, et je vais devoir les essayer ...
Allen George
+1 pour expliquer la réponse; -1 pour mentionner epoll mais pas kqueue
Good Person
Cette réponse donne l'impression qu'epoll est toujours préférable
user3467349
0

Les deux sont lents et pour la plupart identiques , mais de taille et de fonctionnalités différentes!

Lorsque vous écrivez un itérateur, vous devez copier l'ensemble de selectchaque fois! Bien que pollce genre de problème ait été résolu pour avoir un beau code. Une autre différence est qu'il pollpeut gérer plus de 1024 descripteurs de fichiers (FD) par défaut. pollpeut gérer différents événements pour rendre le programme plus lisible au lieu d'avoir beaucoup de variables pour gérer ce genre de travail. Les opérations dans pollet selectest linéaire et lent en raison d'avoir beaucoup de contrôles.

Amir Fo
la source