Обратите внимание: ни одна из этих методик не занимается непосредственным вводом/выводом. Они всего лишь сообщают нам о готовности файлового дескриптора. Для выполнения чтения или записи нужно использовать дополнительные системные вызовы.
Одной из моделей, не описанной в этой главе, является POSIX AIO (асинхронный ввод/вывод), который позволяет процессу помещать операции чтения или записи файла в очередь и затем оповещает его об их завершении. Преимущество POSIX AIO заключается вот в чем: исходный вызов возвращается без промедления, так что процессу не нужно ждать, когда данные будут переданы ядру или операция будет завершена. Это позволяет процессу выполнять другие задачи параллельно с вводом/выводом (возможно даже размещение в очереди дополнительных запросов на чтение или запись). POSIX AIO обеспечивает заметный прирост производительности для определенной категории приложений. В современных версиях Linux этот интерфейс реализован на основе потоков в рамках библиотеки glibc. На момент написания книги ведется работа над реализацией POSIX AIO на уровне ядра, что должно обеспечить лучшее масштабирование. Описание данного интерфейса можно найти в книгах [Gallmeister, 1995] и [Robbins & Robbins, 2003].
Далее в этой главе мы постараемся взвешивать причины, которые могут подтолкнуть нас к использованию той или иной методики. А пока что перечислим несколько основных моментов.
• select() и poll() — устоявшиеся системные вызовы; они присутствуют в UNIX-системах на протяжении многих лет. Их основным преимуществом перед остальными методиками выступает портируемость на другие платформы. Главный же недостаток заключается в проблемах с масштабированием при мониторинге множества (сотен или тысяч) файловых дескрипторов.
• Ключевым преимуществом программного интерфейса epoll является то, что он позволяет приложению эффективно следить за большим количеством дескрипторов. Главный его недостаток — он поддерживается только в Linux.
Ряд реализаций UNIX предоставляют (нестандартные) механизмы, похожие на epoll. Например, в Solaris существует специальный файл /dev/poll (страница poll(7d) руководства), а в некоторых разновидностях BSD доступен программный интерфейс kqueue (представляющий собой более универсальную систему мониторинга, чем epoll). Эти два механизма кратко описаны в книге [Stevens et al., 2004]; подробную информацию об интерфейсе kqueue можно найти в книге [Lemon, 2001].
• По аналогии с интерфейсом epoll ввод/вывод на основе сигналов позволяет приложениям более эффективно отслеживать большое количество файловых дескрипторов. Вместе с тем epoll имеет несколько заметных преимуществ:
• позволяет избежать трудностей, связанных с сигналами;
• позволяет выбирать нужный способ мониторинга (например, отслеживать готовность для чтения или для записи);
• позволяет выбирать, когда будут генерироваться уведомления — при изменении уровня или при достижении граничного значения (см. подраздел 59.1.1).
Кроме того, чтобы в полной мере воспользоваться преимуществами ввода/вывода на основе сигналов, необходимо применять функции, которые доступны только в Linux и отсутствуют в других системах; то есть данная методика ничем не лучше epoll в плане портируемости.
Ввиду того что вызовы select() и poll() имеют лучшую портируемость, а ввод/вывод на основе сигналов и интерфейс epoll обладают более высокой производительностью, в ряде случаев для мониторинга событий, связанных с файловыми дескрипторами, имеет смысл написать отдельный уровень абстракции. Это позволит использовать интерфейс epoll (или аналогичный) в системах, которые его поддерживают, а в остальных случаях прибегать к вызовам select() или poll().
Библиотека libevent представляет собой слой абстракции для мониторинга событий, относящихся к файловым дескрипторам. Она была перенесена на множество UNIX-систем. Позволяет прозрачно задействовать любые методики, описанные в этой главе: вызовы select() и poll(), ввод/вывод на основе сигналов, интерфейс epoll, а также файл /dev/poll в Solaris и интерфейс kqueue в системах семейства BSD (таким образом, libevent служит примером использования всех этих механизмов). Библиотека libevent написана Найлсом Провосом и доступна на http://libevent.org/.
59.1.1. Уведомления, срабатывающие по уровню или фронту
Прежде чем переходить к подробному обсуждению различных альтернативных механизмов ввода/вывода, необходимо выделить два способа определения готовности файлового дескриптора:
•
•