Эффективные сокеты Linux (DMA / ноль-копия) - PullRequest
30 голосов
/ 01 декабря 2009

Я создаю очень высокопроизводительный сервер Linux (на основе epoll, неблокирующих сокетов и асинхронного дискового ввода-вывода [на основе io_submit / io_getevents / eventfd]). Некоторые из моих тестов показывают, что способ работы с сокетами недостаточно эффективен для моих требований. В частности, я обеспокоен получением данных из буфера пользовательского пространства на сетевую карту и с сетевой карты обратно в буфер пользовательского пространства (давайте пока проигнорируем вызов sendfile).

Из того, что я понимаю, вызов read / write для неблокирующего сокета Linux не является полностью асинхронным - системный вызов блокируется, когда он копирует буфер из пространства пользователя в ядро ​​(или наоборот), и только затем возвращается. Есть ли способ избежать этого подслушивания в Linux? В частности, есть ли полностью асинхронный вызов записи, который я могу сделать в сокете, который немедленно возвратил бы, DMA буфер пользовательского пространства к сетевой карте по мере необходимости, и сигнал / установка события / и т.д. по окончании? Я знаю, что в Windows есть интерфейс для этого, но я ничего не смог найти в Linux.

Спасибо!

Ответы [ 2 ]

19 голосов
/ 02 декабря 2009

Недавно на linux-kernel были разговоры о предоставлении API для чего-то подобного, но камнем преткновения является то, что вы не можете использовать DMA из общих буферов пространства пользователя на сетевую карту, потому что:

  • То, что выглядит как непрерывные данные в линейном адресном пространстве пользовательского пространства, вероятно, не является непрерывным в физической памяти, что является проблемой, если сетевая карта не выполняет DMA-сборку с разбросом;
  • На многих машинах не все адреса физической памяти «DMA-способны». В настоящее время приложение для пользовательского пространства не может специально запрашивать буфер с поддержкой DMA.

В последних версиях ядра вы можете попытаться использовать вместе vmsplice и splice для достижения того, что вы хотите - vmsplice страниц (с SPLICE_F_GIFT), которые вы хотите отправить в канал, затем splice их ( с SPLICE_F_MOVE) из трубы в розетку.

1 голос
/ 02 декабря 2009

AFAIK вы используете самые эффективные звонки из доступных, если вы не можете использовать sendfile (2). Различные аспекты эффективного высокопроизводительного сетевого кода охватываются Проблема C10K

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...