天天看點

在Windows平台上調試嵌入式TCP/IP協定棧的研究

介紹在Windows平台上使用Visual C++ 6.0開發環境進行嵌入式TCP/IP協定棧的開發和仿真調試手段。詳細講解了如何使用Winpcap接收和發送IP資料封包以及在Windows上配置雙協定棧的一些問題。

【關鍵詞】 嵌入式系統;TCP/IP協定棧;Windows平台;仿真調試;WinPcap;

1 引言

随着Internet的廣泛的應用,在嵌入式裝置中支援TCP/IP協定以連接配接到Internet網絡并與外界通信的需求更加強烈,這就需要在嵌入式系統中支援TCP/IP協定棧。雖然目前的商用嵌入式作業系統,如VxWorks、QNX、pSOS、VRTX等,均提供基于TCP/IP的網絡元件,但為了滿足各個方面的應用需要,其實作過于複雜,需要占用大量的系統資源。而嵌入式系統的本身資源有限,并且其應用和功能比較單一,具有較強的針對性,是以也并不需要一個完整的TCP/IP網絡協定元件,隻需要實作與需求相關的部分協定,不使用的協定則不需要支援。在另一方面,對于某些特定的嵌入式系統,甚至需要優化TCP/IP協定棧或者在TCP/IP協定棧中編寫自己需要的網絡協定。那些不能提供開放源碼的商用嵌入式系統的TCP/IP協定棧都很難滿足使用者的配置需求,需要使用者自行開發和定制适合自己系統需求的嵌入式TCP/IP協定棧。

2 嵌入式協定棧的開發和調試問題

一般的嵌入式系統的開發和調試都是使用其相應的開發調試工具連接配接計算機和目标機進行交叉開發和調試。例如被廣泛使用的VxWorks嵌入式實時作業系統的開發工具Tornado,它就是一套強有力的交叉開發工具,使用者可以在計算機上使用圖形界面對目标機上的應用程式進行調試。

但即便是使用像Tornado這樣優秀的嵌入式開發環境,在交叉調試協定棧此類比較大型的程式時,還是顯得力不從心,其開發調試是件費時費力的工作,大大增加了系統的開發難度和開發調試的周期。在目前的嵌入式系統的調試工具還不盡如人意的現狀下,對嵌入式TCP/IP協定棧的開發如果能前期在Windows平台上進行開發和仿真調試,将是一件很有意義的工作。

嵌入式TCP/IP協定棧雖然是基于嵌入式作業系統,但除了接收和發送資料包以外,幾乎并不直接與底層硬體打交道。是以在Windows平台上仿真調試和運作TCP/IP協定棧是完全可行的,可以完成絕大部分功能的開發與調試,後期再移植到嵌入式系統上,隻需進一步稍加調試和測試便能實作整個嵌入式軟體系統的功能和性能。這樣的開發流程能夠極大的提高開發的效率,減少開發的周期。

3 在Windows平台上運作嵌入式協定棧

在Windows平台上仿真調試和運作TCP/IP協定棧,首先需要在Visual C++ 6.0開發環境中建立一個Win32應用程式的項目工程用于模拟嵌入式系統,嵌入式TCP/IP協定棧就是在這個Win32的應用程式中運作。這樣,我們使用Windows平台下的一個程序模拟了一個多任務的嵌入式作業系統。

一個多任務嵌入式作業系統需要具有任務管理、記憶體管理以及任務間通信機制如信号量、消息隊列等功能。是以,如想在Windows平台上運作嵌入式TCP/IP協定棧,也必須提供上述多任務嵌入式作業系統的基本功能。

在多任務嵌入式作業系統中,任務是系統進行排程的最基本的單元,參與資源競争和CPU資源在任務間的配置設定,系統通過循環的方式為每個任務安排一定的 CPU時間片,而在宏觀上看仿佛是若幹任務并發處理,形成多任務作業系統。而在Winodows這樣的通用作業系統平台上,則是由線程作為參與CPU時間 片資源競争最小實體,是以,我們使用線程模拟嵌入式作業系統中的一個任務。任務的建立、删除和控制等操作通過調用Windows平台中提供的線程的建立、 删除和控制的Win32 API函數來實作。

在多任務作業系統中,任務與任務之間需要協調動作,互相配合,這就需要提供任務間互相通信的機制以進行同步和互斥。嵌入式系統中一般提供信号量、事件和消 息機制這三種主要的任務間通信手段。同樣,在Windows平台上的Win32 API也提供相應的用于程序/線程間通信的信号量、事件和消息機制的函數。

由于Windows是一個強大的通用分時作業系統,能夠提供完善的操 作系統接口。是以,多任務嵌入式作業系統完全可以在Windows平台上模拟。不過,這種模拟也隻是近似的,畢竟對于多數嵌入式系統都是實時系統,而 Windows卻是分時系統,無法保證其系統的實時性。

至于嵌入式TCP/IP協定棧的開發,考慮TCP/IP協定族的複雜性以及其協定棧龐大的代碼量,試圖完全從頭到尾徹底的重新編寫一套TCP/IP協定棧的代碼是極為艱難的,需要大量的人力、物力和時間的投入。其實目前TCP/IP技術已經十分成熟,幾乎所有的通用作業系統都提供TCP/IP協定棧用于網絡支援,包括那些公開源碼的作業系統。是以考慮移植源碼公開的TCP/IP協定棧,同時根據需求對其進行适量的精簡和改進。

目前,比較常見的源碼公開的TCP/IP協定棧軟體有:

1). BSD Net網絡協定棧軟體。這是由加利福利亞大學伯克利分校計算機系統研究小組釋出的,世界上第一個被廣泛應用TCP/IP軟體版本就是伯克利于1983年釋出的4.2BSD,有許多系統的TCP/IP協定棧實作都是以它的源代碼為基礎而開發的。目前其最新版本是1994年釋出的4.4BSD-Lite2,又稱為Net/3。

2). Linux的TCP/IP協定棧軟體。作為一個遵循GUN公共許可協定,源碼全部公開的自由作業系統軟體,其TCP/IP協定棧部分源碼是以BSD的網絡協定棧為模型,支援BSD的Socket接口,但其内部代碼是重新寫的,與4.4BSD-Lite2并不雷同。

3). lwIP是一個比較小型的源碼開放的TCP/IP協定棧軟體,是由瑞典計算機科學研究院的Adam Dunkels教授編寫。它隻需要10K的RAM空間和40K的ROM存儲空間,是以非常适合嵌入式系統裡使用。

4). uIP則是一個超小型的TCP/IP協定棧,僅能提供ARP、SLIP、TCP、ICMP和IP這幾種基本的協定。其所需資源非常的少,是以非常适合在8位和16位單片機上運作。

對于TCP/IP協定棧的選擇主要根據使用者本身的需求和所能提供的軟硬體資源來确定。比如像BSD和Linux的TCP/IP協定棧屬于通用的協定棧,支援協定比較齊全,但也需要耗用大量的ROM和RAM存儲空間,對CPU的要求也比較高;而lwIP和uIP這類的協定棧是專門為嵌入式作業系統開發出來的,軟體結構比較緊湊,對CPU和存儲器需求不高,但其所支援的協定種類及功能也非常有限。

4 WinPcap工具包介紹

在Windows平台上仿真調試和運作TCP/IP協定棧,還需要考慮協定棧如何接收和發送資料封包的問題,這就需要使用WinPcap來實作。

WinPcap(Windows Packet Capture)是Windows平台下一個公共的、免費的網絡通路系統,能為Win32應用程式提供網絡通路的能力。它提供以下四項主要功能:

1) 捕獲原始資料封包,包括共享網絡上各主機發送/接收和互相交換的資料包;

2) 在資料封包發送往應用程式之前,按照自定義的規則将某些特定的資料包過濾掉;

3) 在網絡上發送原始的資料封包;

4) 收集網絡通信過程中的統計資訊;

WinPcap的主要功能在于獨立于主機協定而發送和接收原始資料封包,能夠監聽共享網絡上傳送的資料包。是以,通過調用它提供的各種函數,可以實作在 Windows平台下将各類資料封包通過網絡擴充卡發送到共享網絡上去,同樣也可以接收網絡擴充卡上收到的各種原始的資料包。

要使用WinPcap,首先需要在Windows平台上安裝WinPcap驅動軟體,然後便可以在Win32的應用程式中通過包含packet32.h這 個頭檔案來使用由WinPcap的動态連結庫packet32.dll或者靜态連結庫packet32.lib所提供的庫函數來對網絡擴充卡進行打開、設 置、關閉操作和通過網絡擴充卡進行接收或者發送資料封包。

下面簡要介紹一下其主要函數的功能:

1) BOOLEAN PacketGetAdapterNames(LPSTR pStr,PULONG BufferSize) 傳回可以得到的網絡擴充卡清單及描述。

2) LPADAPTER PacketOpetAdapter(LPTSTR AdapterName) 打開一個網絡擴充卡。

3) BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim) 設定捕獲資料報的核心級緩沖區大小。

4) BOOLEAN PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter) 為接收到的資料報設定硬體過濾規則。一般而言,需要将其設定為 NDIS_PACKET_TYPE_PROMISCUOUS(混雜模式),即接收所有流過的資料封包。

5) LPPACKET PacketAllocatePacket(void) 如果運作成功,傳回一個_PACKET結構的指針,否則傳回NULL。成功傳回的結果将會傳送到PacketReceivePacket()函數,接收來自驅動的網絡資料報。

6) VOID PacketInitPacket(LPPACKET lpPacket, PVOID Buffer, UINT Length) 初始化一個_PACKET結構。

7) BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET lpPacket, BOOLEAN Sync) 發送一個或多個資料報的副本。

8) BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync) 從NPF驅動程式讀取網絡資料報及統計資訊。

9) VOID PacketFreePacket(LPPACKET lpPacket) 釋放參數提供的_PACKET結構。

10) VOID PacketCloseAdapter(LPADAPTER lpAdapter) 關閉參數中提供的網絡擴充卡,釋放相關的ADAPTER結構。

5 在Windows平台下協定棧發送和接收函數的設計

在Windows平台下通過WinPcap可以直接對網絡擴充卡進行操作,進而實作發送和接收資料封包的目的。在使用WinpCap前首先需要進行初始化 操作,其步驟如下:調用PacketGetAdapterNames()擷取目前網絡擴充卡的名稱,再調用PacketOpenAdapter()函數打 開一個網絡擴充卡,然後還需要調用PacketSetHwFilter()函數設定網絡擴充卡的過濾規則和調用PacketSetBuff()設定捕獲數 據報的核心級緩沖區大小。

當協定棧需要發送資料封包時,首先需要調用PacketAllocatePacket()函數為發送資料封包建立一個網絡資料報結構,然後調用 PacketInitPacket()函數對該結構進行初始化,将存儲待發送資料封包的緩沖區指針和長度填入網絡資料報結構,再接下來便是調用 PacketSendPacket()函數将資料封包從指定的網絡擴充卡中發送出去,之後需要調用PacketFreePacket()函數釋放掉剛才申 請的網絡資料封包結構的記憶體空間。這樣,一個TCP/IP協定棧就能夠完成将一個資料封包通過WinPcap操作網絡擴充卡發送到網絡上的工作。

在Windows平台上調試嵌入式TCP/IP協定棧的研究
在Windows平台上調試嵌入式TCP/IP協定棧的研究

使用WinPcap接收網絡擴充卡上收集到的網絡上的資料封包,首先需要建立一個高優先級别的任務或者線程,一般在TCP/IP協 議棧的網絡接口層初始化時即需要建立一個這樣的任務或者線程,然後在該任務或者線程函數裡調用PacketAllocatePacket()為接收資料報 文建立網絡資料報結構,再調用PacketInitPacket()函數為接收的資料封包配置設定記憶體緩沖區,這個緩沖區需要盡量大一點兒,否則一旦網絡上數 據封包比較多,而協定棧上層來不及處理,則會造成資料封包的丢失。接下來便是循環的調用PacketReceivePacket()函數從指定的網絡适配 器讀取資料封包,并将資料封包拷貝到協定棧的記憶體空間,再通過作業系統提供的任務或線程間通信的機制将該資料封包發送到TCP/IP協定棧的接收任務或者線程進行封包的分析和處理。這個資料接收的任務和線程将永遠不會傳回,始終循環調用PacketReceivePacket()函數讀取網絡擴充卡上接收到的網絡上傳輸過來的資料封包并将其傳遞給TCP/IP協定棧進行處理。

6 在Windows平台上配置雙協定棧的問題

由于Windows平台本身自帶有TCP/IP協定棧,而我們又需要在Windows平台上運作一個嵌入式TCP/IP協定棧,實際上是在Windows這一個作業系統上配置了雙TCP/IP協定棧。

要使這兩個TCP/IP協定棧互相之間互不影響并能各自良好的運作,首先需要為兩個協定棧各自配置設定不同的IP位址;其次在嵌入式TCP/IP協定棧中的資料鍊路層的Mac位址,一定不能使用Windows平台的TCP/IP協定棧使用的網絡擴充卡的位址,除非計算機裝有兩塊網絡擴充卡,Windows平台的TCP/IP協定棧使用一個網絡擴充卡進行資料的收發,而嵌入式TCP/IP協定棧使用另一個網網絡擴充卡收發資料封包。其實在嵌入式TCP/IP協 議棧中,其鍊路層的Mac位址可以通過修改程式代碼設定任意的虛拟Mac位址,但這必須首先調用WinPcap的PacketSetHwFilter() 函數設定網絡擴充卡的接收模式為NDIS_PACKET_TYPE_PROMISCUOUS(混雜模式)用于指定網羅擴充卡接收所有流過的資料封包,否 則,網絡擴充卡會根據本身的Mac位址對網絡上接收到的資料封包進行Mac過濾,丢棄掉不屬于該網絡擴充卡接收的資料封包。

7 小結

作者在工作中按照上述方法,成功的在Windows平台上運作并調試了Linux的TCP/IP協定棧,并最終将其移植到VxWorks作業系統中運作。在調試過程中,作者明顯感覺Windows的VC6開發平台下調試确實比直接使用Tornado調試要友善和快捷許多。由于前期在Windows平台上調試時解決了大部分移植和修改TCP/IP協定棧的問題,後期在Tornado下調試時基本上沒有花費太多的時間,大大提高了工作的效率,減小了開發的周期。

繼續閱讀