LINUX.ORG.RU

zero-copy сервер


0

0

хочу написать zero-copy сервер. реализовано это следующим образом - ядро через nmap пробрасывает приемный буффер в приложение, после чего приложение может читать данные без копирования их из ядра. к сожалению, в буффер копируются Ethernet кадры целиком, что требует от меня самостоятельно парсить заголовки. (более того, работает это в линуксе только с RAW сокетами) однако, я слышал, что на некоторых сетевых картах есть такая функция как header splitting, которая копирует шапки и содержимое протокола в разные места, что позволяет заносить в непрерывный буффер только содержимое TCP.

кто-нибудь делал это? информации по этой теме очень мало. Есть ли у вас ссылки на более подробное описание функции header splitting, примеры zero-copy сервера, информация по карточкам, которые поддерживают такие функции?


ядро через nmap

nmap? Уверен?

кто-нибудь делал это? информации по этой теме очень мало. Есть ли у вас ссылки на более подробное описание функции header splitting, примеры zero-copy сервера, информация по карточкам, которые поддерживают такие функции?

google: OFED, RDMA.

mv ★★★★★
()

после чего приложение может читать данные без копирования их из ядра.

оно не сможет так делать

что позволяет заносить в непрерывный буффер только содержимое TCP.

Что мешает принимать только TCP?!

что требует от меня самостоятельно парсить заголовки

видимо придётся.

Boy_from_Jungle ★★★★
()
Ответ на: комментарий от mv

>nmap? Уверен?

mmap

google: OFED, RDMA.

это требует установки соответствующего софта у клиента

b3qkc
() автор топика
Ответ на: комментарий от Boy_from_Jungle

>оно не сможет так делать

http://www.ntop.org/PF_RING.html

Что мешает принимать только TCP?!

то, что для этого принятые непрерывным потоком ethernet пакеты придется парсить, вычленять из них содержимое TCP, и копировать его в другое место. таким образом это уже получится не zero-copy

видимо придётся.

я не хочу писать свой tcp/ip стек по ряду причин

b3qkc
() автор топика
Ответ на: комментарий от Boy_from_Jungle

>Не хочешь ничего делать, и получить результат?!

не совсем понял, где я проявляю такой подход.

Лучшее что для может быть, и не городить костыли, это заюзать sendfile()

мне нужно отсылать данные из юзерспейса

b3qkc
() автор топика
Ответ на: комментарий от Boy_from_Jungle

>ну так sendfile() это и делает.

The sendfile() system call sends a regular file specified by descriptor fd out a stream socket specified by descriptor s.

Я не вижу, где он позволяет послать данные из юзерспейса. насколько я понимаю, он может выслать файл, который читается в буффер ядра через дма, и вот уже оттуда, без проброски в юзерспейс, высылается на нужное соединение. для того, чтобы при посылке файла избежать двух копирований он и был введен. он не спасает от копирования данных из юрезспейса. Ну либо я чего-то не понимаю, в таком случае прошу меня поправить.

кроме того, отсылка, насколько я понимаю, это, в общем, не главное (она, по крайней мере, не зависит от карточки), самая большая проблема - прием, потому что без разделения заголовка и содержимого получить буффер с непрерывным TCP потоком нельзя. и вот примеров использования этой технологии я как раз не нашел (отсылка не должна изменять интерфейс, поэтому искать примеры гуглом не получится. но тут хотя бы все должно работать, судя по манам)

Я уже начанаю сомневаться, что в сети вообще доступны примеры zero-copy серверов

b3qkc
() автор топика

Жесть

А ты уверен что тебе удастся решить эту задачу, не заплатив за это слишком высокую цену. Похоже этой проблемой озадачиваются уже давно, и ни к чему нормальному пока ещё не пришли.

У меня сложилось впечатление, что для нормальной реализации идеологии zero-copy надо полностью переделать архитектуру ввода-вывода данных и систему управления жизненным циклом буферов данных. Приложение и драйвер должны работать не с потоком байт (read()/write()), а с очередями блоков данных. Каждый блок указывает на кусок данных внутри буфера.

Например сетевая подсистема ядра выделяет буфер определенного размера для кадра. Кадр будет содержать заголовок и непрерывный кусок с данными. Приложению мы передадим «блок» - структуру,ссылающуюся на нужную часть данных в буфере. Для следующего кадра сетевая подсистема выделит другой буфер и т.д. Буферы освободятся только тогда, когда данные в них уже никому не будут нужны, т.е. нет ни одного «блока» ни в одной из очередей который бы ссылался на этот буфер.

Вместо read()/write() будут pop_blocks()/push_blocks().

В тогда да. Ни одного лишнего копирования байт данных из буфера в буфер. Вместо этого будет копирование мелких «блоков» из очереди в очередь.

Но стоит ли оно того. Видно что такой подход будет эффективен тогда, когда надо будет работать с блоками большого размера. Значит его нельзя назвать универсальным. Так же нельзя не заметить существенное усложнение системы, что наверняка приведет к трудноуловимым ошибкам.

pathfinder ★★★★
()
Ответ на: Жесть от pathfinder

>А ты уверен что тебе уд....

реализация PF_RING позволяет принимать данные без копирования, при этом не заморачиваясь ни с какими блоками. я вообще не понял из твоего сообщения, зачем нужны блоки для zero copy

b3qkc
() автор топика
Ответ на: комментарий от b3qkc

Почитал более подробно про PF_RING и совсем запутался. Почему решили, что PF_RING это zero-copy. Вот кусок из примера:

while(1) {
  u_char buffer[2048];
  struct pfring_pkthdr hdr;
  if(pfring_recv(pd, (char*)buffer, sizeof(buffer), &hdr, 1) > 0)
    dummyProcesssPacket(&hdr, buffer);
}
Хорошо видно, что данные КОПИРУЮТСЯ в стек в массив buffer из ядра.

pathfinder ★★★★
()
Ответ на: комментарий от pathfinder

>Почитал более подробно про PF_RING и совсем запутался.

там есть несколько вариантов. некоторые работают именно через mmap

Если вам интересен именно вариант с mmap, то вы можете взять его здесь:

http://public.lanl.gov/cpw/

вот по этой ссылке - http://public.lanl.gov/cpw/libpcap-0.9.8.20081128.tar.gz качаете libpcap с поддержкой mmap, после чего можете, например, заглянуть сюда: libpcap-0.9.8.20081128 $ vim pcap-ring.c +136

там вы можете увидеть, как буффер мапится из ядра в адресное пространство процесса (во всяком случае, в соответствии с документацией там происходит именно это). проблема в том, что PF_RING работает только с сырыми сокетами, а мне нужно TCP. я уже начинаю думать, что нужно доделывать самому

b3qkc
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.