标题：嵌入式Linux网络体系结构设计与TCP/IP协议栈
图书信息
单立平  编著  ISBN 978-7-121-12976-6
2011年5月出版
定价：69.00元
16开
480 页
内 容 简 介
本书涵盖了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