Je fais référence à la norme POSIX sélectionnez y sondage les appels API du système C.
Réponses
Trop de publicités?El select()
call vous demande de créer trois bitmasks pour marquer les sockets et les descripteurs de fichiers que vous souhaitez surveiller en termes de lecture, d'écriture et d'erreurs, puis le système d'exploitation marque ceux qui ont effectivement eu une activité ; poll()
vous créez une liste d'ID de descripteurs, et le système d'exploitation marque chacun d'entre eux avec l'identifiant genre de l'événement qui s'est produit.
El select()
est plutôt maladroite et inefficace.
-
Il existe généralement plus de mille descripteurs de fichiers potentiels à la disposition d'un processus. Si un processus de longue durée n'a que quelques descripteurs ouverts, mais qu'au moins l'un d'entre eux s'est vu attribuer un numéro élevé, alors le masque de bits passé à la commande
select()
doit être suffisamment grande pour accueillir le descripteur le plus élevé - ainsi, des plages entières de centaines de bits seront désactivées et le système d'exploitation devra les parcourir en boucle à chaque fois qu'un fichierselect()
appeler juste pour découvrir qu'ils ne sont pas réglés. -
Une fois
select()
retourne, l'appelant doit boucler sur les trois bitmasks pour déterminer les événements qui ont eu lieu. Dans de très nombreuses applications typiques, seuls un ou deux descripteurs de fichiers recevront un nouveau trafic à un moment donné, mais les trois bitmasks doivent être lus jusqu'au bout pour découvrir de quels descripteurs il s'agit. -
Comme le système d'exploitation vous signale une activité en réécrivant les masques binaires, ceux-ci sont ruinés et ne portent plus la liste des descripteurs de fichiers que vous voulez écouter. Vous devez soit reconstruire l'ensemble du masque binaire à partir d'une autre liste que vous gardez en mémoire, soit conserver une copie de chaque masque binaire et de la liste des descripteurs de fichiers.
memcpy()
le bloc de données par-dessus les masques de bits en ruine après chaqueselect()
appeler.
Ainsi, le 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 noyaux Linux modernes : epoll()
qui améliore encore le mécanisme pour permettre un nouveau bond en avant en matière d'évolutivité, car les serveurs d'aujourd'hui veulent souvent gérer des dizaines de milliers de connexions à la fois. Il s'agit d'une bonne introduction à cet effort :
http://scotdoyle.com/python-epoll-howto.html
Bien que ce lien contienne de jolis graphiques montrant les avantages de l'utilisation de l'eau. epoll()
(vous noterez que select()
est à ce stade considéré comme tellement 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 de 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 et epoll dans Twisted
Je pense que este répond à votre question :
De Richard Stevens (rstevens@noao.edu) :
La différence fondamentale est que le fd_set de select() est un masque de bit et a donc une taille fixe. Il serait possible pour le noyau de ne pas limiter cette taille lors de la compilation. de ne pas limiter cette taille lors de la compilation du noyau, permettant à l'application de définir FD_SETSIZE comme elle le souhaite (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 de 4.4BSD et la fonction de bibliothèque de Solaris ont tous deux cette limite. Mais je Mais je vois que BSD/OS 2.1 a maintenant été codé pour éviter cette limite, donc c'est faisable. donc faisable, juste une petite question de programmation :-) Quelqu'un devrait déposer un rapport de bogue Solaris à ce sujet, et voir si cela est corrigé un jour.
Avec poll(), cependant, l'utilisateur doit allouer un tableau de structures pollfd et passer le nombre d'entrées dans ce tableau, donc il n'y a pas de limite fondamentale. 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 originales (SVR3), vous ne pouviez pas mettre le descripteur à -1 pour indiquer au pour dire au noyau d'ignorer une entrée dans la structure pollfd, ce qui le rendait difficile de supprimer des entrées du tableau ; SVR4 contourne ce problème. Personnellement, j'utilise toujours select() et rarement poll(), parce que je porte aussi mon code pour les environnements BSD aussi. Quelqu'un pourrait écrire une implémentation implémentation de poll() qui utilise select(), pour ces environnements, mais je n'en ai jamais vu une. jamais vu. select() et poll() sont tous deux normalisés par POSIX 1003.1g.