1

Imaging 有一堆协议和一些 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 中减去并让上层代码直接从末尾/右侧填充全局缓冲区,计算每个层标头的正确偏移量和实际有效负载的偏移量边。

这听起来合理吗?是否有替代的,也许更优雅的方法?

4

2 回答 2

2

您可能对这篇文章感兴趣: Alan Cox 的“网络缓冲区和内存管理”。基本上,你有一个缓冲区和几个指向该缓冲区不同有趣部分的指针:协议头、数据……最初,你通过将数据指针设置为 (buffer_start + max_headers_size) 为标头保留一些空间,并且每一层都有一个指针更接近缓冲区的开始。

我敢肯定 BSD 的 mbufs 在某处一定有类似的描述。

编辑:

David Miller(Linux 网络维护者)有这篇文章“SKB 的工作原理”

于 2010-07-21T19:54:07.523 回答
0

这听起来像“零拷贝”。我不是专家,所以搜索该术语,您会找到各种参考资料。

于 2010-07-21T19:54:50.143 回答