aio_read внутри обработчика сигнала
Я собираюсь использовать AIO для асинхронного чтения. Когда aio завершает работу и запускается обработчик сигнала, мне может потребоваться выполнить еще один вызов aio_read и продолжить.
aio_read не упоминается среди безопасных функций (в сигнале человека). Обычное чтение, однако.
Каковы опасности выполнения последующих вызовов aio_read внутри обработчика сигналов aio?
1 ответ
Как автор предложенного 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 backend, и он ужасен, ужасен, ужасен. Избегайте чумы.
Обратите внимание, что синхронный API-интерфейс с многопоточным интерфейсом является переносимым, хорошо масштабируется для большинства случаев использования, и это то, что я (и даже arvid) рекомендовал бы всем, у кого нет особых потребностей, таких как написание серверной части базы данных, где требуется очень жесткий контроль над уровнем физического хранилища. и ничего кроме O_DIRECT|O_SYNC не вариант.
Хорошо, все это говорит о том, что если вы действительно хотите использовать управляемый сигналом aio, я предполагаю, что это потому, что вы хотите мультиплексировать ваш файловый ввод-вывод с нефайловым вводом-выводом, и поэтому вы не можете использовать aio_suspend(), который правильный API для этого. AFIO v2 обрабатывает это, используя сигнал в реальном времени для прерывания aio_suspend(), когда необходимо обработать что-то, не связанное с aio, затем его можно обработать и перезапустить aio_suspend(). Вы должны быть очень осторожны в обработке гонок и взаимоблокировок, и вам нужно будет тщательно замаскировать и снять маску сигнала для потока, вызывающего aio_suspend(), чтобы сигнал в реальном времени не терялся и вы не потеряли пробуждение. В общем, это не стоит того, что вы обычно получаете гораздо более низкую производительность ввода-вывода по сравнению с пулом потоков + синхронными API.