Обработка изображений наличия стопки протоколов и некоторого кода 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 () s в этом коде, таким образом, я воображаю что-то как:
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, и разрешение верхнему уровню кодировать затем заполняет глобальный буфер непосредственно от конца / правая сторона.
Это звучит разумным? Существует ли альтернатива, возможно, более изящные подходы?
Возможно, вас заинтересует эта статья: «Сетевые буферы и управление памятью» Алана Кокса. По сути, у вас есть буфер и несколько указателей на разные интересные части этого буфера: заголовки протокола, данные, ... Первоначально вы резервируете некоторое пространство для заголовков, устанавливая указатель данных на (buffer_start + max_headers_size), и каждый уровень получает указатель ближе к началу буфера.
Я уверен, что где-то должно быть подобное описание для mbufs BSD.
РЕДАКТИРОВАТЬ:
Дэвид Миллер (специалист по поддержке сетей Linux) написал статью «Как работают SKB»
Это звучит как «Нулевое копирование». Я не эксперт, поэтому ищите этот термин, и вы найдете всевозможные ссылки.