通过直接写入下面的发送缓冲区来保存堆栈

发布于 2024-09-11 04:48:42 字数 1635 浏览 6 评论 0原文

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

这听起来合理吗?是否有其他的、也许更优雅的方法?

Imaging having a stack of protocols and some c/cpp code that neatly covers
sending on each layer. Each send function uses the layer below to add
another header until the whole message is eventually placed into a
continuous global buffer on layer 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);
}

Now the data is moved to some global variable and actually transferred:

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);
}

I'd like to reduce both the stack usage and the number of memcpy()s in this
code, so I imagine something like:

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

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

  ...
}

My idea would be to have something at the bottom that would calculate the proper offsets for each layers header and the offset for the actual payload by continuously subtracting from MAX_MSG_SIZE and letting the upper layer code then fill in the global buffer directly from the end / right side.

Does this sound sensible? Are there alternative, perhaps more elegant approaches?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我一向站在原地 2024-09-18 04:48:42

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

我确信 BSD 的 mbufs 一定有类似的描述。

编辑:

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

You may be interested in this article: "Network Buffers and Memory Management" by Alan Cox. Basically, you have the buffer and several pointers to different interesting parts of that buffer: protocol headers, data, ... Initially you reserve some space for headers by setting the data pointer to (buffer_start + max_headers_size), and each layer gets a pointer nearer to the start of the buffer.

I'm sure there must be a similar description somewhere for BSD's mbufs.

EDIT:

David Miller (Linux networking maintainer) has this article "How SKBs work"

一场春暖 2024-09-18 04:48:42

这听起来像“零复制”。我不是专家,因此搜索该术语,您会找到各种参考资料。

This sounds like "Zero Copy." I'm no expert so search for that term and you'll find all sorts of references.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文