找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 5782|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

嵌入式TCP/IP協(xié)議棧框架之我見(jiàn)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:82781 發(fā)表于 2015-6-13 00:51 | 只看該作者 回帖獎(jiǎng)勵(lì) |正序?yàn)g覽 |閱讀模式

最近在移植新網(wǎng)卡驅(qū)動(dòng)的時(shí)候?qū)W習(xí)了下TCP/IP的協(xié)議棧的框架模型做一個(gè)總結(jié)
1、硬件相關(guān):硬件使用Emac+DMA
2、軟件相關(guān):任意一款RTOS/內(nèi)核+IPC+TCPIP協(xié)議棧

測(cè)試環(huán)境搭建:使用一臺(tái)PCIP地址為192.168.1.5,板子IP地址搞成192.168.1.60,路由器為192.168.1.1在一個(gè)子網(wǎng)下進(jìn)行通信。使用wireshark 抓包,PC ide JATG接口進(jìn)行 DEBUG。追蹤一個(gè)UDP報(bào)文的輸入,以此窺見(jiàn)整體的軟件框架架構(gòu)。

構(gòu)造數(shù)據(jù)發(fā)送接收流程:PC->網(wǎng)卡到路由器->路由器轉(zhuǎn)發(fā)之->板子接收。
數(shù)據(jù)如下:



首先是中斷,以太網(wǎng)最最底層的物理層中斷,提示以太網(wǎng)接收到數(shù)據(jù)包,這時(shí)候數(shù)據(jù)報(bào)文是最完整的一幀如下:

所上面所謂的Frame就是這一層接收到的,從上面可見(jiàn)TCP/IP是嚴(yán)格的分層處理的, 下面也會(huì)從代碼上看出來(lái),確實(shí)是分層的。這一層接收到的數(shù)據(jù)是RAW數(shù)據(jù),這完全取決于驅(qū)動(dòng)層是否穩(wěn)定可靠,有很多人在這里就栽跟頭,最后搞的什么PING 不通啦,死機(jī)啦等等我也栽跟頭了,最近的就是ARP廣播的問(wèn)題。所以驅(qū)動(dòng)層是整個(gè)協(xié)議棧的的基石。最好建議使用大神寫的代碼或者固件庫(kù)來(lái)弄,自己那兩下子,就別比比了。OK只要你能正確的接收網(wǎng)絡(luò)上的包這一層就OK,
下面是流程:

一、網(wǎng)絡(luò)接口層的處理

start A :
{
1、以太網(wǎng)中斷,證明有數(shù)據(jù)包到來(lái),這時(shí)候第一件事是讀取數(shù)據(jù)包,由于有操作系統(tǒng)支撐,那好建立一個(gè)RX線程來(lái)處理這個(gè)事件。

以太網(wǎng)的中斷處理
{
ETH_IRQHandler
1、post a RXmbox to RX thread
}

接收線程
{
1、掛起到 RXmbox 上(if 沒(méi)有郵箱到來(lái)--死等)
2、調(diào)用物理層讀取報(bào)文到pbuf中,這里注意pbuf是從內(nèi)存中動(dòng)態(tài)開(kāi)辟出來(lái)的。還有一點(diǎn)就是收發(fā)是倆線程記得加互斥鎖哦。返回指針P
這個(gè)指針P承載著所有的收進(jìn)來(lái)的數(shù)據(jù),完全copy到內(nèi)存中了,長(zhǎng)度就是數(shù)據(jù)包的長(zhǎng)度。也就是系統(tǒng)給分配內(nèi)存了。這個(gè)數(shù)據(jù)包開(kāi)始在系統(tǒng)中生存。這很重要,標(biāo)志這這就是一頭豬要?dú)⒌舫匀饬。光有指針不夠,必須有個(gè)結(jié)構(gòu)來(lái)記錄,所以就是pbuf來(lái)記錄進(jìn)來(lái)的包。
3、交給TCPIP協(xié)議棧的物理層進(jìn)行處理。物理層其實(shí)做的活很簡(jiǎn)單:



}
物理層就是判斷是什么類型的包,是ARP的話交給ARP處理,是IP的話交給IP層處理,什么也不是就釋放掉Pbuf記錄的包,UDP數(shù)據(jù)是IP的類型,所以執(zhí)行


:更新ARP表的。
這個(gè)是去除MAC地址的,也就是
這一層里面描述的,其實(shí)也不是去掉,只是指針向后移動(dòng)了避開(kāi)了這些字段,也就是所謂的指針。修改了長(zhǎng)度字段等,這樣上層就可以只處理上面的了。
這個(gè)才是最終的數(shù)據(jù)包去向哦。!那么他去哪里了呢?繼續(xù)

顯然他來(lái)到了一個(gè)邊界,線程的邊界,可以看出他分配了一個(gè)類型的消息,然后用加載了PBUF的所有數(shù)據(jù)(哪有數(shù)據(jù)啊,其實(shí)就是指向那個(gè)BUF的指針而已,說(shuō)白了他傳遞的就僅僅是是指針而已,通過(guò)指針的索引可以找到所有的數(shù)據(jù))最后用投遞了出去。

這就是接收線程的最后了,他做完這些就又回到原來(lái)的郵箱等待了。等待下一個(gè)數(shù)據(jù)的到來(lái),然后做重復(fù)的動(dòng)作,就是這樣。
他承擔(dān)了底層數(shù)據(jù)的讀取,和簡(jiǎn)單的封裝分揀,然后投遞到郵箱中通知TCPIP的主線程準(zhǔn)備工作。
}
end A

二:TCPIP線程的處理
start B:
是時(shí)候進(jìn)入TCPIP主線程了,所有的調(diào)度都在這里進(jìn)行。他的工作室這樣的
首先是掛起到這里,因?yàn)锳段說(shuō)到已經(jīng)post了一個(gè)郵箱,所以這里立馬激活運(yùn)行,鄉(xiāng)下
這個(gè)類型一定是所以
執(zhí)行到這里

從上面可見(jiàn)TCPIP線程取出來(lái)了先前加入的原始數(shù)據(jù)報(bào)文的指針P和網(wǎng)絡(luò)接口的記錄。這個(gè)netif不用理會(huì),想想為網(wǎng)卡的一種抽象即可.關(guān)鍵是P指針。
輸入進(jìn),最后釋放掉了這則消息。因?yàn)橐呀?jīng)用完了,這里中斷是進(jìn)入了網(wǎng)絡(luò)層了。也就是IP層
就是這一層哦。
這里面各種檢測(cè)判斷,各種的檢查啊,主要是第一檢測(cè)這個(gè)IP報(bào)文的IP地址是不是給我們,是就傳給山層,不是就轉(zhuǎn)發(fā),還有一些校驗(yàn)和的判斷也在這里進(jìn)行。還有一點(diǎn)在這里執(zhí)行的是釋放了一部分pbuf,節(jié)省了內(nèi)存,這個(gè)不是和上次單純移動(dòng)指針,而是真的去除用不到的buf,只保留IP和以上層的數(shù)據(jù)。
這個(gè)里面處理多了去了,DHCP.ICMP,IGMP,RAW,一堆的最終歸宿一定是這個(gè)輸入的是個(gè)UDP包。所以就是繼續(xù)向下
哎呀我去,這個(gè)里面又來(lái)了,各種的判斷,各種的異常處理,各種的檢測(cè),不過(guò)簡(jiǎn)而言之就是一句話只要不是我的我不要,是我的當(dāng)然我還要看看校驗(yàn)和對(duì)不對(duì),對(duì)那好,又會(huì)來(lái)了一個(gè)最終的歸宿這里
這個(gè)是什么?顯然像個(gè)函數(shù),實(shí)際上是個(gè)指針函數(shù),他指向哪里了?。。。。。 旺旺~~~冒金星了。不知道他指向哪里了,
實(shí)際上這些指針也好結(jié)構(gòu)也罷,你要知道他去哪里就要找到他的源頭,他的源頭句柄是PCB,那么PCB在哪里?PCB和SOCKET有什么聯(lián)系肯定有聯(lián)系,然后轉(zhuǎn)而去找pcb的建立,從socket開(kāi)始找最后找到一個(gè)這個(gè)玩意
,
然后在向里面就是這下找到啦
最終

這個(gè)函數(shù)就是上面的下一步哦,goon ....
在這里面又會(huì)分配
這個(gè)玩意出來(lái),

對(duì)他進(jìn)行了這些操作,
啊,原來(lái)他是來(lái)描述接收到的這個(gè)UDP數(shù)據(jù)包的呀。看下面?zhèn)鬟f上來(lái)的指針P又被賦給了他,莊戶人拉呱:倒三把了。
在向下就是這一端的終點(diǎn)了哦

這個(gè)就是TCPIP和應(yīng)用層的交互郵箱,著名的郵箱了,據(jù)說(shuō)很多大神對(duì)此都很有研究。我這菜比也見(jiàn)了見(jiàn),不錯(cuò)不錯(cuò)。
這只是見(jiàn)了見(jiàn),你知道他在哪里?于是乎還得找,他在這里


這個(gè)郵箱實(shí)在conn初始化的時(shí)候被創(chuàng)建了,圍繞著這個(gè)郵箱的size,我認(rèn)為郵箱尺寸要盡量的大一點(diǎn)才好呢。


end B
三、應(yīng)用層處理
start C
至于應(yīng)用線程,直接說(shuō)他是掛起在這個(gè)郵箱上的,他會(huì)做自動(dòng)的數(shù)據(jù)COPY,把UDP描述記錄中的內(nèi)容自動(dòng)復(fù)制你提供的內(nèi)存中,然后結(jié)束PBUF的使命,殺掉他。釋放內(nèi)存,然后你從你指定的那塊緩存中取出數(shù)據(jù)就可以完成一個(gè)UDP數(shù)據(jù)包的接收,就這么簡(jiǎn)單,這就是事實(shí),事實(shí)就是這樣!


接收到32字節(jié)的數(shù)據(jù),處理吧!。。。。。。。。。。。。。。。。。。。!#¥!@#%¥%¥……
end C



發(fā)送是主動(dòng)的會(huì)簡(jiǎn)單一些,和接收互逆,只是添加構(gòu)建一些頭,主要還是接收這一塊,通過(guò)分析可見(jiàn),TCPIP協(xié)議棧對(duì)接收到的數(shù)據(jù)報(bào)文進(jìn)行層層的剝皮,檢查,就像剝一個(gè)雞蛋一樣,一層層的去掉,最后取出蛋黃放在口里。那個(gè)recv就是回調(diào)。其他的mbox和recvbox是承上啟下的。
TCP的要復(fù)雜一些,不過(guò)根本框架是一樣的哦。
ICMP報(bào)文,到不了這里到IP層就會(huì)被自動(dòng)轉(zhuǎn)發(fā)出去了,
ARP層直接到不了IP層在早就轉(zhuǎn)發(fā)走了。

TCPIP協(xié)議棧傳遞的就是一個(gè)pbuf指針,直到應(yīng)用程序copy完畢數(shù)據(jù),當(dāng)然其他的異常什么的除外了。
對(duì)TCPIP協(xié)議的我們可以用到其他的一些通信中,主要是學(xué)習(xí)他的這種框架,和機(jī)制。是程序就有BUG,只能說(shuō)是水太深,我太菜,沒(méi)有什么了!
最后向作者致敬,不禁感嘆:大神!

老王
日照比特



分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表