Вопрос

В сети разбросаны страницы, на которых с разной степенью детализации описываются возможности POSIX AIO.Ни один из них не является чем-то совсем недавним.Непонятно, что именно они описывают.Например, «официальный» (?) веб-сайт поддержки асинхронного ввода-вывода ядра Linux здесь говорит, что сокеты не работают, но все страницы руководства «aio.h» на моей рабочей станции Ubuntu 8.04.1, похоже, подразумевают, что он работает для произвольных файловых дескрипторов.Тогда есть еще один проект, который, похоже, работает на уровне библиотеки с еще меньшим количеством документации.

Я хотел бы знать:

  • Какова цель POSIX AIO?Учитывая, что самый очевидный пример реализации, который я могу найти, говорит о том, что он не поддерживает сокеты, все это кажется мне странным.Это только для асинхронного дискового ввода-вывода?Если да, то почему гиперуниверсальный API?Если нет, то почему именно дисковый ввод-вывод подвергается атаке в первую очередь?
  • Где есть примеры полный Программы POSIX AIO, которые я могу посмотреть?
  • Кто-нибудь реально им пользуется?
  • Какие платформы поддерживают POSIX AIO?Какие его части они поддерживают?Кто-нибудь действительно поддерживает подразумеваемый «Любой ввод-вывод на любой FD», который <aio.h> кажется обещает?

Другие доступные мне механизмы мультиплексирования вполне хороши, но плавающие вокруг случайные фрагменты информации вызвали у меня любопытство.

Это было полезно?

Решение

Сетевой ввод-вывод не является приоритетом для AIO, поскольку все, кто пишет сетевые серверы POSIX, используют неблокирующий подход на основе событий.Старый подход Java «миллиарды блокирующих потоков» ужасно отстойный.

Ввод-вывод записи на диск уже буферизован, а ввод-вывод чтения с диска можно предварительно загрузить в буфер с помощью таких функций, как posix_fadvise.В результате прямой, небуферизованный дисковый ввод-вывод остается единственной полезной целью для AIO.

Прямой небуферизованный ввод-вывод действительно полезен только для транзакционных баз данных, которые склонны писать свои собственные потоки или процессы для управления дисковым вводом-выводом.

Итак, в конце POSIX AIO остается в положении, когда он не обслуживает любой полезная цель.Не используйте его.

Другие советы

Эффективное выполнение сокетного ввода-вывода было решено с помощью kqueue, epoll, портов завершения ввода-вывода и тому подобного.Выполнение асинхронного файлового ввода-вывода появилось довольно поздно (не считая перекрывающегося ввода-вывода Windows и ранней поддержки Solaris для posix AIO).

Если вам нужен сокетный ввод-вывод, вам, вероятно, лучше использовать один из вышеперечисленных механизмов.

Таким образом, основная цель AIO — решить проблему асинхронного дискового ввода-вывода.Скорее всего, именно поэтому Mac OS X поддерживает AIO только для обычных файлов, а не для сокетов (поскольку kqueue в любом случае делает это намного лучше).

Операции записи обычно кэшируются ядром и сбрасываются позже.Например, когда считывающая головка диска проходит мимо места, где должен быть записан блок.

Однако для операций чтения, если вы хотите, чтобы ядро ​​расставляло приоритеты и упорядочивало чтение, AIO — действительно единственный вариант.Вот почему ядро ​​(теоретически) может сделать это лучше, чем любое приложение пользовательского уровня:

  • Ядро видит все дисковые операции ввода-вывода, а не только дисковые задания приложений, и может упорядочивать их на глобальном уровне.
  • Ядро (может) знать, где находится головка чтения диска, и может выбирать задания чтения, которые вы передаете ему, в оптимальном порядке, чтобы переместить головку на кратчайшее расстояние.
  • Ядро может воспользоваться собственная очередь команд для дальнейшей оптимизации операций чтения
  • Возможно, вы сможете выполнить больше операций чтения для каждого системного вызова с помощью lio_listio(), чем с помощью readv(), особенно если ваши чтения не являются (логически) смежными, что сэкономит небольшую часть накладных расходов на системные вызовы.
  • Ваша программа может быть немного проще с AIO, поскольку вам не нужен дополнительный поток для блокировки вызова чтения или записи.

Тем не менее, posix AIO имеет довольно неудобный интерфейс, например:

  • Единственным эффективным и хорошо поддерживаемым способом обратных вызовов событий являются сигналы, что затрудняет их использование в библиотеке, поскольку это означает использование номеров сигналов из глобального пространства имен сигналов процесса.Если ваша ОС не поддерживает сигналы реального времени, это также означает, что вам придется просмотреть все ожидающие запросы, чтобы выяснить, какой из них действительно завершен (например, это относится к Mac OS X, а не к Linux).Перехват сигналов в многопоточной среде также накладывает некоторые сложные ограничения.Обычно вы не можете отреагировать на событие внутри обработчика сигнала, но вам нужно вызвать сигнал, записать его в канал или использовать signalfd() (в Linux).
  • lio_suspend() имеет те же проблемы, что и select(), он не очень хорошо масштабируется в зависимости от количества заданий.
  • lio_listio() в том виде, в котором он реализован, имеет довольно ограниченное количество заданий, которые вы можете передать, и найти это ограничение в переносном способе непросто.Вам нужно вызвать sysconf(_SC_AIO_LISTIO_MAX), что может привести к сбою, и в этом случае вы можете использовать определение AIO_LISTIO_MAX, которое не обязательно определено, но тогда вы можете использовать 2, которое определено как гарантированно поддерживаемое.

Что касается реального приложения, использующего posix AIO, вы можете взглянуть на Lighttpd (lighty), который также опубликовал Измерение производительности при введении поддержки.

Большинство платформ posix на данный момент поддерживают posix AIO (Linux, BSD, Solaris, AIX, tru64).Windows поддерживает его через перекрывающийся файловый ввод-вывод.Насколько я понимаю, только Solaris, Windows и Linux действительно поддерживают асинхронность.файловый ввод-вывод вплоть до драйвера, тогда как другие ОС эмулируют асинхронный режим.Ввод-вывод с потоками ядра.Linux является исключением: его реализация posix AIO в glibc эмулирует асинхронные операции с потоками пользовательского уровня, тогда как его собственный асинхронный интерфейс ввода-вывода (io_submit() и т. д.) действительно асинхронен вплоть до драйвера, при условии, что драйвер его поддерживает. .

Я считаю, что среди операционных систем довольно распространено не поддерживать posix AIO для любого fd, а ограничивать его обычными файлами.

Разработчик libtorrent предоставляет отчет по этому поводу: http://blog.libtorrent.org/2012/10/asynchronous-disk-io/

Есть aio_write — реализован в glibc;Первый вызов функции aio_read или aio_write порождает несколько потоков пользовательского режима, отправляет запросы aio_write или aio_read в этот поток, поток выполняет предварительную запись/запись, и когда он завершается, ответ отправляется обратно в заблокированный вызывающий поток.

Также есть «настоящий» aio, поддерживаемый на уровне ядра (для этого нужен libaio, см. вызов io_submit). http://linux.die.net/man/2/io_submit );для этого также нужен O_DIRECT (также может поддерживаться не всеми файловыми системами, но основные из них поддерживают его)

глянь сюда:

http://lse.sourceforge.net/io/aio.html

http://linux.die.net/man/2/io_submit

Разница между POSIX AIO и libaio в Linux?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top