Как лучше всего обрабатывать большие буферы в многоуровневом стеке протоколов? - PullRequest
7 голосов
/ 31 августа 2009

Я работаю над простым стеком протоколов для небольшой встроенной системы (multidrop, тип RS485). В этом стеке проигрышные модели после уровней OSI:

  1. Применение
  2. Сеть
  3. Канальный
  4. физический (серийный драйвер)

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

Я буду использовать свой собственный буферный пул статически распределенных блоков фиксированного размера для хранения двоичных пакетов. (Нет malloc / free в этом приложении.)

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

Для трехслойного стека это будет 2 операции копирования и 3 выделенных буфера.

Есть ли лучший способ сделать это и при этом поддерживать чистое разделение уровней протокола?

Чтобы лучше закрепить обсуждение, допустим, что пакеты обычно имеют размер около 2 КБ, а процессор представляет собой небольшой 8-битный микро, работающий на 8 МГц.

Ответы [ 3 ]

7 голосов
/ 31 августа 2009

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

  • Буфер запросов прикладного уровня длина LA от сетевого уровня.
  • Сетевой уровень запрашивает длину буфера LA + LN от Datalink Layer.
  • Канал уровня данных запрашивает длину буфера LA + LN + LD от физического уровня.
  • Физический уровень извлекает буфер из пула буферов.
  • Физический уровень возвращает buffer + phdr_len в слой данных.
  • Уровень канала данных возвращает buffer + phdr_len + dhdr_len на сетевой уровень.
  • Сетевой уровень возвращает buffer + phdr_len + dhdr_len + nhdr_len на прикладном уровне.
  • Прикладной уровень заполняет данные в предоставленном буфере и вызывает сетевой уровень для передачи.
  • Сетевой уровень предварительно устанавливает заголовок и вызывает уровень передачи данных для передачи.
  • Datalink Layer добавляет заголовок и вызывает физический уровень для передачи.
  • Физический уровень предшествует заголовку и переходит на оборудование.
4 голосов
/ 31 августа 2009

Создать структуру буфера. Зная максимальный размер на нижнем уровне, выделите достаточно места на буфере на верхнем уровне, чтобы добавить каждый последующий уровень по мере того, как он идет вниз по стеку. Каждый слой перемещает указатель в структуре буфера при добавлении слоя.

На нижнем уровне начало буфера записывается в указателе в структуре буфера. Данные для отправки находятся в непрерывном буфере. Данные не были скопированы на каждом слое.

Переходя снизу вверх, вы снимаете слои внутри структуры буфера.

0 голосов
/ 31 августа 2009

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

Полагаю, вы даете пример API для буфера передачи.

Я думаю, что вы можете оставить тот же API, если добавите ограничение, согласно которому тот, кто вызывает этот API, не может использовать или снова трогать этот буфер до тех пор, пока они не получат последующее уведомление о завершении операции передачи: так, чтобы вызвать API неявно передает право собственности на этот буфер.

...