Was sind die Unterschiede zwischen Umfrage und Auswahl?


Antworten:


90

Ich denke, dass dies Ihre Frage beantwortet:

Von Richard Stevens (rstevens@noao.edu):

Der grundlegende Unterschied besteht darin, dass 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 beim Kompilieren des Kernels nicht einschränkt, sodass die Anwendung FD_SETSIZE nach Belieben 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 Grenze. Ich sehe jedoch, dass BSD / OS 2.1 jetzt codiert wurde, um diese Grenze zu umgehen. Es ist also machbar, nur eine kleine Frage der Programmierung. :-) Jemand sollte einen Solaris-Fehlerbericht dazu einreichen und prüfen, ob er 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 grundlegende Begrenzung gibt. Wie Casper feststellt, haben weniger Systeme poll () als select, sodass letzteres portabler ist. Außerdem konnten Sie bei Originalimplementierungen (SVR3) den Deskriptor nicht auf -1 setzen, um den Kernel anzuweisen, einen Eintrag in der pollfd-Struktur zu ignorieren, was es schwierig machte, Einträge aus dem Array zu entfernen. SVR4 umgeht dies. Persönlich verwende ich immer select () und selten poll (), da ich meinen Code auch auf BSD-Umgebungen portiere. Jemand könnte eine Implementierung von poll () schreiben, die select () für diese Umgebungen verwendet, aber ich habe noch nie eine gesehen. Sowohl select () als auch poll () werden durch POSIX 1003.1g standardisiert.

Oktober 2017 Update:

Die oben genannte E-Mail ist mindestens so alt wie 2001; Der poll()Befehl wird jetzt (2017) auf allen modernen Betriebssystemen unterstützt - einschließlich BSD. In der Tat glauben einige Leute, dass select() dies veraltet sein sollte . Abgesehen von den Meinungen sind Portabilitätsprobleme poll()bei modernen Systemen kein Problem mehr. Darüber hinaus wurde epoll()seitdem entwickelt (Sie können die Manpage lesen ) 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 Evolution epoll(), bieten die gleichen Funktionen (und mehr) wie select()ohne unter den darin enthaltenen Einschränkungen zu leiden.


15
Wann wurde Stevens Antwort geschrieben? Gilt der Kommentar, dass poll () nicht auf BSD verfügbar ist, weiterhin? MacOS X (das teilweise auf BSD basiert) verfügt über poll (), und der POSIX-Standard (POSIX 2008) verlangt dies.
Jonathan Leffler

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

2
Ich glaube es nicht Antwort gepostet vor 5 Jahren, ich stolpere darüber, lass es im Browser offen. Bereits am nächsten Tag bearbeitet und verbessert der Autor die Antwort. SO benachrichtigt mich mit Update auf Seite mit AJAX / Websocket. Deshalb ist SO großartig
Steven Lu

9
@StevenLu Ja, aber leider kein Wort darüber, ob AJAX / Websocket verwendet selectoder poll:(
Christopher Schultz

> Jemand könnte eine Implementierung von poll () schreiben, die select () für diese Umgebungen verwendet, aber ich habe noch nie eine gesehen. Java tut dies ;-)
Sergey Mashkov

229

Mit dem select()Aufruf müssen Sie drei Bitmasken erstellen, um zu markieren, welche Sockets und Dateideskriptoren auf Lesen, Schreiben und Fehler überwacht werden sollen. Anschließend markiert das Betriebssystem, welche tatsächlich eine Aktivität hatten. poll()Haben Sie eine Liste von Deskriptor-IDs erstellt, und das Betriebssystem markiert jede von ihnen mit der Art des aufgetretenen Ereignisses.

Die select()Methode ist ziemlich klobig und ineffizient.

  1. In der Regel stehen einem Prozess mehr als tausend potenzielle Dateideskriptoren zur Verfügung. Wenn in einem lang laufenden Prozess nur wenige Deskriptoren offen sind, aber mindestens einem von ihnen eine hohe Nummer zugewiesen wurde, muss die übergebene Bitmaske select()groß genug sein, um diesen höchsten Deskriptor aufzunehmen - also werden ganze Bereiche von Hunderten von Bits aufgenommen Stellen Sie sicher, dass das Betriebssystem bei jedem select()Aufruf eine Schleife durchlaufen muss, um festzustellen, dass sie nicht festgelegt sind.

  2. Nach der select()Rückkehr muss der Anrufer alle drei Bitmasken durchlaufen, um festzustellen, welche Ereignisse stattgefunden haben. In sehr vielen typischen Anwendungen erhalten zu einem bestimmten Zeitpunkt nur ein oder zwei Dateideskriptoren neuen Datenverkehr. Alle drei Bitmasken müssen jedoch bis zum Ende gelesen werden, um festzustellen, um welche Deskriptoren es sich handelt.

  3. Da das Betriebssystem Sie durch Umschreiben der Bitmasken über Aktivitäten informiert, sind diese 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 neu erstellen, die Sie im Speicher behalten, oder Sie müssen memcpy()nach jedem select()Aufruf eine doppelte Kopie jeder Bitmaske und des Datenblocks über den zerstörten Bitmasken aufbewahren .

Der poll()Ansatz funktioniert also viel besser, da Sie dieselbe Datenstruktur weiterhin verwenden können.

Tatsächlich poll()hat ein weiterer Mechanismus in modernen Linux-Kerneln inspiriert: Er epoll()verbessert den Mechanismus noch weiter, um einen weiteren Sprung in der Skalierbarkeit zu ermöglichen, da die heutigen Server häufig 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 feststellen, dass select()dies zu diesem Zeitpunkt als so ineffizient und altmodisch angesehen wird, dass in diesen Grafiken nicht einmal eine Linie angezeigt wird!):

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


Update: Hier ist eine weitere Frage zum Stapelüberlauf, deren Antwort noch detaillierter auf die Unterschiede eingeht:

Vorbehalte von Select / Poll vs. Epoll-Reaktoren in Twisted


1
Und +1 für die Verknüpfung mit einem Beispiel für die Verwendung von Epoll in Python - anscheinend gibt es dort einige interessante Beispiele, und ich muss sie ausprobieren ...
Allen George

+1 zur Erklärung der Antwort; -1 für die Erwähnung von Epoll, aber nicht Kqueue
Gute Person

Diese Antwort lässt es so klingen, als wäre Epoll immer vorzuziehen
user3467349

0

Beide sind langsam und meistens gleich , aber unterschiedlich groß und in irgendeiner Form!

Wenn Sie einen Iterator schreiben, müssen Sie den Satz selectjedes Mal kopieren ! Während pollhat diese Art von Problem behoben, um schönen Code zu haben. Ein weiterer Unterschied besteht darin, dass pollstandardmäßig mehr als 1024 Dateideskriptoren (FDs) verarbeitet werden können. pollkann verschiedene Ereignisse behandeln, um das Programm besser lesbar zu machen, anstatt viele Variablen für diese Art von Arbeit zu haben. Operationen in pollund selectsind linear und langsam, da viele Überprüfungen durchgeführt werden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.