Які відмінності між опитуванням та вибором?


Відповіді:


90

Я думаю, що це відповідає на ваше запитання:

Від Річарда Стівенса (rstevens@noao.edu):

Основна відмінність полягає в тому, що fd_set select () є бітною маскою і тому має деякий фіксований розмір. Ядро могло б не обмежувати цей розмір під час компіляції ядра, що дозволяє додатку визначати FD_SETSIZE на все, що хоче (як випливають із коментарів у заголовку системи сьогодні), але це потребує більшої роботи. Це ядро ​​4.4BSD і функція бібліотеки Solaris мають це обмеження. Але я бачу, що BSD / OS 2.1 тепер були закодовані, щоб уникнути цього обмеження, тому це можливо, лише невелика справа програмування. :-) Хтось повинен подати звіт про помилку Solaris про це і побачити, чи він коли-небудь виправляється.

Однак, опитуючи (), користувач повинен виділити масив структур pollfd та пропустити кількість записів у цьому масиві, тому немає принципового обмеження. Як зазначає Каспер, менша кількість систем має опитування (), ніж вибір, тому остання є більш портативною. Крім того, з оригінальними реалізаціями (SVR3) ви не змогли встановити дескриптор до -1, щоб сказати ядру ігнорувати запис у структурі pollfd, що ускладнило видалення записів з масиву; SVR4 обходить це. Особисто я завжди використовую select () і рідко запитую (), тому що я також портую свій код до BSD-середовищ. Хтось може написати реалізацію опитування (), яке використовує select (), для цих середовищ, але я жодного разу не бачив цього. Як select (), так і опитування () стандартизуються POSIX 1003.1g.

Оновлення жовтня 2017 року:

Електронна пошта, на яку було посилатися вище, принаймні стара в 2001 році; poll()команда зараз (2017) підтримується у всіх сучасних операційних систем , в тому числі - BSD. Насправді, деякі люди вважають, що це select() слід застаріти . Думки осторонь, питання переносимості навколо poll()вже не хвилюють сучасні системи. Крім того, epoll()вона була розроблена (ви можете прочитати сторінку людини ) і продовжує наростати популярність.

Для сучасної розробки ви, мабуть, не хочете використовувати select(), хоча в цьому явно нічого поганого немає. poll(), і це більш сучасна еволюція epoll(), забезпечують ті ж характеристики (і більше), що і select()не страждаючи від обмежень, які в них містяться.


15
Коли була написана відповідь Стівенса? Чи все ще застосовується коментар щодо опитування (), яке не доступне для BSD? MacOS X (який частково базується на BSD) має опитування (), а стандарт POSIX (POSIX 2008) вимагає цього.
Джонатан Леффлер

12
Багатий Стівенс помер у вересні 1999 року, тому відповідь має бути старшою за це. Він згадує, що побачив нову зміну BSD / OS 2.1, яка була випущена в січні 1996 року, так що, ймовірно, приблизно тоді.
alanc

2
Я не вірю в це. Відповідь, опубліковану 5 років тому, я натрапляю на неї, залишаю відкритим у браузері. Наступного дня автор редагує та вдосконалює відповідь. Так повідомляє мене про оновлення на сторінці за допомогою AJAX / websocket. ось чому SO чудово
Стівен Лу

9
@StevenLu Так, але, на жаль, жодного слова про те, чи використовує AJAX / websocket selectабо poll:(
Крістофер Шульц

> Хтось може написати реалізацію опитування (), яке використовує select (), для цих середовищ, але я жодного разу не бачив. Java робить так ;-)
Сергій Машков

229

У select()виклику ви створили три бітові маски, щоб позначити, які сокети та дескриптори файлів ви хочете спостерігати за читанням, записом та помилками, а потім операційна система відзначає, які з них насправді мали певну активність; poll()Ви створили список ідентифікаторів дескриптора, і операційна система позначає кожного з них тим видом події, що сталася.

select()Метод досить незграбний і неефективний.

  1. Типово для процесу доступно більше тисячі потенційних дескрипторів файлів. Якщо у тривалому процесі відкрито лише декілька дескрипторів, але хоча б одному з них було присвоєно велику кількість, то передана бітмаска select()повинна бути достатньо великою, щоб вмістити цей найвищий дескриптор - тому цілі діапазони сотень біт будуть не враховуйте, що операційна система повинна переходити на кожен select()виклик лише для того, щоб виявити, що вони не налаштовані.

  2. Як тільки select()повертається, абонент повинен перенести всі три бітові маски, щоб визначити, які події відбулися. У дуже багатьох типових додатках лише один або два дескриптори файлів отримують новий трафік у будь-який момент, але все три бітові маски повинні бути прочитані до кінця, щоб виявити, які це дескриптори.

  3. Оскільки операційна система сигналізує вам про активність, переписуючи бітові маски, вони руйнуються і більше не позначаються списком дескрипторів файлів, які ви хочете слухати. Вам або доведеться перебудувати всю біт-маску з якогось іншого списку, який ви зберігаєте в пам’яті, або вам доведеться зберігати подвійну копію кожної біт-маски та memcpy()блоку даних над зруйнованими біт-масками після кожного select()дзвінка.

Тож poll()підхід працює набагато краще, оскільки ви можете продовжувати повторно використовувати ту саму структуру даних.

Насправді, poll()він надихнув ще один механізм в сучасних Linux ядрах: epoll()що ще більше вдосконалює механізм, що дозволяє ще один стрибок у масштабованості, оскільки сьогоднішні сервери часто хочуть обробляти десятки тисяч з'єднань одночасно. Це гарне вступ до зусиль:

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

Хоча на цьому посиланні є кілька приємних графіків, що показують переваги epoll()(ви зауважте, що select()до цього моменту вважається настільки неефективним та старомодним, що навіть не отримує рядки на цих графіках!):

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


Оновлення: Ось ще одне запитання щодо переповнення стека, відповідь якого дає ще більш детальну інформацію про відмінності:

Порізи реакторів вибору / опитування проти епольних реакторів у крученому


1
І +1 за посилання на приклад використання epoll в python - схоже, є кілька цікавих прикладів, і мені доведеться їх випробувати ...
Аллен Джордж

+1 для пояснення відповіді; -1 для згадування еполі, але не kqueue
Good Person

Ця відповідь дозволяє звучати, як epoll завжди кращий
user3467349

0

Обидва вони повільні і здебільшого однакові , але різні за розміром і якимись особливостями!

Коли ви пишете ітератор, вам потрібно selectкожного разу копіювати набір ! Хоча pollвирішили подібну проблему, щоб мати гарний код. Ще одна відмінність полягає в тому, що pollза замовчуванням може працювати більше 1024 дескрипторів файлів (FD). pollможе обробляти різні події, щоб зробити програму більш зрозумілою, замість того, щоб мати багато змінних для обробки подібних завдань. Операції в pollі selectлінійні, і повільні, оскільки багато перевірок.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.