<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                數據包pbuf的釋放是必須的,因為當內核處理完數據就要將這些資源進行回收,否則就會造成內存泄漏,在后續的數據處理中無法再次申請內存。當底層將數據發送出去后或者當應用層將數據處理完畢的時候,數據包就要被釋放掉。 當然,既然要釋放數據包,那么肯定有條件,pbuf中ref字段就是記錄pbuf數據包被引用的次數,在申請pbuf的時候,ref字段就被初始化為1,當釋放pbuf的時候,先將ref減1,如果ref減1后為0,則表示能釋放pbuf數據包,此外,能被內核釋放的pbuf數據包只能是首節點或者其他地方未被引用過的節點,如果用戶錯誤地調用pbuf釋放函數,將pbuf鏈表中的某個中間節點刪除了,那么必然會導致錯誤。 前面我們也說了,一個數據包可能會使用鏈表的形式將多個pbuf連接起來,那么假如刪除一個首節點,怎么保證刪除完屬于一個數據包的數據呢?很簡單,LwIP的數據包釋放函數會自動刪除屬于一個數據包中連同首節點在內所有pbuf,舉個例子,假設一個數據包需要3個pbuf連接起來,那么在刪除第一個pbuf的時候,內核會檢測一下它下一個pbuf釋放與首節點是否存儲同一個數據包的數據,如果是那就將第二個節點也刪除掉,同理第三個也會被刪除。但如果刪除某個pbuf鏈表的首節點時,鏈表中第二個節點的pbuf中ref字段不為0,則表示該節點還在其他地方被引用,那么第二個節點不與第一個節點存儲同一個數據包,那么就不會刪除第二個節點。 下面用示意圖來解釋一下刪除的過程,假設有4個pbuf鏈表,鏈表中每個pbuf的ref都有一個值,具體見圖 6?5,當調用pbuf\_free()刪除第一個節點的時候,剩下的pbuf變化情況,具體見。 ![](https://box.kancloud.cn/af3e853ba405d070e771a8a232d94895_855x472.png) ![](https://box.kancloud.cn/f655926d2a73c424b51d8301a436caeb_837x462.png) 從這兩張圖中我們也看到了,當刪除第一個節點后,如果后續的pbuf的ref為1(即與第一個節點存儲同一個數據包),那么該節點也會被刪除。第一個pbuf鏈表在刪除首節點之后就不存在節點;第二個pbuf鏈表在刪除首節點后只存在pbuf3;第三個pbuf鏈表在刪除首節點后還存在pbuf2與pbuf3;第四個鏈表還不能刪除首節點,因為該數據包還在其他地方被引用了。 pbuf\_free()函數源碼具體見 ``` 1 u8_t 2 pbuf_free(struct pbuf *p) 3 { 4 u8_t alloc_src; 5 struct pbuf *q; 6 u8_t count; 7 8 if (p == NULL) 9 { 10 return 0; (1) 11 } 12 13 PERF_START; 14 15 count = 0; 16 17 while (p != NULL) 18 { 19 LWIP_PBUF_REF_T ref; 20 21 SYS_ARCH_DECL_PROTECT(old_level); 22 23 SYS_ARCH_PROTECT(old_level); 24 25 ref = --(p->ref); (2) 26 SYS_ARCH_UNPROTECT(old_level); 27 /* this pbuf is no longer referenced to? */ 28 if (ref == 0) 29 { 30 /* remember next pbuf in chain for next iteration */ 31 q = p->next; (3) 32 33 alloc_src = pbuf_get_allocsrc(p); (4) 34 /* is this a pbuf from the pool? */ 35 if (alloc_src == PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF_POOL) 36 { 37 memp_free(MEMP_PBUF_POOL, p); 38 /* is this a ROM or RAM referencing pbuf? */ 39 } 40 else if (alloc_src == PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF) 41 { 42 memp_free(MEMP_PBUF, p); 43 /* type == PBUF_RAM */ 44 } 45 else if (alloc_src == PBUF_TYPE_ALLOC_SRC_MASK_STD_HEAP) 46 { 47 mem_free(p); 48 } 49 else 50 { 51 /* @todo: support freeing other types */ 52 LWIP_ASSERT("invalid pbuf type", 0); 53 } 54 count++; (5) 55 /* proceed to next pbuf */ 56 p = q; (6) 57 /* p->ref > 0, this pbuf is still referenced to */ 58 /* (and so the remaining pbufs in chain as well) */ 59 } 60 else 61 { 62 /* stop walking through the chain */ 63 p = NULL; 64 } 65 } 66 PERF_STOP("pbuf_free"); 67 /* return number of de-allocated pbufs */ 68 return count; 69 } ``` (1):如果釋放的pbuf地址為空,則直接返回。 (2):將pbuf中ref字段減一。 (3):若ref為0,表示該pbuf被引用次數為0,則可以刪除該pbuf,用q記錄下當前pbuf的下一個pbuf。 (4):獲取當前pbuf的類型,根據不一樣的類型進行不一樣的釋放操作,如果是從內存池中申請的pbuf,則調用memp_free()函數進行釋放,如PBUF_POOL、PBUF_ROM和PBUF_REF類型的pbuf,如果是從內存堆中申請的,就調用mem_free()函數進行釋放內存,如PBUF_RAM類型的pbuf。 (5):記錄刪除的pbuf個數。 (6):處理鏈表中的下一個pbuf,直到pbuf中引用次數不為0才退出。 pbuf的釋放要小心,如果pbuf是串成鏈表的話, pbuf在釋放的時候,就會把pbuf的ref值減1,然后函數會判斷ref減完之后是不是變成0,如果是0就會根據pbuf的類型調用內存池或者內存堆回收函數進行回收。然后這里就有個很危險的事,對于這個pbuf_free()函數,用戶傳遞的參數必須是鏈表頭指針,假如不是鏈表頭而是指向鏈表中間的某個pbuf的指針,那就很容易出現問題,因為這個pbuf_free()函數可不會幫我們檢查是不是鏈表頭,這樣子勢必會導致一部分pbuf沒被回收,意味著一部分內存池就這樣被泄漏了,以后沒辦法用了。同時,還可能將一些尚未處理的數據回收了,這樣子整個系統就亂套了。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看