找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 11469|回復(fù): 1
收起左側(cè)

lwIP bug 導(dǎo)致程序崩潰問(wèn)題的解決

[復(fù)制鏈接]
ID:419956 發(fā)表于 2018-11-2 23:21 | 顯示全部樓層 |閱讀模式
本人使用的LWIP版本號(hào)是LWIP 1.3.2 ,并且使用UCOSII  V2.89系統(tǒng)。

在移植使用的過(guò)程中,使用LWIP只做客戶端或服務(wù)端是沒(méi)有問(wèn)題的。

后來(lái)客戶端和服務(wù)端都集合使用的時(shí)候,碰到了一個(gè)BUG,
for(pcb =tcp_active_pcbs; pcb != NULL; pcb = pcb->next) , 在這個(gè)地方進(jìn)入死循環(huán)了,
pcb 塊申請(qǐng)和釋放的時(shí)候出錯(cuò)了,pcb->net指向自己本身了。后來(lái)在網(wǎng)上查了一大堆資料,
說(shuō)是LWIP1.3.2版本就有這個(gè)問(wèn)題,而1.4.1版本沒(méi)有。

為了解決這個(gè)問(wèn)題就嘗試去移植LWIP1.4.1這個(gè)版本,然后卻發(fā)現(xiàn)1.4.11.3.2版本的郵箱和信號(hào)
量函數(shù)接口都不同了,在UCOSII,V2.8.9下已經(jīng)不能滿足了。相當(dāng)于之前移植的sys_arch.c已經(jīng)
不能適應(yīng)了。LWIP1.4.1在網(wǎng)上的sys_arch.c例子基本都是基于UCOSIII-V3.0.x 來(lái)實(shí)現(xiàn)。所有如果
更換LWIP1.4.1的話,最好也要去替換UCOSII。而又由于之前的工程中已有使用UCOSII,再去替
換工作量又相當(dāng)大,所有想找到一種方式,直接在LWIP1.3.2版本下解決LWIPpcb->net指向自己
本身的問(wèn)題。

后來(lái)發(fā)現(xiàn)這個(gè)問(wèn)題是由于LWIP里面的TCP塊在沒(méi)有接連的情況下,不用close就會(huì)自動(dòng)釋放。如果LWIP
自己釋放過(guò)了,而你自己又操作closeabort釋放一次,那么TCP_PCB內(nèi)存塊就出現(xiàn)問(wèn)題了。那么問(wèn)題
既然找到了,那就想辦法解決。本人想到了一個(gè)修改最少最簡(jiǎn)便的方法來(lái)解決這個(gè)問(wèn)題,僅需修改
2個(gè).c、1個(gè).h文件即可解決這個(gè)問(wèn)題。修改情況如下:


  
需改內(nèi)容
  
解釋
文件名稱
添加內(nèi)容(增加紅色字體)
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 結(jié)構(gòu)體中增加一個(gè)字段,pcb_used。這個(gè)字段值 = 0 = 1。
  
0代表這個(gè)TCP_PCB塊沒(méi)有在使用,已經(jīng)釋放。
  
1代表這個(gè)TCP_PCB塊正在使用,占用內(nèi)存。
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);
  
..............................省略......................................
  
SYS_ARCH_UNPROTECT(old_level);
  
}
在釋放TCP_PCB塊的時(shí)候,如果pcb_used==0,那么這個(gè)TCP_PCB塊已經(jīng)釋放過(guò)了,可能是沒(méi)連接的塊系統(tǒng)自己釋放,也能是自己誤操作,多次釋放?傊还苁裁丛,已經(jīng)釋放過(guò)的不能再釋放了,所有這邊直接return退出。沒(méi)有釋放的正常釋放,只是字段pcb_used0。
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;
  
}
在申請(qǐng)TCP_PCB塊的時(shí)候,把pcb_used1,標(biāo)記這個(gè)塊目前正在使用,占用內(nèi)存。


現(xiàn)在只需要在,structtcp_pcb中添加一個(gè)字段,再加上幾行代碼,就可以解決這個(gè)問(wèn)題了。


評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:275111 發(fā)表于 2019-8-27 11:18 | 顯示全部樓層
佩服。真厲害呀。真在學(xué)習(xí)LWIP。
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表