Должны ли мы использовать 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() может быть лучшим выбором.