Quelles sont les différences entre sondage et sélection?

Je me réfère à la norme de sélection et d’ interrogation du système POSIX C API appels.

Je pense que cela répond à votre question:

De Richard Stevens ([email protected]):

La différence de base est que fd_set de select () est un masque de bits et a donc une taille fixe. Il serait possible que le kernel ne limite pas cette taille lorsque le kernel est compilé, ce qui permet à l’application de définir FD_SETSIZE à sa guise (comme le suggèrent les commentaires dans l’en-tête du système), mais cela demande plus de travail. Le kernel de 4.4BSD 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 s’il est réparé.

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, ce dernier est donc plus portable. De plus, avec les implémentations originales (SVR3), vous ne pouvez pas définir le descripteur sur -1 pour indiquer au kernel d’ignorer une entrée dans la structure pollfd, ce qui rend 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. Select () et poll () sont tous deux normalisés par POSIX 1003.1g.

Mise à jour d’octobre 2017:

L’e-mail référencé ci-dessus est au moins aussi ancien que 2001; La commande poll() est maintenant (2017) prise en charge sur tous les systèmes d’exploitation modernes, y compris BSD. En fait, certaines personnes pensent que select() devrait être déconseillé . Mis à part les opinions, les problèmes de portabilité autour de poll() ne sont plus une préoccupation pour 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 que cela ne soit pas explicitement faux. poll() , et son epoll() évolution plus moderne, fournit les mêmes fonctionnalités (et plus) que select() sans en subir les limitations.

L’appel select() vous a créé trois masques de bits pour marquer les sockets et les descripteurs de fichiers que vous souhaitez surveiller, en lecture, en écriture et en erreur, puis les systèmes d’exploitation qui ont en fait eu une activité quelconque; poll() vous permet de créer une liste d’ID de descripteur, et le système d’exploitation marque chacun d’eux avec le type d’événement qui s’est produit.

La méthode select() 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 que l’un d’entre eux a reçu un nombre élevé, le masque de bits transmis à select() doit être suffisamment grand pour accueillir ce descripteur le plus élevé possible. des bits seront désactivés que le système d’exploitation doit parcourir en boucle à chaque appel select() juste pour découvrir qu’ils ne sont pas définis.

  2. Une fois que select() retourne, l’appelant doit effectuer une boucle sur les trois masques de bits pour déterminer quels événements ont eu lieu. Dans de très nombreuses applications typiques, un ou deux descripteurs de fichiers seulement obtiendront un nouveau trafic à un moment donné, mais tous les trois masques de bits doivent être lus jusqu’à la fin pour découvrir quels sont les descripteurs.

  3. Parce que le système d’exploitation vous signale une 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. Vous devez soit reconstruire le masque de bits entier à partir d’une autre liste que vous gardez en mémoire, soit conserver une copie de chaque masque de bits et memcpy() le bloc de données au-dessus des masques de bits endommagés après chaque appel select() . .

Ainsi, l’approche poll() fonctionne beaucoup mieux car vous pouvez continuer à réutiliser la même structure de données.

En fait, poll() a inspiré un autre mécanisme dans les kernelx Linux modernes: epoll() améliore encore le mécanisme pour permettre une nouvelle évolutivité, car les serveurs actuels veulent souvent gérer des dizaines de milliers de connexions à la fois. C’est une bonne introduction à l’effort:

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

Bien que ce lien ait de jolis graphes montrant les avantages d’ epoll() (vous remarquerez que select() est à ce stade considéré comme tellement inefficace et désuet qu’il n’a même pas de ligne sur ces graphes!):

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


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

Mises en garde sur les réacteurs select / poll vs. epoll dans Twisted