Подтвердить что ты не робот

Эффективные сокеты Linux (DMA/zero-copy)

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

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

Спасибо!

4b9b3361

Ответ 1

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

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

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

Ответ 2

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