lwIP TCP IP協議棧的一種實現 2

2021-04-02 18:50:25 字數 2915 閱讀 7071

(很抱歉,前段時間忙,另外,還缺一些上傳!)

(續)6緩衝及記憶體管理

在乙個通訊系統中,緩衝及記憶體管理系統必須能準備好分配不同大小的緩衝區,從包含有幾百位元組有用資料的全長

tcp報文段,到只含幾個位元組的icmp 應答響應。同時,為了避免拷貝,應該盡可能地讓資料型別緩衝區駐留在記憶體中,而不是由網路子系統,如應用記憶體或rom,來管理。

6.1 包緩衝區――pbuf

pbuf是

lwip包的內部表示,被設計為最小化棧的特殊需要。pbufs類似於bsd實現中的mbufs。pbuf結構支援為包內容動態分配記憶體和讓包資料駐留在靜態記憶體中。pbufs能被乙個稱為pbuf鏈的鏈結到乙個鍊錶中,以至乙個包能跨越多個pbufs。

pbufs有三種型別

:pbuf_ram,pbuf_rom和pbuf_pool。圖1表示pbuf_ram型別,包含有存在記憶體中由pbuf子系統管理的包資料。圖2顯示了乙個pbuf鍊錶,第1個是pbuf_ram型別,第2個是pbuf_rom型別,意味著它包含有不被pubf子系統管理的記憶體資料。圖3描述了pbuf_pool,其包含有從固定大小pbuf池中分配來的pbuf。乙個pbuf鏈可以包含多個不同型別的pbuf。

這三種型別有不同的用處。

pbuf_pool型別主要由網路裝置驅動使用,因為分配單個pbuf快速且適合中斷控制代碼使用。pbuf_rom型別由應用程式傳送那些在應用程式記憶體空間中的資料時使用。這些資料不會在pbuf遞交給tcp/ip棧後被修改,因此這個型別主要用於當資料在rom中時。pbuf_rom中指向資料的頭部被存在鍊錶中其前乙個pubf_ram型別的pbuf中,如圖2所示。

pbuf_ram型別也用於應用程式傳送動態產生的資料。這情況下,

pbuf系統不僅為應用程式資料分配記憶體,也為將指向(prepend)資料的頭部分配記憶體。如圖1所示。pbuf系統不能預知哪種頭部將指向(prepend)那些資料,只假定最壞的情況。頭部的大小在編譯時確定。

本質上,進來的

pbuf是pbuf_pool型別,而出去的pbuf是pbuf_rom或pbuf_ram型別。

從圖

1,圖2可以看出pbuf的內部結構。pbuf結構包含有兩個指標,兩個長度字段,乙個標誌字段,和乙個參考計數。next欄位指向統一鍊錶中的下乙個pbuf。有效載荷指標指向該pbuf中資料的起始點。len欄位包含有該pbuf資料內同的長度。tot_len欄位是當前pbuf和所有鍊錶接下來中的len字段值的總和。簡單說,tot_len欄位是len欄位及下乙個pbuf中tot_len字段值的總和。flags欄位表示pbuf型別而ref欄位包含乙個參考計數。next和payload欄位是本地指標,其大小由處理器體系結構決定。兩個長度欄位是16位無符號整數,而flags和ref欄位都是4位元大小。pbuf的總大小決定於使用的處理器體系結構。在32位指標和4位元組校正的體系結構上,總大小是16位元組,而在16位指標和1自己校正的體系結構上,總大小是9位元組。

pbuf模組提供了操作

pbuf的函式。pbuf_alloc()可以分配前面提到的三種型別的pbuf。pbuf_ref()增加引用計數,pbuf_free()釋放分配的空間,它先減少引用計數,當引用計數為0時就釋放pbuf。pbuf_realloc()收縮空間以使pbuf只占用剛好的空間儲存資料。pbuf_header()調整payload指標和長度字段,以使乙個頭部指向pbuf中的資料。pbuf_chain()和pbuf_dechain()用於鍊錶化pbuf。

6.2 記憶體管理

記憶體管理只是簡單地支援

pbuf機制。它處理連續記憶體的分配和釋放,並能收縮先前分配的記憶體塊。記憶體管理使用系統總記憶體貢獻出的小部分,這確保網路系統不會使用所有可用的記憶體,並且其他程式的操作不會因為網路系統使用完所有記憶體而受打斷。

在內部,記憶體管理在每個分配的記憶體塊頭部記錄乙個小的結構以跟蹤所有已分配的記憶體。圖

4所示結構儲存兩個指標分別指向前乙個和後乙個分配的記憶體塊。它同時有乙個已使用標誌指示該記憶體塊是否已經分配。

記憶體分配是通過搜尋乙個未使用的足夠大小的記憶體塊給所請求的空間分配。首次適應法使搜尋時第一塊足夠大小的記憶體被分配出去。當一記憶體塊被釋放時,已用標誌被設為

0。為了防止碎片,通過檢查前乙個和後乙個記憶體塊的已用標誌,可以把未用的塊結合起來形成更大的未用的塊。

7網路層介面

lwip中物理網路硬體的裝置驅動被表示為乙個像

bsd中那樣的乙個網路介面結構。圖5顯示了網路介面結構。網路介面被儲存在乙個全域性的鍊錶中,通過結構中的next指標連線起來。每個網路介面都有乙個名字,存在name欄位中。兩字元名字指示網路介面使用的裝置驅動種類,只在執行時通過人工操作完成介面配置。name欄位由裝置驅動設定,並且能反映出由網路介面表示的硬體型別。例如,藍芽驅動的網路介面其name值應為bt,ieee 802.11b wlan其name值應為wl。因為name值沒必要是唯一的,因此num欄位用來區別統一型別驅動的不同網路介面。

三個

ip位址,ip_addr, netmask和gw由ip層使用來傳送和接收包,將在下面描述它們。不可能使用超過乙個ip位址去配置乙個網路介面,乙個網路介面只能對應乙個ip位址。

input指標指向乙個函式,該函式是在收到乙個包時由裝置驅動呼叫的。

乙個網路介面是通過

output指標指向乙個裝置驅動的。這個指標指向裝置驅動中的乙個函式用來在物理網路上傳輸乙個包,ip層要傳送包時會呼叫該函式。這個欄位由裝置驅動初始化函式設定。output函式的第三個引數,ipaddr,是將接收實際鏈路層幀的主機ip位址,它沒必要和ip包的目的位址一樣。特別地,當傳送乙個ip到不在本地網路的主機時,鏈路層幀將被送到網路中的一台路由器上。這種情況下,傳遞給output函式的ip位址將會是該路由器的ip位址。

最後,state指標指向裝置驅動指示網路介面的特定狀態,由裝置驅動設定。

(待續)

calc the sum的一種利用棧的解法

這道題解法很多,是遞迴演算法的一道很典型的例題,並且用字串來解效率也還可以 我也不知道時間複雜度多少算效率高,還沒學資料結構 用棧來解效率不高記憶體還大,僅僅為了滿足本人的好奇心而已 不過我們可以先來複習一下什麼是棧 以下是我對棧的理解 棧 stack 是一種線性的表,只能在表末尾進行運算,比如pu...

如何新增一種新Case協議

這裡以新增基礎http為例 首先要在指令碼檔案 xml檔案 中定義好這種協議的基本資訊 您必須在這裡設計好您協議預先需要的資料 比如串列埠協議,那波特率,串口號等可能是不會經常改變的就可以在這裡先預設定 然後您需要在這裡新增您的新協議名稱 在 caseexecutiveactuator 下 接著,您...

tsunami 一種基於UDP協議的快速傳輸

一.需求 最近在做資料庫遷移,經常需要打包例項傳輸,傳統scp感覺很慢。二.軟體資訊 1.軟體主頁 2.軟體安裝 直接原始碼make make install 三.簡單使用 以下介紹簡明步驟 在源機子開啟tsunami程序 tsunamid 在目標機子 connect ip get 四.測試 在幾台...