資源描述:
《linux內(nèi)核協(xié)議棧源碼解析,pdf》由會員上傳分享,免費在線閱讀,更多相關(guān)內(nèi)容在教育資源-天天文庫。
1、linux內(nèi)核協(xié)議棧源碼解析,pdf篇一:Linux網(wǎng)絡(luò)協(xié)議棧筆記轉(zhuǎn)】Linux內(nèi)核網(wǎng)絡(luò)協(xié)議棧筆記1:協(xié)議棧分層/層次結(jié)構(gòu)大家都知道TCP/IP協(xié)議棧現(xiàn)在是世界上最流行的網(wǎng)絡(luò)協(xié)議棧,恐怕它的普及的最重要的原因就是其清晰的層次結(jié)構(gòu)以及清晰定義的原語和接口。不僅使得上層應(yīng)用開發(fā)者可以無需關(guān)心下層架構(gòu)或者內(nèi)部機制,從而相對透明的操作網(wǎng)絡(luò)。這個明顯的層次結(jié)構(gòu)也可以在Linux內(nèi)核的網(wǎng)絡(luò)協(xié)議棧中觀察到。主要的參考文獻(xiàn)是:Linux網(wǎng)絡(luò)棧剖析(中文版)/AnatomyofLinuxnetworkingstack(英文原版)byTimJones.以及:Linux內(nèi)核
2、2.4.x的網(wǎng)絡(luò)接口結(jié)構(gòu)18另外一些參考資料可以從這個頁面找到:/retype/zoom/c79c028a6529647d2728529d?pn=1&x=0&y=42&raww=893&rawh=327&o=png_6_0_0_0_0_0_0_892.979_1262.879&type=pic&aimh=175.76707726763718&md5sum=d4c2cc1604113d810c4be146738659bc&sign=edef1c02be&zoom=&png=0-7260&jpg=0-0”target=“_blank”>點此查看。屬于網(wǎng)絡(luò)協(xié)
3、議棧最核心的部分,文件位于內(nèi)核/net/core文件夾下,所以又叫網(wǎng)絡(luò)核心層。其中包括了核心的數(shù)據(jù)結(jié)構(gòu)skbuff文件中的sk_buff/dev.c文件中net_device,這些數(shù)據(jù)結(jié)構(gòu)將在下篇文章中介紹)設(shè)備驅(qū)動程序(在/driver/net文件夾內(nèi))不像OSI或者TCP/IP協(xié)議棧,事實上并沒有一個命名標(biāo)準(zhǔn),因此在這里,這些層次的名稱并不是通用的,但是其語義是清晰的,而且在大多數(shù)其他的文章里只是個別字上的差別。分層詳細(xì)介紹可以參考Jones的文章。我們這里所說的初始化過程指的是從硬件加電啟動,到可以從網(wǎng)絡(luò)接收或發(fā)送數(shù)據(jù)包之前的過程。在Linux系
4、統(tǒng)中,網(wǎng)卡擁有雙重身份:structpci_dev和structnet_device。pci_dev對象代表通用硬件的性質(zhì),是作為一個標(biāo)準(zhǔn)的PCI的設(shè)備插入了PCI的卡槽,由驅(qū)動程序進行管理;另一方面,net_device對象代表網(wǎng)絡(luò)傳輸?shù)男再|(zhì),與內(nèi)核的網(wǎng)絡(luò)協(xié)議棧交互,進行數(shù)據(jù)傳輸。因此我們也必須通過兩個方面來進行初始化,但是后者是我們的重點。而且我們并不關(guān)心內(nèi)核與硬件的交互細(xì)節(jié),例如寄存器讀寫與I/O映射等。18內(nèi)核在初始化時,也會初始化一些與網(wǎng)絡(luò)相關(guān)的數(shù)據(jù)結(jié)構(gòu);而且對應(yīng)我們前面的日志所提及的內(nèi)核網(wǎng)絡(luò)協(xié)議棧層次結(jié)構(gòu)(點這里),內(nèi)核也需要一定的初始化工
5、作來建立這種層次結(jié)構(gòu)。筆者認(rèn)為初始化最重要的就是重要數(shù)據(jù)結(jié)構(gòu)(通常用粗體標(biāo)注)。因此也希望讀者能夠記住重要的數(shù)據(jù)結(jié)構(gòu)的作用。下面我們將分層,自底向上的分析整個初始化過程:(一)驅(qū)動程序?qū)颖疚闹幸砸粋€realtek8139系列網(wǎng)卡作為例子,因為其驅(qū)動只有一個c文件(/drivers/net/8139too.c),比較容易分析。讀者也可以參考e1000網(wǎng)卡的另一篇文章(點這里)。內(nèi)核版本基于2.6.11。驅(qū)動程序加載/注冊主要包括以下的步驟:(a)將設(shè)備驅(qū)動程序(pci_driver)添加到內(nèi)核驅(qū)動程序鏈表中;(b)調(diào)用每個驅(qū)動中的probe函數(shù)(其中重要
6、一步就是初始化net_device對象)。下面進行詳細(xì)分解。通常,在Linux中使用insmod命令加載一個驅(qū)動程序模塊,例如8139too.o目標(biāo)文件。加載之后,Linux會默認(rèn)執(zhí)行模塊中的module_init(rtl8139_init_module)宏函數(shù),其中的參數(shù)rtl8139_init_module是一個函數(shù)指針,指向在具體的驅(qū)動程序8139too.o中聲明的rtl8139_init_module函數(shù)。這個函數(shù)定義如下:staticint__initrtl8139_init_module18(void){returnpci_module_i
7、nit(&rtl8139_pci_driver);}pci_module_init是一個宏定義,實際上就等于pci_register_driver函數(shù)。(在2.6.30內(nèi)核版本中,直接變成了returnpci_register_driver(&rtl8139_pci_driver))。pci_register_driver函數(shù)的注釋說明了它的作用:registeranewpcidriver.Addsthedriverstructuretothelistofregistereddrivers。也就是把如下的這樣一個驅(qū)動程序(pci_dri
8、ver類型)掛到系統(tǒng)的驅(qū)動程序鏈表中:staticstructpci_driverrtl813