Сохранение стека путем прямой записи в буфер отправки ниже - PullRequest
1 голос
/ 21 июля 2010

Изображения, имеющие стек протоколов и некоторый код c / cpp, который аккуратно охватывает отправка на каждый слой. Каждая функция отправки использует слой ниже, чтобы добавить другой заголовок, пока все сообщение не будет в конечном итоге помещено в непрерывный глобальный буфер на уровне 0:

void SendLayer2(void * payload, unsigned int payload_length)
{
  Layer2Header header;   /* eat some stack */
  const int msg_length = sizeof(header) + payload_length;

  char msg[msg_length];  /* and have some more */
  memset(msg, 0, sizeof(msg));

  header.whatever = 42;
  memcpy(&buffer[sizeof(header)], payload, payload_length);

  SendLayer1(buffer, msg_length);
}

void SendLayer1(void * payload, unsigned int payload_length)
{
  Layer1Header header;   /* eat some stack */
  const int msg_length = sizeof(header) + payload_length;

  char msg[msg_length];  /* and have some more */
  memset(msg, 0, sizeof(msg));

  header.whatever = 42;
  memcpy(&buffer[sizeof(header)], payload, payload_length);

  SendLayer0(buffer, msg_length);
}

Теперь данные перемещаются в некоторую глобальную переменную и фактически передаются:

char globalSendBuffer[MAX_MSG_SIZE];
void SendLayer0(void * payload, unsigned int payload_length)
{
  // Some clever locking for the global buffer goes here

  memcpy(globalSendBuffer, payload, payload_length);
  SendDataViaCopper(globalSendBuffer, payload_length);
}

Я бы хотел уменьшить использование стека и количество memcpy () в этом код, поэтому я представляю что-то вроде:

void SendLayer2(void * payload, unsigned int payload_length)
{            
  Layer2Header * header = GetHeader2Pointer();
  header->whatever = 42;

  void * buffer = GetPayload2Pointer();
  memcpy(buffer, payload, payload_length);

  ...
}

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

Это звучит разумно? Есть ли альтернативные, возможно, более элегантные подходы?

Ответы [ 2 ]

2 голосов
/ 21 июля 2010

Вас может заинтересовать эта статья: «Сетевые буферы и управление памятью» от Alan Cox. По сути, у вас есть буфер и несколько указателей на различные интересные части этого буфера: заголовки протокола, данные, ... Изначально вы резервируете некоторое пространство для заголовков, устанавливая указатель данных на (buffer_start + max_headers_size), и каждый уровень получает указатель ближе к началу буфера.

Я уверен, что где-то должно быть похожее описание для mbufs BSD.

EDIT:

Дэвид Миллер (сопровождающий сети Linux) имеет эту статью «Как работают SKB»

0 голосов
/ 21 июля 2010

Это звучит как "Zero Copy".Я не эксперт, поэтому ищите этот термин, и вы найдете все виды ссылок.

...