Поддержка AIO в Linux

Кто-нибудь знает, где я могу получить последнюю информацию о состоянии поддержки ядром для aio в последней версии ядра Linux ?. Поиск в Google приводит к появлению веб-страниц, которые могут безнадежно устареть.

Редактировать:

В частности, меня интересуют дескрипторы, не связанные с файлами, такие как каналы и сокеты. В Интернете указано, что поддержки нет, так ли это до сих пор?

Edit2: То, что я ищу, похоже на Windows OVERLAPPED IO


person doron    schedule 31.10.2011    source источник


Ответы (3)


Поддержка AIO включена в собственно ядро ​​Linux. Вот почему первое обращение в Google предлагает исправления только для ядра Linux 2.4. В версиях 2.6 и 3.0 он уже присутствует.

Если вы посмотрите исходный код ядра Linux, он находится на fs / aio.c

Есть некоторая документация в руководстве GNU libc, но будьте сообщил, что aio возможно не для всех типов файловых дескрипторов Linux. Большая часть общей документации с инструкциями устарела. примерно в 2006 году, что вполне уместно, поскольку именно тогда AIO в Linux попала в заголовки газет.

Обратите внимание, что стандарты POSIX.1b и Unix98 не изменились, так что не могли бы вы уточнить характер «устаревания» примеров?

person Edwin Buck    schedule 31.10.2011
comment
@doron, это первое попадание в Google, о котором я упоминал выше. Стандарт POSIX.1b был разработан в 1997 году, спецификация Unix98 - в 1998 году. Документация середины 2000-х годов не является решающей, просто игнорируйте детали, относящиеся к ядрам до версии 2.6 (например, исправление инструкции). - person Edwin Buck; 31.10.2011
comment
а как насчет поддержки сокетов? - person doron; 31.10.2011
comment
AIO работает с файловыми дескрипторами, сокеты также отслеживаются через файловые дескрипторы. - person Edwin Buck; 31.10.2011
comment
Linux AIO имеет серьезные ограничения, в том числе невозможность использовать буферный кеш. Это похоже на быстрое внедрение какой-то крупной компанией для их конкретных нужд. - person lvella; 31.10.2011
comment
lvella: Итак, если я правильно прочитал, aio - второсортный гражданин Linux, и, вероятно, его следует избегать. - person doron; 01.11.2011
comment
@Edwin - я имею в виду свою первую ссылку выше, где говорится, что сокеты не поддерживаются должным образом aio. - person doron; 01.11.2011

Вам не нужен POSIX AIO (например, man aio) для асинхронного использования сокетов и каналов. Согласно man 3 aio, это даже невозможно. Вместо этого следует использовать неблокирующие файловые дескрипторы вместе с интерфейсом уведомления о событиях, например select(), poll() или epoll. epoll специфичен для Linux, но масштабируется намного лучше, чем первые два.

Чтобы использовать файловые дескрипторы в неблокирующем режиме, вы должны установить флаг O_NONBLOCK для каждого файлового дескриптора:

fcntl(fd, F_SETFL, O_NONBLOCK)

После того, как файловый дескриптор находится в неблокирующем режиме, операции ввода-вывода, такие как read() и write(), никогда не будут блокироваться, но вернут EAGAIN или EWOULDBLOCK, если операция не может быть завершена немедленно. Некоторые более специфические операции, такие как connect(), должны использоваться по-другому в неблокирующем режиме; см. соответствующие страницы руководства.

Чтобы иметь возможность правильно использовать неблокирующие дескриторы файлов, ваше приложение должно быть управляемым событиями. По сути, в main() вам нужно сначала инициализировать материал, а затем войти в цикл обработки событий. Цикл событий постоянно ожидает событий (используя интерфейс уведомления о событиях, например, epoll_wait()), затем проверяет, какие события произошли, и отвечает на них.

Теперь, когда вы говорите read(), а он терпит неудачу с EWOULDBLOCK, вы добавляете его в список файловых дескрипторов, отслеживаемых для удобства чтения; когда провайдер событий указывает на удобочитаемость, попробуйте еще раз.

Точно так же, если вы попытаетесь write(), а EWOULDBLOCK не удастся, вы можете захотеть буферизовать данные и повторить попытку, когда указана возможность записи.

person Ambroz Bizjak    schedule 31.10.2011
comment
Я знаю это. Однако проблема означает, что выполняется больше системных вызовов, чем необходимо на 100%. - person doron; 01.11.2011
comment
Да, это не совсем оптимально, но действительно ли вы наблюдаете проблемы с производительностью? Я считаю, что накладные расходы по сравнению с чистым интерфейсом AIO несущественны, если ваша программа выполняет какую-либо обработку данных, с которыми она работает. - person Ambroz Bizjak; 01.11.2011
comment
К тому времени, когда вы заметите проблемы с производительностью, архитектура будет слишком глубоко укоренившейся, чтобы ее можно было исправить, вы можете эффективно проектировать с нуля. - person doron; 01.11.2011
comment
Действительно? Затем я предлагаю вам сделать абстракцию ввода-вывода в стиле AIO и реализовать ее поверх всего, что предоставляет ОС (сначала попробуйте неблокировать). Если окажется, что неблокирующие сокеты работают слишком медленно, вы можете повторно реализовать эту абстракцию поверх настоящего интерфейса ядра AIO (возможно, вам придется реализовать / улучшить такой интерфейс ядра самостоятельно). Это то, что я сделал в своем проекте с открытым исходным кодом BadVPN; Я использую блокирующие сокеты в Linux, но IOCP (настоящий AIO) в Windows. code.google.com/p/badvpn/source/ просмотреть / транк / система / - person Ambroz Bizjak; 01.11.2011
comment
Думаю, Microsoft промывает тебе мозги, Дорон. Тот факт, что перекрывающийся ввод-вывод является самым быстрым способом ввода-вывода в Windows, не означает, что это лучший способ выполнять ввод-вывод повсюду. Семантика POSIX отличается от семантики Windows. Посмотрите, насколько несовершенны все оболочки POSIX для Windows, и наоборот. Если бы можно было обращаться со всеми платформами одинаково, такие обертки были бы тонкими и быстрыми. - person Warren Young; 04.11.2011
comment
Фактическая проблема заключается в том, что Windows Overlapped IO может обеспечить нулевое копирование памяти, а epoll + nonblock io - нет. POSIX AIO API в принципе может этого добиться, но в Linux есть только неэффективный уровень моделирования. - person ASBai; 12.12.2018
comment
Итак, если сокет готов, NIO или нет, это означает, что поток будет занят фактическим чтением / записью? - person Mangat Rai Modi; 06.06.2019

В 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
comment
Меня не интересует пользовательский aio, поскольку он вряд ли будет эффективным с точки зрения системного вызова, а создание большего количества потоков действительно требует ресурсов. - person doron; 01.11.2011
comment
Да, наверное, это первая мысль, о которой я говорил изначально. Удивительно, но он работает намного лучше и надежнее (насколько я могу судить), чем реализация ядра. Kernel AIO - это более или менее Йо, так что вы хотите DMA? взломать. Если вы превысите какой-то неизвестный порог, не повезло. Если вам нужно что-то, что не является блочным устройством с DMA, не повезло. Если вы хотите использовать буферный кеш, не повезло. Если ... не повезло. С другой стороны, реализация пользовательского пространства GNU просто выполняет AIO в смысле асинхронного ввода-вывода, чего обычно и ожидают. Просто работает. - person Damon; 01.11.2011