劉波濤
(長江大學 計算機科學學院,湖北 荊州 434023)
當前,物聯(lián)網(wǎng)技術正受到研究者的廣泛關注[1],而在物聯(lián)網(wǎng)技術中的一個關鍵問題[2-4],就是要實現(xiàn)嵌入式設備聯(lián)入Internet.嵌入式設備接入Internet的方法很多,其中一種方法[5-8]就是在嵌入式設備中實現(xiàn)裁剪后的TCP/IP協(xié)議棧.通用計算機系統(tǒng)有足夠的資源支持系統(tǒng)在內(nèi)核中實現(xiàn)復雜的標準TCP/IP協(xié)議棧,而這對只有有限資源的嵌入式系統(tǒng)來說,既不可能也沒有必要.因此,針對嵌入式系統(tǒng)的特點,把握嵌入式TCP/IP協(xié)議棧設計的技巧就顯得尤為重要.
在理解嵌入式TCP/IP協(xié)議棧設計技巧前,需了解嵌入式系統(tǒng)的特點,特別是其資源較少的特點.
嵌入式系統(tǒng)與通用計算機系統(tǒng)的本質(zhì)區(qū)別在于系統(tǒng)應用的不同,嵌入式系統(tǒng)是將計算機系統(tǒng)嵌入到對象系統(tǒng)中.因此,嵌入式系統(tǒng)與通用計算機系統(tǒng)相比,主要具有以下特點[9]:第一,嵌入式系統(tǒng)是面向特定應用的系統(tǒng).嵌入式系統(tǒng)與通用型系統(tǒng)的最大區(qū)別就在于嵌入式系統(tǒng)大多為特定用戶群設計的系統(tǒng),因此它通常都具備低功耗、體積小、集成度高等特點,并且可以滿足不同應用的特定需求;第二,嵌入式系統(tǒng)的硬件和軟件都必須進行高效地設計,量體裁衣、去除冗余,這樣才能更具競爭力;第三,為了提高執(zhí)行速度和系統(tǒng)可靠性,嵌入式系統(tǒng)中的軟件一般都固化在Flash或ROM中,而不是存儲在磁盤中;第四,嵌入式系統(tǒng)本身不具備二次開發(fā)能力,即設計完成后用戶通常不能對其中的程序功能進行修改,必須有一套開發(fā)工具和環(huán)境進行再次開發(fā).
正因為嵌入式系統(tǒng)不像通用計算機那樣有豐富的系統(tǒng)資源,因此必須針對嵌入式系統(tǒng)的特點,來設計協(xié)議棧的實現(xiàn)技巧,否則協(xié)議棧實現(xiàn)的再好,但由于缺乏嵌入式系統(tǒng)的支持,也將是徒勞無功.
TCP/IP協(xié)議棧的工作過程如圖1所示.數(shù)據(jù)以一定的單位(通稱為數(shù)據(jù)包)在發(fā)送端一方由應用進程交給協(xié)議棧,數(shù)據(jù)包在協(xié)議棧從上層至下層被依次封裝,即將上層的整個數(shù)據(jù)包作為下層的數(shù)據(jù)部分,再添加下層的首部,而作為新的數(shù)據(jù)包;在接收端,數(shù)據(jù)包則經(jīng)由協(xié)議棧從下層至上層被依次解包:即將下層的首部剝?nèi)?,并根?jù)其內(nèi)容將數(shù)據(jù)部分交付上層的協(xié)議處理,最后應用層的數(shù)據(jù)交由應用進程處理[10].
圖1 TCP/IP協(xié)議棧的工作過程
為了保證協(xié)議棧中層與層之間的封裝性,一般TCP/IP的實現(xiàn)過程中多采用層層拷貝的原則.也就是說,在封包時,將上層協(xié)議的數(shù)據(jù)包從上層協(xié)議拷貝到下層協(xié)議的數(shù)據(jù)空間中;而在解包時,將數(shù)據(jù)包從下層協(xié)議拷貝到上層協(xié)議的數(shù)據(jù)空間中.而對應于嵌入式系統(tǒng),特別是資源極其有限的單片機系統(tǒng)及SOC片上的系統(tǒng),如果在封包或解包時按上述方法來拷貝數(shù)據(jù),則需要很多的緩沖區(qū)并且耗費大量嵌入式CPU拷貝時間.顯然,這是不明智的.
因此,筆者設計的數(shù)據(jù)包封裝及解封裝采用了如下方法:在層與層之間交換信息時,以數(shù)據(jù)緩沖區(qū)首指針作為函數(shù)參數(shù)進行傳遞;在封裝時,上層協(xié)議在分配空間時充分考慮以后下層協(xié)議的封裝,并在緩沖區(qū)首部多分配一些必要的空間,便于下層協(xié)議在不需要從上層拷貝的情況下直接填充該層的首部.例如,HTTP協(xié)議在分配數(shù)據(jù)空間時多分配54字節(jié)用于隨后的TCP、IP和Ethernet協(xié)議首部的填充;在解封裝時,也將收到的原始數(shù)據(jù)包首地址直接傳給向上層協(xié)議,便于上層協(xié)議獲取下層協(xié)議的一些必要信息.如讓TCP層知道數(shù)據(jù)包的源IP地址,以便于填充TCP傳輸控制塊的目的IP地址字段.因此,這種方式不僅節(jié)約了系統(tǒng)的資源,而且會因為不需要拷貝數(shù)據(jù)包而提高了系統(tǒng)的處理速度.
不管是零拷貝還是層層拷貝,都需要分配一定的內(nèi)存來支持實現(xiàn).嵌入式系統(tǒng)不像通用計算機那樣,內(nèi)存資源豐富,一般內(nèi)存較少,因此更應該“精打細算”.考慮到Internet網(wǎng)絡中接收和發(fā)送的數(shù)據(jù)包大小不一,即收到的和發(fā)送的數(shù)據(jù)包長度都不是一個定值,例如以太網(wǎng)數(shù)據(jù)包的長度范圍值是64至1518字節(jié),因此對內(nèi)存的分配應該采用動態(tài)的方式進行管理.有如下兩種方案可供選擇:方案一,是每次分配一個固定長度的緩存.讓該緩存能夠容納一個最大的數(shù)據(jù)包,且在該緩存中設置一個字段用來存儲其有效數(shù)據(jù)的長度,顯然這種方案實現(xiàn)簡單,但是浪費了寶貴內(nèi)存資源;方案二,是按需分配合適大小的緩存,而不管該緩存是用于底層接收數(shù)據(jù)還是用于上層發(fā)送數(shù)據(jù),這種方案節(jié)約了內(nèi)存資源.因此,筆者建議采用方案二來實現(xiàn)數(shù)據(jù)包緩存的動態(tài)分配.
需要注意的是,動態(tài)管理內(nèi)存就肯定會面臨“內(nèi)存泄露”的風險,它最終會將系統(tǒng)的可用內(nèi)存耗盡,最終會使嵌入式設備崩潰、停止運行.為避免這個風險的出現(xiàn),嵌入式TCP/IP協(xié)議棧實現(xiàn)過程中,應該遵從“誰分配誰釋放”的原則來進行內(nèi)存的動態(tài)管理.例如,HTTP有數(shù)據(jù)包需要發(fā)送,那么在它依次調(diào)用完TCP發(fā)送模塊函數(shù)、IP發(fā)送模塊函數(shù)、驅(qū)動發(fā)送函數(shù)后,應該釋放它申請的動態(tài)內(nèi)存.
因為TCP/IP協(xié)議棧本身就是一個分層的軟件系統(tǒng),故應該按協(xié)議將協(xié)議棧實現(xiàn)分為若干個模塊文件,讓每個模塊實現(xiàn)一層每一個協(xié)議的功能,如圖2所示.在圖2中,在頭文件(*.H)中定義了該模塊對外的接口變量及函數(shù)接口聲明,而在源文件(*.C)中則定義了相關的變量和函數(shù).要引用某模塊的變量或調(diào)用其中的函數(shù)時,只需包含此模塊的頭文件即可.這樣設計之后,分工明確,程序清晰,可讀性好,便于程序的維護及修改.
圖2 協(xié)議棧實現(xiàn)的文件目錄
圖3 嵌入式TCP/IP軟件構(gòu)成層次圖
嵌入式處理器多種多樣,嵌入式設備類型豐富,廠家眾多,因此,在進行嵌入式軟件的設計過程中應該充分考慮這一點,實現(xiàn)盡可能的方便移植.為了使嵌入式TCP/IP協(xié)議棧具備良好的可移植性,以便適應多種目標平臺,可將實現(xiàn)分為硬件無關層和硬件依賴層,如圖3所示.在圖3中,硬件無關層的實現(xiàn)使用高級語言完成,例如C語言,以方便將硬件無關層相關代碼移植到所有其他能夠編譯C代碼的硬件平臺上;在硬件依賴層中使用特殊機制,例如C語言中的#define宏定義來重新定義數(shù)據(jù)類型,這樣就可根據(jù)移植環(huán)境的變化來重新定義數(shù)據(jù)類型,以盡量消除系統(tǒng)對于具體編譯器的依賴;依賴層和無關層間采用統(tǒng)一的接口交互信息,當硬件平臺改變時,只需改動硬件依賴層的各驅(qū)動程序?qū)崿F(xiàn),在其接口函數(shù)名稱與參數(shù)不變的情況下,硬件無關層無需改變,從而屏蔽了硬件實現(xiàn)的差異.
由于嵌入式的系統(tǒng)運行速度和內(nèi)存容量有限,在設計時還應遵循下列原則:盡量避免使用全局變量或外部變量,全局變量或外部變量在整個程序運行期間都要占用內(nèi)存,所以要盡量少用全局變量或外部變量,而盡量多地用局部變量.因此,建議采用函數(shù)參數(shù)傳遞的方式來共享信息;占用內(nèi)存較多的變量應該定義在外部RAM中.因嵌入式處理器的內(nèi)部RAM可用存儲空間非常有限,占用過多的內(nèi)部RAM會使嵌入式處理的硬件堆棧溢出,從而導致函數(shù)調(diào)用失敗.如實現(xiàn)嵌入式TCP/IP協(xié)議棧中的TCP傳輸控制塊數(shù)組較大,就應當定義在外部RAM中.
圖4 測試內(nèi)存泄露時輸出的信息
圖5 客戶端動態(tài)獲取服務傳感器溫度
遵循前述設計思路,筆者在單片機W78E58B上實現(xiàn)了一個嵌入式TCP/IP協(xié)議棧[5],并在此基礎上實現(xiàn)了一個嵌入式Web服務器.采用的測試方法是將該此嵌入式Web服務器與PC機在RJ-45口及串口分別對接.將嵌入式Web服務的調(diào)試信息從串口輸出,并由串口精靈顯示[11].圖4顯示的是對其進行內(nèi)存泄露的測試.筆者對系統(tǒng)的內(nèi)存塊進行相關記錄和統(tǒng)計:Len字段記錄是本次分配的內(nèi)存長度,UsedMemLen字段記錄的是所用內(nèi)存總長度,F(xiàn)reeMemLen字段記錄的是空閑內(nèi)存的長度;每一條信息表明了某個內(nèi)存塊分配或釋放所在函數(shù)名及所處時刻.如由圖4可知,每條信息對應的UsedMemLen與FreeMemLen之和是一個定值,也就是說,筆者遵照這一思路設計的嵌入式Web服務器不存在內(nèi)存泄露的風險.
對嵌入式Web服務器進行相關功能測試,如圖5所示.由圖可知,嵌入式Web服務器能完成數(shù)據(jù)的下載及上傳功能,遵照這一思路設計的嵌入式TCP/IP協(xié)議棧運行穩(wěn)定可靠.
本文總結(jié)了在實現(xiàn)嵌入式TCP/IP協(xié)議棧的過程中,應該注意的設計技巧.并做了相關測試,驗證了該技巧的可行性.這為嵌入式設備中順利實現(xiàn)嵌入式TCP/IP協(xié)議棧,從而實現(xiàn)物聯(lián)網(wǎng)技術打下了堅實的基礎.
[1]劉書艷.十年后,物聯(lián)網(wǎng)風行[N].中華工商時報,2010-3-5(7).
[2]International Telecommunication Union UIT.ITU Internet Reports 2005:The Internet of Things[R].2005.
[3]王保云.物聯(lián)網(wǎng)技術研究綜述[J].電子測量與儀器學報,2009,23(12):1-7.
[4]AMARDEO C,SARMA,J G.Identities in the Future Internet of Things[J].Wireless Pers Commun 2009,49:353-363.
[5]馮翠麗,劉波濤.一種嵌入式TCP/IP協(xié)議棧的設計與實現(xiàn)[J].長江大學學報,2008,5(4):331-333.
[6]陳立家,焦戰(zhàn)立,熊文龍.基于精簡TCP/IP協(xié)議棧網(wǎng)絡服務器的實現(xiàn)[J].武漢理工大學學報,2007,31(3):565-568.
[7]任會平,王平,徐櫞.低成本嵌入式web服務器的研究[J].微計算機信息,2008,24(10):23-25.
[8]陳立家,焦戰(zhàn)立,熊文龍.基于精簡TCP/IP協(xié)議棧網(wǎng)絡服務器的實現(xiàn)[J].武漢理工大學學報,2007,31(3):565-568.
[9]牛茹.基于嵌入式系統(tǒng)的農(nóng)業(yè)數(shù)據(jù)采集傳輸關鍵技術研究[D].咸陽:西北農(nóng)林科技大學,2008.
[10]劉波濤,賈菡,馮翠麗,等.嵌入式Web服務器中TCP/IP協(xié)議棧的裁剪設計[J].西安通訊學院學報,2008,7(4):28-30.
[11]劉波濤,馮翠麗,王青海,等.應用RTL8019AS的嵌入式Web服務器硬件實現(xiàn)[J].長江大學學報,2008,5(1):75-78.