Jakie są różnice między poll a select?

Mam na myśli standard POSIX select i poll wywołania API systemu C.

 144
Author: Steven Lu, 2009-06-09

2 answers

Myślę, że to odpowiada na twoje pytanie:

Od Richarda Stevensa ([email protected]):

Podstawowa różnica polega na tym, że fd_set select () jest maską bitową i dlatego ma jakiś stały rozmiar. Byłoby możliwe, aby jądro nie ograniczać tego rozmiaru podczas kompilacji jądra, pozwalając na aplikacja do definiowania FD_SETSIZE do czego chce (jak w komentarzach w nagłówku systemowym), ale wymaga to więcej pracy. 4.4 BSD jądro i obie funkcje biblioteki Solaris mają ten limit. Ale Ja zobacz, że BSD / OS 2.1 został zakodowany, aby uniknąć tego limitu, więc jest wykonalne, tylko mała kwestia programowania. :- ) Ktoś powinien złożyć Solaris Zgłoś błąd i sprawdź, czy kiedykolwiek zostanie naprawiony.

Z poll (), jednak użytkownik musi przydzielić tablicę pollfd struktur, i przekazać liczbę wpisów w tej tablicy, więc jest bez fundamentalnych ograniczeń. Jak zauważa Kacper, mniej systemów ma poll () niż wybierz, ten ostatni jest więc bardziej przenośny. Również z oryginalnym implementacji (SVR3) nie można ustawić deskryptora na -1 aby powiedzieć jądro, aby zignorować wpis w strukturze pollfd, co sprawiło, że trudne do usunięcia wpisy z tablicy; SVR4 to obejdzie. Osobiście zawsze używam select () i rzadko poll (), ponieważ portuję swój kod do środowisk BSD. Ktoś mógłby napisać implementację poll (), który używa select (), dla tych środowisk, ale nigdy widziałem. Obie select () i poll() są standaryzowane przez POSIX 1003.1 g.

[20]}Październik 2017 Aktualizacja:

Powyższy e-mail jest co najmniej tak stary jak 2001; polecenie poll() jest teraz (2017) obsługiwane we wszystkich nowoczesnych systemach operacyjnych - w tym BSD. W rzeczywistości, niektórzy ludzie wierzą, że select() powinien być przestarzały . Pomijając opinie, kwestie przenośności wokół poll() nie są już problemem nowoczesnych systemów. Ponadto, epoll() został opracowany (można przeczytać strona man ) i nadal rośnie popularność.

W przypadku nowoczesnego rozwoju prawdopodobnie nie chcesz używać select(), chociaż nie ma w tym nic złego. poll(), a to bardziej nowoczesna ewolucja epoll(), zapewniają te same funkcje (i więcej), co select(), bez cierpienia z ograniczeń w nich zawartych.

 76
Author: akappa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-18 05:21:03

Wywołanie select() powoduje utworzenie trzech bitmasek, aby zaznaczyć, które gniazda i deskryptory plików chcesz obserwować pod kątem odczytu, zapisu i błędów, a następnie system operacyjny oznacza, które z nich faktycznie miały jakąś aktywność; poll() tworzy listę identyfikatorów deskryptorów, a system operacyjny oznacza każdy z nich rodzajem zdarzenia, które miało miejsce.

Metoda select() jest raczej niezgrabna i nieefektywna.

  1. Zazwyczaj jest więcej niż tysiąc potencjalnych deskryptorów plików dostępnych dla procesu. Jeśli proces długo działający ma otwarte tylko kilka deskryptorów, ale przynajmniej jednemu z nich przypisano dużą liczbę, to maska bitowa przekazywana do select() musi być wystarczająco duża, aby pomieścić ten najwyższy deskryptor - tak więc całe zakresy setek bitów będą wyłączone, więc system operacyjny musi zapętlić się na każde wywołanie select() tylko po to, aby odkryć, że są wyłączone.

  2. Gdy select() powróci, wywołujący musi wykonać pętlę wszystkie trzy bitmaski, aby określić, jakie wydarzenia miały miejsce. W bardzo wielu typowych aplikacjach tylko jeden lub dwa deskryptory plików uzyskają nowy ruch w danym momencie, jednak wszystkie trzy bitmaski muszą być odczytane aż do końca, aby dowiedzieć się, które deskryptory są tymi deskryptorami.

  3. Ponieważ system operacyjny sygnalizuje Ci aktywność, przepisując bitmaski, są one zrujnowane i nie są już oznaczone listą deskryptorów plików, których chcesz słuchać. Albo trzeba odbudować Cała maska bitowa z innej listy, którą przechowujesz w pamięci, lub musisz zachować zduplikowaną kopię każdej maski bitowej i memcpy() bloku danych nad zniszczonymi maskami bitowymi po każdym wywołaniu select().

Więc podejście poll() działa znacznie lepiej, ponieważ można nadal ponownie używać tej samej struktury danych.

W rzeczywistości, poll() zainspirował jeszcze jeden mechanizm we współczesnych jądrach Linuksa: epoll() który ulepsza jeszcze bardziej mechanizm, aby umożliwić kolejny skok w skalowalność, ponieważ dzisiejsze serwery często chcą obsługiwać dziesiątki tysięcy połączeń jednocześnie. Jest to dobre wprowadzenie do wysiłku:

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

Podczas gdy ten link ma kilka ładnych wykresów pokazujących zalety epoll() (zauważ, że {[0] } jest w tym momencie uważany za tak nieefektywny i staromodny, że nawet nie dostaje linii na te / align = "left" / ):

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


Update: oto kolejne pytanie o przepełnienie stosu, którego odpowiedź daje jeszcze więcej szczegółów na temat różnic:

Zastrzeżenia select / poll vs. epoll w Twisted

 214
Author: Brandon Rhodes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:35