Was sind die Unterschiede zwischen poll und select?

Lesezeit: 6 Minuten

Ich beziehe mich auf den POSIX-Standard auswählen und Umfrage System-C-API-Aufrufe.

Benutzeravatar von Brandon Rhodes
Brandon Rhodes

Das select() call lässt Sie drei Bitmasken erstellen, um zu markieren, welche Sockets und Dateideskriptoren Sie auf Lesen, Schreiben und Fehler überwachen möchten, und dann markiert das Betriebssystem, welche tatsächlich irgendeine Art von Aktivität hatten; poll() Sie haben eine Liste von Deskriptor-IDs erstellt, und das Betriebssystem markiert jede von ihnen mit dem nett des eingetretenen Ereignisses.

Das select() Methode ist ziemlich klobig und ineffizient.

  1. Typischerweise stehen einem Prozess mehr als tausend potenzielle Dateideskriptoren zur Verfügung. Wenn ein langlaufender Prozess nur wenige Deskriptoren geöffnet hat, aber mindestens einem davon eine hohe Nummer zugewiesen wurde, dann wird die Bitmaske an übergeben select() muss groß genug sein, um diesen höchsten Deskriptor aufzunehmen – also werden ganze Bereiche von Hunderten von Bits ungesetzt, die das Betriebssystem bei jedem durchlaufen muss select() anrufen, nur um festzustellen, dass sie unscharf sind.

  2. Einmal select() zurückgibt, muss der Aufrufer alle drei Bitmasken durchlaufen, um festzustellen, welche Ereignisse stattgefunden haben. In sehr vielen typischen Anwendungen erhalten nur ein oder zwei Dateideskriptoren zu einem bestimmten Zeitpunkt neuen Verkehr, dennoch müssen alle drei Bitmasken bis zum Ende gelesen werden, um herauszufinden, welche Deskriptoren das sind.

  3. Da das Betriebssystem Sie über Aktivitäten informiert, indem es die Bitmasken neu schreibt, sind sie ruiniert und nicht mehr mit der Liste der Dateideskriptoren gekennzeichnet, die Sie anhören möchten. Sie müssen entweder die gesamte Bitmaske aus einer anderen Liste, die Sie im Speicher behalten, neu erstellen, oder Sie müssen eine Kopie jeder Bitmaske behalten und memcpy() der Datenblock über den zerstörten Bitmasken nach jedem select() Anruf.

Also die poll() Ansatz funktioniert viel besser, da Sie dieselbe Datenstruktur immer wieder verwenden können.

In der Tat, poll() hat einen weiteren Mechanismus in modernen Linux-Kernels inspiriert: epoll() Dadurch wird der Mechanismus noch weiter verbessert, um einen weiteren Sprung in der Skalierbarkeit zu ermöglichen, da die heutigen Server oft Zehntausende von Verbindungen gleichzeitig verarbeiten möchten. Dies ist eine gute Einführung in die Bemühungen:

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

Während dieser Link einige schöne Grafiken enthält, die die Vorteile von zeigen epoll() (Sie werden das merken select() wird zu diesem Zeitpunkt als so ineffizient und altmodisch angesehen, dass es nicht einmal eine Linie in diesen Diagrammen erhält!):

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


Aktualisieren: Hier ist eine weitere Stack Overflow-Frage, deren Antwort noch mehr Details zu den Unterschieden enthält:

Vorbehalte zwischen Select/Poll- und Epoll-Reaktoren in Twisted

  • Und +1 für den Link zu einem Beispiel für die Verwendung von epoll in Python – es sieht so aus, als gäbe es dort einige interessante Beispiele, und ich muss sie ausprobieren …

    – Allen George

    16. Juni 2011 um 18:44 Uhr

  • Diese Antwort lässt es so klingen, als wäre epoll immer vorzuziehen

    – Benutzer3467349

    23. Januar 2015 um 17:16 Uhr

  • Sie lassen es so aussehen, als ob der Bitscan der Engpass war. Es ist nicht. Das Scannen eines 1024-Bit-Arrays (1024 ist die FD_SETSIZE unter Linux) dauert etwa 20 ns. Syscalls dauert Hunderte, wenn nicht Tausende. Spärliche Lücken können ziemlich effizient übersprungen werden (viel effizienter als mit struct pollfd Arrays, bei denen Sie auch Lücken benötigen oder die Wartung der Nichtlücke viel teurer sein wird als die fd_set-Manipulation).

    – PSkočik

    15. Juni 2021 um 11:33 Uhr

  • Laut diesem Benchmark, den ich gefunden habe, scheinen sie mit großen fd-Sets ungefähr gleich (in) effizient zu sein: monkey.org/~provos/libevent/libevent-benchmark2.jpgwobei poll bei hohen fd-Zahlen nur einen kleinen Vorteil erhält, wahrscheinlich weil select seine Argumentsätze stärker ändert als select.

    – PSkočik

    15. Juni 2021 um 11:33 Uhr

Benutzeravatar von akappa
Akappa

ich denke, dass Dies beantwortet deine Frage:

Von Richard Stevens ([email protected]):

Der grundlegende Unterschied besteht darin, dass das fd_set von select() eine Bitmaske ist und daher eine feste Größe hat. Es wäre möglich, dass der Kernel diese Größe nicht begrenzt, wenn der Kernel kompiliert wird, sodass die Anwendung FD_SETSIZE beliebig definieren kann (wie die Kommentare im Systemheader heute implizieren), aber es erfordert mehr Arbeit. Der Kernel von 4.4BSD und die Solaris-Bibliotheksfunktion haben beide diese Begrenzung. Aber ich sehe, dass BSD/OS 2.1 jetzt so codiert wurde, dass diese Grenze vermieden wird, also ist es machbar, nur eine kleine Sache der Programmierung. 🙂 Jemand sollte einen Solaris-Fehlerbericht dazu einreichen und sehen, ob es jemals behoben wird.

Bei poll() muss der Benutzer jedoch ein Array von pollfd-Strukturen zuweisen und die Anzahl der Einträge in diesem Array übergeben, sodass es keine grundsätzliche Begrenzung gibt. Wie Casper feststellt, verfügen weniger Systeme über poll() als select, sodass letzteres besser portierbar ist. Außerdem konnten Sie bei ursprünglichen Implementierungen (SVR3) den Deskriptor nicht auf -1 setzen, um dem Kernel mitzuteilen, dass er einen Eintrag in der pollfd-Struktur ignorieren soll, was es schwierig machte, Einträge aus dem Array zu entfernen; SVR4 umgeht das. Ich persönlich verwende immer select() und selten poll(), weil ich meinen Code auch auf BSD-Umgebungen portiere. Jemand könnte für diese Umgebungen eine Implementierung von poll() schreiben, die select() verwendet, aber ich habe noch nie eine gesehen. Sowohl select() als auch poll() werden durch POSIX 1003.1g standardisiert.

Aktualisierung Oktober 2017:

Die oben erwähnte E-Mail ist mindestens so alt wie 2001; das poll() command wird jetzt (2017) von allen modernen Betriebssystemen unterstützt – einschließlich BSD. Tatsächlich glauben das einige Leute select() sollte verworfen werden. Meinungen beiseite, Portabilitätsprobleme herum poll() sind auf modernen Systemen kein Problem mehr. Außerdem, epoll() wurde seitdem entwickelt (Sie können lesen Sie die Manpage) und erfreut sich immer größerer Beliebtheit.

Für die moderne Entwicklung möchten Sie wahrscheinlich nicht verwenden select()obwohl daran nichts explizit falsch ist. poll()und es ist eine modernere Entwicklung epoll()bieten die gleichen Funktionen (und mehr) wie select() ohne unter den Einschränkungen darin zu leiden.

  • Wann wurde Stevens Antwort geschrieben? Gilt der Kommentar, dass poll() nicht auf BSD verfügbar ist, immer noch? MacOS X (das teilweise auf BSD basiert) hat poll(), und der POSIX-Standard (POSIX 2008) erfordert es.

    – Jonathan Leffler

    10. März 2010 um 20:49 Uhr

  • Rich Stevens starb im September 1999, also muss die Antwort älter sein. Er erwähnt eine neue Änderung in BSD/OS 2.1, das im Januar 1996 veröffentlicht wurde, also wahrscheinlich um diese Zeit herum.

    – al

    5. Juni 2010 um 15:13 Uhr

  • Ich glaube es nicht. Antwort vor 5 Jahren gepostet, ich stolpere darüber, lasse es im Browser geöffnet. Bereits am nächsten Tag bearbeitet und verbessert der Autor die Antwort. SO benachrichtigt mich über Aktualisierungen auf der Seite mit AJAX/Websocket. Deshalb ist SO großartig

    – Steven Lu

    14. Mai 2014 um 16:21 Uhr


  • @StevenLu Ja, aber leider kein Wort darüber, ob AJAX/Websocket verwendet wird select oder poll 🙁

    – Christoph Schultz

    5. Juli 2016 um 22:07 Uhr

  • > Jemand könnte für diese Umgebungen eine Implementierung von poll() schreiben, die select() verwendet, aber ich habe noch nie eine gesehen. Java macht das 😉

    – Sergej Maschkow

    18. April 2017 um 13:05 Uhr


Beide sind es langsam und meistens das GleicheAber unterschiedlich in der Größe und einigen Funktionen!

Wenn Sie einen Iterator schreiben, müssen Sie die Menge kopieren select jedes Mal! Während poll hat diese Art von Problem behoben, um schönen Code zu haben. Ein weiterer Unterschied besteht darin poll kann standardmäßig mehr als 1024 Dateideskriptoren (FDs) verarbeiten. poll kann verschiedene Ereignisse behandeln, um das Programm lesbarer zu machen, anstatt viele Variablen zu haben, um diese Art von Job zu erledigen. Operationen ein poll und select ist linear und langsam, da es viele Überprüfungen gibt.

1425600cookie-checkWas sind die Unterschiede zwischen poll und select?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy