Должны ли мы использовать poll() или select()?
Я полностью осознаю основные различия между poll()
и select()
:
-
select()
поддерживает только фиксированное количество дескрипторов файлов
-
select()
предположительно поддерживается в более системах
-
poll()
позволяет немного более мелкомасштабное управление типами событий
-
poll()
реализации могут отличаться в определенных деталях.
Однако они выполняют одну и ту же задачу примерно одинаково. Итак:
Используем ли мы poll()
или select()
?
EDIT: Я мог бы добавить, что меня не интересует epoll()
, поскольку переносимость меня беспокоит. Кроме того, libev(ent)
также не является вариантом, так как я задаю этот вопрос, потому что я пишу свою собственную библиотеку замены для libev(ent)
.
Ответы
Ответ 1
Все удаленные современные системы имеют poll
, и он значительно превосходит интерфейс select
/pselect
почти всеми способами:
-
poll
позволяет более мелкомасштабное обнаружение статуса, чем select
.
-
poll
не имеет ограничений на максимальный дескриптор файла, который вы можете использовать (и что еще более важно, не имеет критических уязвимостей, если вы не можете проверить файловые дескрипторы за пределом FD_SETSIZE
).
Единственными минусами, которые я могу придумать для использования poll
, являются следующие:
- в отличие от
pselect
, poll
не может атомарно разоблачать/маскировать сигналы, поэтому вы не можете использовать его для ожидания набора событий, который включает в себя активность и сигналы дескриптора файла, если вы не прибегнете к трюку с собственной трубкой.
-
poll
имеет разрешение только миллисекунды для тайм-аута ожидания, а не микросекунды (select
) или наносекунды (pselect
).
Конечно, переносимость poll
больше не рассматривается. Любая система, достаточно старая для отсутствия poll
, полна множества уязвимостей, она не должна быть подключена к сети.
В общем, если у вас нет особых потребностей (крошечные интервалы таймаута, неприятные взаимодействия с сигналами, масштабирование до миллионов постоянных подключений и т.д.), я просто использовал бы poll
и выполнял бы с ним. Как отмечали другие, libevent
также является опцией, но это не чистый/безопасный код (его использование select
фактически вызывает опасный UB, пытающийся обойти ограничения select
!), И я нахожу код, который использует libevent
, как правило, намного излишне сложнее, чем код, который просто использует poll
напрямую.
Ответ 2
Если вы пишете для GNU/Linux, вы должны посмотреть на epoll (7).
Но для большей поддержки кросс-платформенной вы можете изучить использование libevent.
http://libevent.org/
На самом деле, трудно рекомендовать реализацию одного опроса/выбора, не зная специфики того, что вы пытаетесь сделать.
Ответ 3
Я бы рекомендовал boost:: asio, тогда вы можете попробовать как реализацию, так и тест, чтобы лучше узнать, что подходит вашей настройке.
Ответ 4
Я бы использовал libev или libevent. Эти библиотеки представляют собой кросс-платформенную и абстрактную информацию о базовой реализации (например, опрос, выбор.)
Ответ 5
В зависимости от ваших конкретных потребностей я бы рекомендовал либо poll
, либо ::boost::asio
. Я считаю, что libevent является довольно громоздким, и в нем есть всевозможные вещи, которые ориентированы на C и/или на обработку протоколов более высокого уровня.
Я бы не рекомендовал select
. Я видел, что реализации select
невидимо терпят неудачу в странных и причудливых путях, поскольку предел дескриптора был превышен. И самое лучшее, что вы можете сделать, это сделать его неудачным в явном виде. Возможно, это очень маловероятно для вашего приложения, но я бы не рискнул.
И теперь poll
доступен почти везде select
. О единственном месте это не Windows. Но, IMHO, если вы хотите перекрестно-платформенной переносимости на эту платформу, вам лучше использовать красивую обертку, например ::boost::asio
, которая красиво обертывает наиболее эффективную технику ОС.
Ответ 6
У Apple poll() есть проблемы с TTY, IME. Если мобильность является проблемой, выбор select() может быть лучшим выбором.