找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 133|回复: 0
收起左侧

关于LWIP的pcb->next指向pcb自身,造成死机问题解决方法

[复制链接]
ID:745515 发表于 2026-1-3 19:05 | 显示全部楼层 |阅读模式
想要群里的一个资源,没想到什么拿得出手的,分享一个曾经项目的经验,一直存在电脑里,主要是关于lwip1.3.2使用时指针指向自身导致程序卡死,大概的现象就是抓包的话可以看到一直有ARP发出,应答之后还是不停的发ARP,详细的解决方案我整理成了文档,希望能帮到需要的人。

截图.png
本人使用的LWIP版本号是LWIP 1.3.2 ,并且使用UCOSII  V2.89系统。
在移植使用的过程中,使用LWIP只做客户端或服务端是没有问题的。后来客户端和服务端都集合使用的时候,碰到了一个BUG,for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) , 在这个地方进入死循环了,即pcb 块申请和释放的时候出错了,pcb->next指向自己本身了。后来在网上查了一大堆资料,说是LWIP1.3.2版本就有这个问题,而1.4.1版本没有。为了解决这个问题就尝试去移植LWIP1.4.1这个版本,然后却发现1.4.1与1.3.2版本的邮箱和信号量函数接口都不同了,在UCOSII,V2.8.9下已经不能满足了。相当于之前移植的sys_arch.c已经不能适应了。LWIP1.4.1在网上的sys_arch.c例子基本都是基于UCOSIII-V3.0.x 来实现。所有如果更换LWIP1.4.1的话,最好也要去替换UCOSII。而又由于之前的工程中已有使用UCOSII,再去替换工作量又相当大,所有想找到一种方式,直接在LWIP1.3.2版本下解决LWIP的pcb->net指向自己本身的问题。
后来发现这个问题是由于LWIP里面的TCP块在没有接连的情况下,不用close就会自动释放。如果LWIP自己释放过了,而你自己又操作close或abort释放一次,那么TCP_PCB内存块就出现问题了。那么问题既然找到了,那就想办法解决。本人想到了一个修改最少最简便的方法来解决这个问题,仅需修改2个.c、1个.h文件即可解决这个问题。修改情况如下:

tcp.h
/* the TCP protocol control block */
struct tcp_pcb {
/** common PCB members */
  IP_PCB;
/** protocol specific PCB members */
  TCP_PCB_COMMON(struct tcp_pcb);
..............................省略......................................

  /* KEEPALIVE counter */
  u8_t keep_cnt_sent;

  u8_t pcb_used;
};
在struct tcp_pcb 结构体中增加一个字段,pcb_used。这个字段值 = 0 或 = 1。
0代表这个TCP_PCB块没有在使用,已经释放。
1代表这个TCP_PCB块正在使用,占用内存。

memp.c
void
memp_free(memp_t type, void *mem)
{
  struct memp *memp;
  struct tcp_pcb *pcb;
  if(type == MEMP_TCP_PCB ){
      pcb = (struct tcp_pcb *)mem;
    if(pcb->pcb_used == 0){
        return;
    }
    pcb->pcb_used = 0;
  }

  SYS_ARCH_DECL_PROTECT(old_level);
..............................省略......................................
在释放TCP_PCB块的时候,如果pcb_used==0,那么这个TCP_PCB块已经释放过了,可能是没连接的块系统自己释放,也能是自己误操作,多次释放。总之,不管什么原因,已经释放过的不能再释放了,所有这边直接return退出。没有释放的正常释放,只是字段pcb_used置0。

tcp.c
struct tcp_pcb *
tcp_alloc(u8_t prio)
{
  struct tcp_pcb *pcb;
  u32_t iss;
  
  pcb = memp_malloc(MEMP_TCP_PCB);
  if (pcb == NULL) {
   ..............................省略......................................
  }
  if (pcb != NULL) {
    memset(pcb, 0, sizeof(struct tcp_pcb));
    ..............................省略......................................
    pcb->keep_cnt_sent = 0;
    pcb->pcb_used = 1;
  }
  return pcb;
}
在申请TCP_PCB块的时候,把pcb_used置1,标记这个块目前正在使用,占用内存。

只需要在,struct tcp_pcb中添加一个字段,再加上几行代码,就可以解决这个问题了。

以上图文的Word格式文档下载(内容和本网页上的一模一样,方便大家保存):
关于LWIP的pcb-》next 指向pcb自身,造成死机问题解决方法.zip (5.29 KB, 下载次数: 0)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表