Как автор предложенного Boost.AFIO, который может использовать POSIX AIO, я настоятельно рекомендую вообще не использовать POSIX AIO. Вряд ли я одинок в этом мнении, @arvid так же против: http://blog.libtorrent.org/2012/10/asynchronous-disk-io/. Сам API плохо спроектирован и, как следствие, плохо масштабируется под нагрузкой, если только вы не используете специфичные для ОС альтернативы или расширения для AIO, такие как BSD kqueues. POSIX AIO практически бесполезен как есть.
Кроме того, вызовы AIO небезопасны для сигналов в Linux, который вы, вероятно, используете. Это связано с тем, что в Linux они реализованы в пользовательском пространстве с помощью эмуляции на основе пула потоков. В BSD вызовы AIO имеют надлежащий интерфейс системных вызовов ядра, но в ядре превращаются — да, как вы уже догадались — в эмуляцию на основе пула потоков, если не включен O_DIRECT.
Поэтому в POSIX вам гораздо лучше просто всегда использовать пул потоков, если только ваш ввод-вывод не включен с O_DIRECT. Если O_DIRECT действительно всегда включен, Linux предоставляет собственный API ядра, подробно описанный по адресу http://man7.org/linux/man-pages/man2/io_submit.2.html, что довольно эффективно, и в BSD, если вы замените обработку, управляемую сигналами, на BSD kqueues (https://www.freebsd.org/cgi/man.cgi?kqueue, см. EVFILT_AIO), то с O_DIRECT все также может хорошо масштабироваться, в любом случае лучше, чем пул потоков.
Использование обработки завершения на основе сигналов на ЛЮБОЙ платформе POSIX имеет ужасную производительность. AFIO v2 предоставляет универсальный бэкэнд POSIX AIO, и он ужасен, ужасен, ужасен. Избегайте, как чумы.
Обратите внимание, что дизайн синхронного API с пулом потоков является переносимым, хорошо масштабируется для большинства случаев использования, и это то, что я (и действительно arvid) рекомендовал бы всем, у кого нет узкоспециализированных потребностей, таких как написание серверной части базы данных, где вам нужен очень жесткий контроль над физическим уровнем хранения. , и ничего, кроме O_DIRECT|O_SYNC, не вариант.
Хорошо, все сказанное, если вы действительно хотите использовать aio, управляемый сигналом, я предполагаю, что это потому, что вы хотите мультиплексировать свой файловый ввод-вывод с нефайловым вводом-выводом, и поэтому вы не можете использовать aio_suspend() который является правильным API для этого. Способ, которым AFIO v2 обрабатывает это, заключается в использовании сигнала реального времени для прерывания aio_suspend(), когда необходимо обработать что-то, не связанное с aio, затем это можно обработать и перезапустить aio_suspend(). Вы должны быть очень осторожны в обработке гонок и взаимоблокировок, и вам нужно будет тщательно маскировать и демаскировать сигнал для потока, вызывающего aio_suspend(), чтобы сигнал реального времени не терялся и вы не получили потерянное пробуждение. В общем, это не стоит того, поскольку обычно гораздо более низкая производительность ввода-вывода, которую вы получаете через пул потоков + синхронные API.
person
Niall Douglas
schedule
31.03.2016
aio_read
: одновременные операции ввода-вывода, определяющие та же структураaiocb
дает неопределенные результаты. Если сигнал поступает во время выполнения другого вызова AIO с использованием той же структуры управления, это приведет к проблемам. Думаю, если вы используете отдельную структуру управления и отдельные буферы, это должно быть безопасно. Я не знаю, будут ли проблемы с сигнализацией AIO, если запрос завершится немедленно. - person Some programmer dude   schedule 31.03.2016sigwaitinfo()
? Таким образом, вы могли бы выделить новую структуру управления (или использовать мьютексы), чтобы избежать использования уже используемой структуры управления? - person Nominal Animal   schedule 31.03.2016