LightWeight IP:缓冲区未释放

Ran*_*lue 8 c lwip

我正在使用名为lwip的TCP/IP堆栈.我已经在下面实现了一个函数来发送数据包,灵感来自一个接收数据包的类似回调函数.

每次收到数据包时,我都会使用该pbuf_alloc函数创建一个缓冲区.然后,我使用发送数据包udp_sendto.最后,我使用了释放缓冲区pbuf_free.(参见下面的代码.)

出于某种原因,pbuf_free不释放缓冲区.(我在n数据包之后得到缓冲区溢出,其中n是池大小.)lwip wiki警告:

网络驱动程序也可能不会假设在调用pbuf_free时实际释放了pbuf内存.

我如何强制pbuf_free释放我的缓冲区?如何避免缓冲区溢出?

(我的实现如下.)

static err_t IAP_tftp_send_data_packet(struct udp_pcb *upcb, struct ip_addr *to, int to_port, int block)
{
  err_t err;
  struct pbuf *pkt_buf;
  char packet[TFTP_DATA_PKT_LEN_MAX];
  int bytesRead;
  int bytesToSend;

  /* Specify that we are sending data. */
  IAP_tftp_set_opcode(packet, TFTP_DATA); 

  /* Specify the block number that we are sending. */
  IAP_tftp_set_block(packet, block);

  bytesRead = IAP_tftp_set_data(packet, block);

  if(bytesRead != 0) {
    bytesToSend = TFTP_DATA_PKT_LEN_MAX - (512 - bytesRead + 1);
  } else {
    bytesToSend = TFTP_DATA_PKT_LEN_MAX - 512;
  }

  pkt_buf = pbuf_alloc(PBUF_TRANSPORT, bytesToSend, PBUF_POOL);

  if (!pkt_buf)
  {
    print("(TFTP) Buffer overflow!\r\n");
  }

  /* Copy the file data onto pkt_buf. */
  memcpy(pkt_buf->payload, packet, bytesToSend);

  err = udp_sendto(upcb, pkt_buf, to, to_port);

  /* free the buffer pbuf */
  printf("%d\n\r", pbuf_free(pkt_buf));

  return err;
}
Run Code Online (Sandbox Code Playgroud)

ask*_*ish 7

您使用的是什么版本的lwIP?根据不同的版本,答案变化很大.

在pbuf_alloc()内部调用的memp_malloc()分配函数失败或pbufs链接失败.因此,它返回NULL.

如果传递的参数也包含NULL,则pbuf_alloc()也将返回NULL.(由于NULL参数检查).

在较新的版本中,您能显示MEMP_OVERFLOW_CHECK宏包含的值吗?当宏值> = 2时,lwIP显示不同的行为.

另一个原因可能是如果您使用多线程,pbuf_alloc()内部的锁定机制会失败,可能会导致它返回NULL.

有些版本要求在调用pbuf_alloc()之前调用pbuf_init().

你可以试试这个:

pkt_buf = NULL;//Use NULL, just incase the NULL is not 0 as per your compiler.
pkt_buf = pbuf_alloc(PBUF_TRANSPORT, bytesToSend, PBUF_REF);
if(pkt_buf == NULL)
{
   printf("pbuf_alloc failed.\n");
}
else
{
   /* Do something with the allocated pbufs and free it. */
}
Run Code Online (Sandbox Code Playgroud)

PBUF_REF将不为pbuf分配缓冲区内存.pbuf应仅在单个线程中使用,如果pbuf排队,则应调用pbuf_take来复制缓冲区.

您也可以尝试PBUF_RAM,它将在RAM中分配缓冲区.

有关更多信息,您还可以浏览您正在使用的lwIP版本的源文件.


unw*_*ind 6

最简单的解决方案似乎是制作缓冲区static,即为每次调用重用相同的缓冲区:

static struct pbuf *pkt_buf = NULL;

if( pkt_buf == NULL )
    pkt_buf = pbuf_alloc(PBUF_TRANSPORT, bytesToSend, PBUF_POOL);
if( pkt_buf == NULL )
{
    print("(TFTP) Buffer overflow!\r\n");
}
Run Code Online (Sandbox Code Playgroud)

如果您的方案涉及卸载/重新加载驱动程序,它将泄漏内存.要解决这个问题,请在IAP_tftp_send_data_packet()函数外部使缓冲区静态,并pbuf_free()在驱动程序卸载时调用(假设lwip告诉你).