В Linux существует два типа AIO.
Один из них - ядро-AIO. Он уродлив и иногда ведет себя не в соответствии с документацией (например, он будет работать синхронно при определенных условиях, и вы не сможете что-то с этим сделать, и он не будет должным образом отменять запросы в полете при определенных условиях и т. Д.) и т.д). Он не работает с каналами.
Это io_
функции. Обратите внимание, что вы должны установить связь с -laio
, который вы должны установить отдельно в некоторых системах (например, Debian / Ubuntu).
Второй - это чистая реализация пользовательского пространства (glibc), которая по запросу порождает потоки для обработки запросов. Он хорошо документирован, работает достаточно хорошо и согласно документации, и он работает практически со всем, что является дескриптором файла, включая каналы.
Это aio_
вид функций. Я бы настоятельно рекомендовал использовать их, даже если они представляют собой «неуклюжую реализацию пользовательского пространства» - они прекрасно работают.
Между тем, оба работают с eventfd в качестве механизма уведомления, кстати, хотя версия ядра все еще не была документирована в прошлый раз, когда я смотрел (но функция находится в заголовках).
Или, как указал Амброз Бизьяк, вообще пропустите AIO, поскольку, как вы описываете, это не является строго необходимым.
РЕДАКТИРОВАТЬ:
С другой стороны, поскольку вы использовали слова «трубы» и «сокеты», знаете ли вы о vmsplice и splice? Это, вероятно, наиболее эффективные функции для отправки данных в / из сокетов / каналов. К сожалению, это еще один из тех двусмысленно задокументированных, трудных для понимания хаков с неясными подводными камнями. Действуйте на свой страх и риск, вас предупредили.
splice
позволяет передавать данные из сокета (или любого файлового дескриптора) в канал или наоборот. vmsplice
позволяет передавать данные между пространством приложения и конвейером.
По иронии судьбы, vmsplice
в идеале должен делать то же самое (переназначить страницы, или «играть с ВМ»), который один конкретный человек принял в качестве аргумента, чтобы утверждать, что все BSD разработчики идиоты, еще в 2006 году.
Итак, хорошие новости, плохие новости заключаются в том, что существует «секретный предел» того, сколько данных вы можете переместить. Насколько я помню, это 64кБ (но настраивается где-то в / proc). Если у вас больше данных, вы должны работать с несколькими порциями, предположительно с несколькими буферами каналов, заполняя один, пока другой читается, и повторно использовать старые буферы каналов после того, как они будут выполнены.
И здесь все усложняется . Если вы просмотрите обсуждения Kernel Trap, вы обнаружите, что даже Великий Мастер не на 100% уверен в том, когда безопасно перезаписать старый буфер при манипулировании несколькими буферами.
Кроме того, чтобы vmsplice
действительно работал (т. Е. Переназначение страниц вместо копирования), вам нужно использовать флаг «ПОДАРОК», и, по крайней мере, мне не ясно из документации, что тогда станет с этой памятью . Следуя инструкциям в письме, вам может потребоваться утечка памяти, поскольку вам никогда не разрешат прикасаться к ней снова. Конечно, этого не может быть. Может я просто дурак.
В конце концов я отказался от этого и просто согласился использовать epoll
для готовности и неблокирующие сокеты с обычным нормальным write
. Эта комбинация, возможно, не самая лучшая, но она хорошо задокументирована и работает так, как задокументировано.
person
Damon
schedule
31.10.2011