簡介
LwIP是Light Weight (輕型)IP協定,有無作業系統的支持都可以運行。LwIP實現的重點是在保持TCP協定主要功能的基礎上減少對RAM 的占用,它只需十幾KB的RAM和40K左右的ROM就可以運行,這使LwIP協定棧適合在低端的
嵌入式系統中使用。
lwIP協定棧主要關注的是怎么樣減少記憶體的使用和代碼的大小,這樣就可以讓lwIP適用於資源有限的小型平台例如嵌入式系統。為了簡化處理過程和記憶體要求,lwIP對API進行了裁減,可以不需要複製一些數據。
模式
lwip提供三種API:1)RAW API 2)lwip API 3)BSD API。
RAW API把協定棧和應用程式放到一個進程裡邊,該接口基於函式回調技術,使用該接口的應用程式可以不用進行連續操作。不過,這會使應用程式編寫難度加大且代 碼不易被理解。為了接收數據,應用程式會向協定棧註冊一個回調函式。該回調函式與特定的連線相關聯,當該關聯的連線到達一個信息包,該回調函式就會被協定 棧調用。這既有優點也有缺點。優點是既然應用程式和TCP/IP協定棧駐留在同一個進程中,那么傳送和接收數據就不再產生進程切換。主要缺點是應用程式不 能使自己陷入長期的連續運算中,這樣會導致通訊性能下降,原因是TCP/IP處理與連續運算是不能並行發生的。這個缺點可以通過把應用程式分為兩部分來克 服,一部分處理通訊,一部分處理運算。
lwip API把接收與處理放在一個執行緒裡面。這樣只要處理流程稍微被延遲,接收就會被阻塞,直接造成頻繁丟包、回響不及時等嚴重問題。因此,接收與協定處理必須 分開。LwIP的作者顯然已經考慮到了這一點,他為我們提供了 tcpip_input() 函式來處理這個問題, 雖然他並沒有在 rawapi 一文中說明。 講到這裡,讀者應該知道tcpip_input()函式投遞的訊息從哪裡來的答案了吧,沒錯,它們來自於由底層網路驅動組成的接收執行緒。我們在編寫網路驅動時, 其接收部分以任務的形式創建。 數據包到達後, 去掉乙太網包頭得到IP包, 然後直接調用tcpip_input()函式將其 投遞到mbox信箱。投遞結束,接收任務繼續下一個數據包的接收,而被投遞得IP包將由TCPIP執行緒繼續處理。這樣,即使某個IP包的處理時間過長也不 會造成頻繁丟包現象的發生。這就是lwip API。
BSD API提供了基於open-read-write-close模型的UNIX標準API,它的最大特點是使應用程式移植到其它系統時比較容易,但用在嵌入式系統中效率比較低,占用資源多。這對於我們的嵌入式套用有時是不能容忍的。
特性
其主要特性如下:
(1)支持多網路接口下的IP轉發;
(4)包括阻塞控制、RTT 估算、快速恢復和快速轉發的TCP(傳輸控制協定);
(5)提供專門的內部回調接口(Raw API),用於提高應用程式性能;
(6)可選擇的Berkeley接口API (在多執行緒情況下使用) 。
(7)在最新的版本中支持ppp
(8) 新版本中增加了的IP fragment的支持.
(9) 支持DHCP協定,動態分配ip地址.
移植
為了移植到μC/OS系統中,需要進行以下調整。
LwIP中需要使用信號量進行通信,所以在sys_arch中應實現相應的信號量
結構體struct sys_semt和處理函式sys_sem_new() 、sys_sem_free() 、sys_sem_signal ( ) 和sys_arch_sem_wait ( ) 。由於μC/OS已經實現了信號量OSEVENT的各種操作,並且功能和LwIP上面幾個函式的目的功能是完全一樣的,所以只要把μC/OS的函式重新包裝成上面的函式,就可直接使用。
LwIP 使用訊息佇列來緩衝、傳遞數據
報文,因此要實現訊息佇列結構sys_mbox_t ,以及相應的操作函式:sys_mbox_new() 、sys_mbox_free () 、sys_mbox _post () 和sys_arch_mbox_fetch() 。μC/OS實現了訊息佇列結構及其操作,但是μC/OS沒有對訊息佇列中的訊息進行管理,因此不能直接使用,必須在μC/OS的基礎上重新實現。具體實現時,對佇列本身的管理利用μC/OS自己的OSQ操作完成,然後使用μC/OS中的記憶體管理模組實現對訊息的創建、使用、刪除和回收,兩部分綜合起來形成了LwIP的訊息佇列功能。
LwIP中每個和TCP/IP相關的任務的一系列定時事件組成一個
單向鍊表,每個鍊表的起始
指針存在lwip_timeouts 的對應表項中,如圖2所示。移植時需要實現struct sys_timeouts * sys_arch_timeouts (void) 函式,該函式返回正處於運行態的執行緒所對應的timeout 佇列指針。
(4) 創建新執行緒函式
在μC/OS 中,沒有執行緒(thread) 的概念,只有任務(Task) 。它提供了創建新任務的系統API調用OSTaskCreate,因此只要把OSTaskCreate封裝一下,就可以實現sys_thread_new。需要注意的是LwIP中的thread並沒有μC/OS 中優先權的概念,實現時要由用戶事先為LwIP中創建的執行緒分配好優先權。