內容簡介
本書涵蓋了Linux嵌入式系統開發中網路體系結構實現的主要內容。
全書共分12章,第1章概述Linux核心組件與核心技術特點,以及網路體系結構實現套用到的核心開發的基礎知識。第2~5章在介紹了實現網路體系結構、協定棧、設備驅動程式的兩個最重要的數據結構sk_buff和net_device的基礎上,展示了Linux核心中為網路設備驅動程式設計和開發而建立的系統構架,最後以兩個實例來具體說明如何著手開發網路設備驅動程式,數據在硬體設備上的接收和傳送過程。第6章討論了網路協定棧中數據鏈路層收發數據的設計和實現,以及硬體層與協定層之間的接口。第7章講解了網路層IP協定的實現。第8~9章介紹傳輸層數據收發過程,重點介紹基於套接字的TCP/UDP傳輸實現。第10章討論了Linux核心套接字層的實現,以及套接字層與套用層、傳輸層之間的接口。第11章介紹網路套用軟體的開發技術,以及核心對網路套用的支持。第12章講解在嵌入式系統開發中如何將硬體驅動程式、核心代碼、應用程式集成在一起下載至晶片中,形成嵌入式可運行的系統,作為全書的總結。
本書可以作為高等院校計算機、通信專業學生學習作業系統的參考書,也可以作為從事嵌入式、計算機行業的工程技術人員的參考書。
前言
無論現在或將來,網路都是一個熱門的主題。目前幾乎所有的電子產品都具備不同程度的網路功能。網路功能的強弱和靈活度與其使用的作業系統對網路的支持程度有直接的關係。Linux作業系統從開發之初就是在Internet環境下實現的,網路子系統是Linux系統中最重要、最具特色的子系統之一,Linux核心中網路子系統在體系結構設計上的合理與靈活,使其可以任意地在現有Linux核心協定棧的基礎上實現新的網路協定、網路功能特色、對新網路適配器硬體的支持。
Linux 是開放原始碼的系統,隨著它的技術越來越完善,Linux的套用也越來越普及,現在更多的產品都選擇把Linux作為其嵌入的作業系統。在全世界有無以計數的計算機研發人員和愛好者在使用、測試Linux作業系統,為Linux系統開發新的套用,使Linux的技術日趨完美。
使用Linux作為研發平台,與使用別的作業系統不一樣,只能通過其提供的套用編程接口(API)函式來完成,無法清楚地了解其內部的實現原理,也就無法更好地在研究過程中對性能、效率等實施控制,有時為了滿足套用的需求,需要費很大的周折。特別是做嵌入式開發時,更需要依據手上的資源和成本要求對開發過程實施控制。
Linux是開放源碼的系統,可以通過學習和研究掌握其內部的實現,這無論對科研、學習還是系統開發都能帶來巨大的好處,這樣才能根據需要量體裁衣,定製自己所需的作業系統,去掉多餘的功能,只保留最有效、最適用的部分。Linux核心的網路功能更是如此,網路子系統具有大量的可選功能,如防火牆功能、路由功能等,不是每個設備都需要配備所有的這些功能,特別是在嵌入式系統,配置Linux核心組件就顯得尤其重要。
Linux網路體系結構比Linux核心中其他組件理解起來更困難,原因在於網路任務的實現被劃分為好幾個階段,在不同的時間由不同的代碼和進程來實現。如何將這些片段連在一起,各階段之間的接口是什麼,是研究Linux網路體系結構的一個難點。
筆者多年從事嵌入式Linux網路系統產品開發,在這個過程中了解到嵌入式系統的開發涉及硬體驅動、作業系統核心和系統套用3個層次。最終的嵌入式產品需要將以上3個部分集成,形成一個完整的執行檔,下載至嵌入式晶片中。本書的目的就是以Linux核心的網路子系統為縱向線索,以Linux核心TCP/IP協定在網路子系統中的實現為實例,把與嵌入式網路套用開發相關的技術知識組織在一起,來講解嵌入式Linux系統的套用開發技術、核心支持和硬體驅動程式開發的完整過程,以形成相關知識領域的完整體系結構,這樣讀者在研發過程中套用起來更得心應手。無論在做哪個部分的研發和學習:套用、核心、驅動程式,都能清楚地知道自己在做什麼,上下之間如何聯繫。
Linux核心網路子系統的功能特色多,代碼分散,所以本書的一個重要目的就是清楚地解釋Linux核心中網路子系統的主要功能特色、設計原理和實現流程,並告訴讀者如何跟蹤分析其內部C原始碼,如何將不同的代碼實現片段串連在一起,並展示其函式功能和數據結構的相互關係,從而對具體的研究過程起到指導和幫助作用。Linux核心TCP/IP協定棧的實現技術是學習和研究作業系統中網路子系統的一個很好的樣本和實例。
全書共分12章,按照TCP/IP協定棧分層結構,從如何驅動硬體、網路數據在TCP/IP協定棧中如何傳送/接收,到網路應用程式開發技術,最後如何形成嵌入式集成系統的思路來安排各章節的內容。本書由電子科技大學教授、博士生導師羅蕾擔任主審,羅蕾教授對本書的編寫予以積極支持和認真指導,她仔細地審閱了書稿,提出許多寶貴意見,在此謹向羅蕾教授表達衷心的感謝。在本書編寫過程中,還得到了電子工業出版社張春雨老師等的支持和幫助,謹向他們表示誠摯的謝意。
本書主要由單立平編著,其他參與編寫的人員有姜雲舟、單根全、單宏偉、王雪梅等。
由於本人水平有限,對書中的錯誤和不足之處,懇請廣大讀者批評指正,筆者將不勝感激。
編 著 者
目錄
第1章 概述 1
1.1 Linux核心組件 1
1.2 Linux核心中的活動 3
1.2.1 進程和系統調用 3
1.2.2 硬體中斷 4
1.2.3 tasklet 6
1.2.4 workqueue 6
1.2.5 軟體中斷 7
1.3 互斥機制 7
1.3.1 spin lock 8
1.3.2 讀-寫 spin lock 10
1.3.3 讀-複製-更新(Read-Copy-Update,RCU) 10
1.4 核心模組(module) 11
1.4.1 管理核心模組 11
1.4.2 自動裝載模組 12
1.4.3 模組功能的註冊和取消 13
1.4.4 在模組裝載時給模組傳遞參數 14
1.4.5 核心和模組的符號表 14
1.5 記憶體資源 15
1.5.1 高速緩衝區(memory cache) 15
1.5.2 高速快取和哈希鍊表 16
1.6 時間管理 16
1.7 嵌入式的挑戰 17
1.8 本章總結 18
第2章 Linux網路包傳輸的關鍵數據結構——Socket Buffer 19
2.1 Socket Buffer 設計概述 19
2.1.1 Socket Buffer與TCP/IP協定棧 19
2.1.2 Socket Buffer的對外接口 20
2.1.3 Socket Buffer的特點 20
2.2 Socket Buffer的構成 20
2.2.1 Socket Buffer的基本組成 21
2.2.2 Socket Buffer穿越TCP/IP協定棧 22
2.3 sk_buff數據域的設計和含義 24
2.3.1 sk_buff 中的結構管理域 24
2.3.2 常規數據域 27
2.3.3 sk_buff 的網路功能配置域 32
2.4 操作sk_buff的函式 34
2.4.1 創建和釋放Socket Buffer 35
2.4.2 數據空間的預留和對齊 40
2.4.3 複製和克隆 41
2.4.4 操作佇列的函式 43
2.4.5 引用計數的操作 44
2.4.6 協定頭指針操作 44
2.5 數據分片和分段 45
2.5.1 為什麼要分割數據包 45
2.5.2 設計skb_shared_info數據結構的目的 46
2.5.3 操作skb_shared_info的函式 46
2.6 本章總結 47
第3章 網路設備在核心中的抽象——struct net_device數據結構 48
3.1 協定棧與網路設備 49
3.1.1 協定棧軟體與網路設備硬體之間的接口 49
3.1.2 設備獨立接口檔案dev.c 50
3.1.3 設備驅動程式 51
3.1.4 struct net_device數據結構 51
3.2 struct net_device 數據結構 52
3.2.1 struct net_device數據結構的數據域 52
3.2.2 struct net_device數據結構的其他數據域 56
3.3 struct net_device數據結構中數據域的功能分類 63
3.3.1 設備管理域 64
3.3.2 設備配置管理域 64
3.3.3 設備狀態 65
3.3.4 統計 65
3.3.5 設備鍊表 66
3.3.6 鏈路層組傳送 66
3.3.7 流量管理 66
3.3.8 常規域 69
3.3.9 操作函式結構 69
3.4 函式指針 69
3.4.1 設備初始化 70
3.4.2 傳送 71
3.4.3 硬體協定頭 71
3.4.4 網路統計狀態 73
3.4.5 修改配置 73
3.5 本章總結 74
第4章 網路設備在Linux核心中識別 75
4.1 核心初始化的特點 76
4.1.1 命令行參數 76
4.1.2 網路子系統的命令行參數 78
4.2 核心啟動過程 80
4.2.1 用do_initcall函式完成的初始化 83
4.2.2 標記初始化函式的宏 84
4.2.3 網路子系統初始化 85
4.2.4 網路設備的初始化 86
4.3 網路設備的註冊和struct net_device數據結構實例的初始化 88
4.3.1 初始化函式的任務 88
4.3.2 網路設備的註冊和註銷 92
4.3.3 網路設備的引用計數(reference count) 97
4.3.4 允許和禁止網路設備 98
4.4 網路設備的管理 99
4.4.1 管理網路設備的鍊表 99
4.4.2 網路設備的搜尋函式 101
4.5 事件通知鏈 102
4.5.1 事件通知鏈構成 103
4.5.2 註冊回調函式到事件通知鏈 104
4.5.3 通知子系統有事件發生 106
4.5.4 網路子系統中的事件通知鏈 107
4.5.5 網路子系統傳送的事件 108
4.6 本章總結 108
第5章 網路設備驅動程式 109
5.1 網路設備驅動程式概述 109
5.1.1 網路設備驅動程式的任務 110
5.1.2 網路設備驅動程式的構成 110
5.2 網路設備與核心的互動 113
5.2.1 設備與核心的互動方式 113
5.2.2 硬體中斷 115
5.2.3 中斷在核心的實現 117
5.2.4 軟體中斷 120
5.3 網路設備驅動程式的實現 127
5.3.1 網路適配器的初始化 127
5.3.2 網路設備活動功能函式 132
5.3.3 網路設備管理函式 143
5.3.4 在適配器中支持組傳送 145
5.4 CS8900A網路適配器驅動程式的實現 149
5.4.1 CS8900A網路控制晶片的功能概述 149
5.4.2 CS8900A的PacketPage結構 151
5.4.3 CS8900A的操作 153
5.4.4 CS8900A設備驅動程式分析 157
5.5 本章總結 167
第6章 數據鏈路層數據幀的收發 168
6.1 關鍵數據結構 170
6.1.1 struct napi_struct數據結構 170
6.1.2 struct softnet_data數據結構 171
6.2 數據幀的接收處理 173
6.2.1 NAPI的實現 174
6.2.2 netif_rx函式分析 178
6.3 網路接收軟體中斷 182
6.3.1 net_rx_action的工作流程 182
6.3.2 net_rx_action函式的實現細節 183
6.3.3 從輸入佇列中讀取數據幀 185
6.3.4 處理輸入數據幀 186
6.4 數據鏈路層與網路層的接口 190
6.4.1 輸入數據幀協定解析 190
6.4.2 實現數據鏈路層與網路層接口的關鍵數據結構 192
6.4.3 接口的組織 194
6.5 數據鏈路層對數據幀傳送的處理 196
6.5.1 啟動/停止設備傳送數據 197
6.5.2 調度設備傳送數據幀 198
6.5.3 佇列策略接口 200
6.5.4 dev_queue_xmit函式 203
6.5.5 傳送軟體中斷 206
6.5.6 Watchdog時鐘 209
6.6 本章總結 211
第7章 網路層傳送 212
7.1 Internet協定的基本概念 213
7.1.1 Internet協定的任務 213
7.1.2 Internet 協定頭 214
7.1.3 Linux核心中描述IP協定頭的數據結構 217
7.2 IP協定實現前的準備工作 217
7.2.1 協定初始化 217
7.2.2 與網路過濾子系統的互動 219
7.2.3 與路由子系統的互動 220
7.3 輸入數據包在IP層的處理 220
7.3.1 ip_rcv函式分析 221
7.3.2 ip_rcv_finish函式分析 224
7.3.3 接收操作中IP選項的處理 226
7.4 IP選項 228
7.4.1 IP選項的格式 228
7.4.2 描述IP選項的數據結構 234
7.4.3 Linux核心對IP選項的處理 235
7.4.4 Linux核心對IP選項處理的具體實現 237
7.5 IPv4數據包的前送和本地傳送 245
7.5.1 數據包的前送 245
7.5.2 dst_output函式的實現 249
7.5.3 本地傳送的處理 250
7.6 在IP層的傳送 254
7.6.1 執行傳送的關鍵函式 255
7.6.2 傳送數據包相關信息的數據結構 256
7.6.3 ip_queue_xmit函式 260
7.6.4 ip_append_data函式預備 264
7.6.5 ip_append_data函式分析 274
7.6.6 ip_append_page 函式 279
7.6.7 ip_push_pending_frames函式 280
7.6.8 傳送數據包的整體過程 282
7.7 與相鄰子系統的接口 284
7.8 數據包的分片與重組 286
7.8.1 數據分片需要考慮的問題 287
7.8.2 在上層分片的效率 287
7.8.3 數據包分片/重組使用的IP 協定頭數據域 287
7.9 本章總結 288
第8章 傳輸層UDP協定的實現 289
8.1 UDP協定基礎 289
8.2 UDP協定實現的關鍵數據結構 290
8.2.1 UDP協定頭的數據結構 290
8.2.2 UDP的控制緩衝區 290
8.2.3 UDP套接字的數據結構 291
8.2.4 應用程式傳送給UDP負載數據的數據結構 291
8.3 UDP、套接字層、IP層之間的接口 292
8.3.1 UDP協定實例與套接字層間的接口 292
8.3.2 UDP協定與IP層之間的接口 293
8.4 傳送UDP數據報的實現 294
8.4.1 初始化一個連線 294
8.4.2 在UDP套接字上傳送數據包 297
8.4.3 向IP層傳送數據包 301
8.4.4 從用戶地址空間複製數據到數據報 304
8.5 UDP 協定接收的實現 305
8.5.1 UDP協定接收的處理函式 305
8.5.2 將數據包放入套接字接收佇列的處理函式 307
8.5.3 UDP協定接收廣播與組傳送數據包 308
8.5.4 UDP的哈希鍊表 309
8.5.5 將數據包放到套接字接收佇列 312
8.6 UDP協定在套接字層的接收處理 313
8.6.1 函式輸入參數 313
8.6.2 函式處理流程 313
8.7 本章總結 315
第9章 傳輸層TCP協定的實現 316
9.1 CP協定簡介 316
9.1.1 CP是可靠協定 316
9.1.2 TCP是面向連線的協定 318
9.1.3 TCP是按位元組流交換的協定 319
9.1.4 TCP協定實現的功能 320
9.2 描述TCP協定實現的關鍵數據結構 320
9.2.1 TCP協定頭數據結構 320
9.2.2 TCP的控制緩衝區 321
9.2.3 TCP套接字的數據結構 322
9.2.4 TCP協定選項Options 323
9.2.5 套用層傳送給傳輸層信息的數據結構 325
9.3 在TCP協定、套接字、IP層之間的接口 326
9.3.1 管理套接字與TCP接口的數據結構 326
9.3.2 初始化套接字與傳輸層之間的接口 327
9.3.3 TCP與IP層之間的接收接口 328
9.3.4 TCP與IP層之間的傳送接口 329
9.3.5 初始化TCP 套接字 331
9.4 TCP協定實例接收過程的實現 332
9.4.1 tcp_v4_rcv函式的實現 333
9.4.2 Fast Path和prequeue佇列的處理 338
9.4.3 處理TCP的Blocklog 佇列 340
9.4.4 套接字層的接收函式 342
9.5 Linux 核心中TCP傳送功能的實現 348
9.5.1 將數據從用戶地址空間複製到核心Socket Buffer 349
9.5.2 TCP 數據段輸出 354
9.5.3 傳送過程的狀態機 358
9.6 TCP套接字的連線管理 358
9.6.1 TCP連線初始化 361
9.6.2 TCP狀態從CLOSED切換到SYN_SENT 362
9.6.3 TCP連線的狀態管理 365
9.6.4 TCP連線為ESTABLISHED狀態時的接收處理 370
9.6.5 TCP的TIME_WAIT狀態處理 374
9.7 本章總結 379
第10章 套接字層實現 380
10.1 套接字概述 380
10.1.1 什麼是套接字 381
10.1.2 套接字與管理套接字的數據結構 383
10.1.3 套接字與檔案 390
10.2 套接字層的初始化 391
10.3 地址族的值和協定交換表 392
10.3.1 協定交換表的數據結構 392
10.3.2 套接字支持多協定棧的實現 393
10.4 IPv4中協定成員註冊和初始化 396
10.5 套接字API系統調用的實現 397
10.5.1 系統調用簡述 397
10.5.2 套接字API系統調用的實現 398
10.6 創建套接字 403
10.6.1 sock_create函式創建套接字 404
10.6.2 協定族套接字創建函式的管理 406
10.6.3 AF_INET套接字的創建 407
10.7 I/O系統調用和套接字 408
10.8 本章總結 409
第11章 套用層——網路套用套接字編程 411
11.1 套接字描述符 413
11.1.1 family參數 413
11.1.2 type 參數 413
11.1.3 protocol 參數 414
11.1.4 AF_XXX與PF_XXX形式的常數 414
11.2 地址格式 416
11.2.1 位元組順序 416
11.2.2 地址結構 417
11.2.3 支持地址格式轉換的函式 419
11.2.4 獲取網路配置信息 419
11.2.5 編程示例 423
11.2.6 將地址與套接字綁定 426
11.3 套接字連線 427
11.3.1 connect函式分析 427
11.3.2 伺服器套接字建立偵聽佇列 428
11.3.3 建立套接字連線 429
11.4 數據的傳送 430
11.4.1 send函式 430
11.4.2 傳送數據的函式 431
11.4.3 接收數據的函式 432
11.4.4 recvfrom、recvmsg函式 432
11.4.5 編程示例 433
11.5 套接字選項 441
11.5.1 設定套接字選項 441
11.5.2 讀取套接字選項 442
11.6 out-of-band 數據 443
11.7 非阻塞和異步I/O操作 444
11.8 本章總結 444
第12章 嵌入式系統網路套用技術 445
12.1 嵌入式系統的設計要素 445
12.2 嵌入式系統開發環境的構成 445
12.2.1 硬體構成 446
12.2.2 典型的硬體開發環境 447
12.2.3 軟體交叉平台開發環境 448
12.2.4 嵌入式軟體的開發步驟 448
12.3 將網路設備驅動程式加入核心 450
12.3.1 配置新網路設備 450
12.3.2 編譯新驅動程式 451
12.4 核心配置 452
12.4.1 目標硬體及核心、庫配置 452
12.4.2 核心組件配置 454
12.4.3 套用配置 459
12.5 集成應用程式並下載至目標板 460
12.5.1 集成應用程式 460
12.5.2 將執行檔案下載至目標板 461
12.6 本章總結 462