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

时间:2010-07-21 19:38:49

标签: c memory-management stack memcpy

成像具有一堆协议和一些巧妙涵盖的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 个答案:

答案 0 :(得分:2)

您可能对本文感兴趣:Alan Cox撰写的"Network Buffers and Memory Management"。基本上,你有缓冲区和指向缓冲区不同有趣部分的几个指针:协议头,数据......最初你通过将数据指针设置为(buffer_start + max_headers_size)来为头保留一些空间,每个层都获得一个指针离缓冲区的起点更近。

我确信BSD的mbuf必须有类似的描述。

修改:

David Miller(Linux网络维护者)有这篇文章"How SKBs work"

答案 1 :(得分:0)

这听起来像“零拷贝”。我不是专家所以搜索那个词你会发现各种各样的参考文献。