1.1 GNU与Linux的成长 1
第一章 走进Linux 1
1.2 Linux的开发模式和运作机制 3
1.3 走进Linux内核 4
1.3.1 Linux内核的特征 5
1.3.2 Linux内核版本的变化 5
1.4 分析Linux内核的意义 6
1.4.1 开发适合自己的操作系统 6
1.4.3 有助于计算机科学的教学和科研 7
1.4.2 开发高水平软件 7
第二章 Linux操作系统结构 9
2.1 Linux的抽象结构 10
2.1.1 概述 10
2.1.2 Linux内核的作用 11
2.1.3 Linux内核的抽象结构 11
2.1.4 系统数据结构 12
2.2 Linux的具体结构 13
2.3.2 功能 14
2.3 进程调度子系统 14
2.3.1 子系统描述 14
2.3.3 接口 15
2.3.4 数据结构 15
2.3.5 子系统结构 16
2.3.6 子系统依赖关系 16
2.4 内存管理子系统 17
2.4.1 子系统描述 17
2.4.2 功能 17
2.4.4 数据结构 18
2.4.3 接口 18
2.4.5 子系统结构 19
2.4.6 子系统依赖关系 19
2.5 虚拟文件系统 20
2.5.1 子系统描述 20
2.5.2 功能 21
2.5.3 接口 22
2.5.6 子系统依赖关系 23
2.5.4 数据结构 23
2.5.5 子系统结构 23
2.6 进程间通信(IPC) 24
2.6.1 子系统描述 24
2.6.2 功能 25
2.6.3 接口 26
2.6.4 数据结构 26
2.6.5 子系统结构 27
2.6.6 子系统的依赖关系 27
2.7 网络接口 28
2.7.1 Linux的网络层 28
2.7.2 接口 28
2.7.3 子系统描述 29
2.7.4 数据结构 30
2.7.5 子系统结构 30
2.8 Linux内核源代码 31
2.8.1 多版本的内核源代码 31
2.7.6 子系统依赖关系 31
2.8.2 Linux内核源代码的结构 32
2.8.3 从何处开始阅读源代码 33
2.9 常用术语的定义 35
第三章 进程调度 37
3.1 进程描述 37
3.1.1 进程和程序(Process and Program) 37
3.1.2 Linux中的进程概述 39
3.1.3 task_struct结构描述 41
3.1.4 task_struct数据结构 47
3.2 Linux时间系统 50
3.2.1 时钟硬件及时钟运作机制 50
3.2.2 千年危机(千年虫)简介 52
3.2.3 Linux时间系统 54
3.2.4 时钟中断 55
3.3 Linux的调度程序——Schedule() 64
3.3.1 基本原理 64
3.3.2 Linux进程调度时机 66
3.3.3 进程调度的依据 68
3.3.4 可运行队列(Runnable Queue) 70
3.3.5 进程调度(调度正文)的工作流程 71
3.3.6 调度程序流程图 72
3.4 Linux内核机制 76
3.4.1 内核机制的引入 76
3.4.2 Linux内核机制 77
3.4.3 任务队列(Task Queue) 80
3.4.4 定时器内核例程序处理程序(time bottom half handler) 82
4.1 虚拟存储器 87
第四章 保护模式 87
4.1.1 虚地址和虚地址空间 88
4.1.2 段机制和分页机制 88
4.1.3 保护 89
4.2 描述符 91
4.2.1 段机制 91
4.2.2 描述符的概念 92
4.2.3 系统段描述符 93
4.2.4 门描述符 94
4.3.1 描述符表 95
4.3 描述符表和寻址方式 95
4.3.2 选择器与描述符表寄存器 96
4.3.3 描述符投影寄存器 98
4.4 分页机制 99
4.4.1 状态和控制寄存器组 100
4.4.2 分页机构 101
4.4.3 页面高速缓冲寄存器 104
4.5.2 调用门 105
4.5 控制转移和任务切换 105
4.5.1 控制转移 105
4.5.3 任务切换 106
4.6 小结 107
第五章 Linux启动系统 109
5.1 初始化流程 109
5.1.1 系统加电或复位 110
5.1.2 BIOS启动 110
5.2.1 处理器对初始化的影响 111
5.2 初始化的任务 111
5.1.3 Boot Loader 111
5.1.4 操作系统的初始化 111
5.2.2 其他硬件设备对初始化的影响 112
5.3 Linux的Boot Loader 112
5.3.1 软盘的结构 112
5.3.2 硬盘的结构 113
5.3.3 Boot Loader 113
5.3.4 LILO 114
5.3.5 LILO的运行分析 117
5.4.1 Setup.S 119
5.4 进入操作系统 119
5.4.2 Head.S 120
5.5 main.c中的初始化 123
5.6 建立init进程 130
5.6.1 init进程的建立 130
5.6.2 启动所需的Shell脚本文件 131
第六章 Linux内存管理 135
6.1.1 Linux虚拟内存的实现结构 136
6.1 Linux的虚拟内存管理 136
6.1.2 多任务及保护 137
6.1.3 内核空间和用户空间 138
6.1.4 Linux虚拟内存实现机制间的关系 140
6.2 地址映射机制 141
6.2.1 地址映射的数据结构 141
6.2.2 进程的虚拟内存 145
6.2.3 内存映射 147
6.3 请页机制 149
6.3.1 页故障的产生 149
6.3.2 页错误的定位 150
6.3.3 页错误处理程序 151
6.3.4 几点说明 154
6.4 交换机制 154
6.4.1 页交换的方法 154
6.4.2 交换守护进程(kswapd)的分析 155
6.4.3 交换空间的数据结构 162
6.4.4 交换空间的应用 163
6.5 内存分配和回收机制 165
6.5.1 分配策略 165
6.5.2 系统级调用分配过程和释放过程 167
6.5.3 用户级内存分配释放函数 169
6.6 缓存和刷新机制 177
6.6.1 Linux使用的缓存 177
6.6.2 缓冲区高速缓存 179
6.6.3 翻译后援存储器(TBL) 182
6.6.4 刷新机制 184
6.7 进程的创建和执行 187
6.7.1 进程的创建 187
6.7.2 程序执行 191
6.7.3 执行函数 193
6.9 内存初始化 199
6.9.1 内存初始化过程 199
6.8 内存共享机制 199
6.9.2 进入用户模式 201
第七章 进程间通信 203
7.1 管道 203
7.1.1 Linux管道的实现机制 204
7.1.2 管道的应用 206
7.1.3 命名管道(FIFO) 207
7.2 System V的IPC机制 208
7.2.1 信号量 209
7.2.2 消息队列 216
7.2.3 共享内存 221
7.3 信号(signal) 223
7.3.1 信号的引入 223
7.3.2 信号掩码 225
7.3.3 系统调用 226
7.3.4 典型系统调用的实现 228
7.3.5 进程与信号的关系 230
7.3.6 信号举例 231
8.1 概述 233
第八章 虚拟文件系统 233
8.2 VFS中的重要数据结构 235
8.2.1 VFS的超级块 235
8.2.2 VFS的索引节点 236
8.2.3 与进程联系的三个结构 238
8.2.4 有关操作的数据结构 242
8.3 高速缓存 245
8.3.1 块高速缓存 245
8.3.2 索引节点高速缓存 249
8.3.3 目录高速缓存 251
8.4 文件系统的注册、安装与卸载 251
8.4.1 文件系统的注册 251
8.4.2 文件系统的安装 253
8.4.3 文件系统的卸载 255
8.5 限额机制 255
8.6 文件系统的系统调用 258
8.6.1 open系统调用 258
8.6.2 read系统调用 260
8.6.3 fcntl系统调用 261
第九章 EXT2文件系统 263
9.1 基本概念 264
9.2 EXT2的磁盘布局和数据结构 266
9.2.1 EXT2的磁盘布局 266
9.2.2 EXT2的超级块 267
9.2.3 EXT2的索引节点 270
9.2.4 组描述符 273
9.2.5 位图 274
9.2.6 索引节点表及举例 275
9.2.7 EXT2的目录项及文件的定位 276
9.3 文件的访问权限和安全 277
9.4 链接文件 279
9.5 错误处理 280
9.6 分配策略 281
第十章 模块机制 283
10.1 概述 283
10.1.1 什么是模块 283
10.1.2 为什么要使用模块 284
10.1.3 Linux内核模块的优缺点 285
10.2 实现机制 285
10.2.1 数据结构 285
10.2.2 实现函数的分析 288
10.2.3 模块的装入 290
10.3 卸载(unload)一个模块 291
10.4 编写内核模块 292
10.4.1 内核的复制函数 293
10.4.2 内核版本2.0.35与2.2.3之间的变化 294
10.4.3 简单内核模块的编写 295
10.4.4 内核模块的Makefiles文件 296
10.4.5 内核模块的多个文件 297
10.5 系统调用 299
10.6 模块实用程序 299
第十一章 设备驱动程序 301
11.1 Linux的设备管理 301
11.1.1 I/O软件 302
11.1.2 设备驱动程序 303
11.1.3 Linux驱动程序的几个通用函数 305
11.2 中断 306
11.2.1 硬件对中断的支持 307
11.2.2 Linux对中断的管理 307
11.2.3 Linux对中断的处理 309
11.3 块设备驱动程序 310
11.3.1 块设备驱动程序的登记 310
11.3.2 块设备基于缓冲区的数据交换 311
11.3.3 块设备驱动程序的几个函数 312
11.3.4 RAM盘驱动程序的实现 314
11.3.5 硬盘驱动程序的实现 317
11.4 字符设备驱动程序 321
11.4.1 字符设备的注册 321
11.4.2 工作内存 322
11.4.3 基本入口点 323
11.4.4 一个字符设备驱动程序的实例 324
11.4.5 驱动程序的编译与装载 333
12.1 基本原理 335
第十二章 Linux系统调用机制 335
12.2 系统调用的初始化 336
12.3 Linux系统调用的执行 340
12.4 增加新的系统调用 343
12.4.1 编写一个系统调用 343
12.4.2 连接新的系统调用 344
12.4.3 使用新的系统调用 345
第十三章 网络 347
13.1 概述 347
13.2 网络协议 348
13.2.1 网络参考模型 349
13.2.2 TCP/IP协议工作原理及数据流 349
13.2.3 Internet协议 349
13.2.4 TCP协议 351
13.3 套接字(socket) 352
13.3.1 套接字在网络中的地位和作用 352
13.3.2 套接字接口的种类 353
13.3.3 套接字的工作原理 354
13.3.4 socket的通信过程 355
13.3.5 和套接字相关的数据结构 357
13.3.6 socket为用户提供的系统调用 359
13.4 套接字缓冲区(sk_buff) 360
13.4.1 套接字缓冲区的特点 360
13.4.2 套接字缓冲区操作基本原理 361
13.4.3 sk_buff数据结构的核心内容 363
13.4.4 套接字缓冲区提供的函数 364
13.4.5 套接字缓冲区的上层支持例程 365
13.4.6 sk_buff数据结构 367
13.5 网络设备接口 369
13.5.1 基本结构 369
13.5.2 命名规则 370
13.5.3 设备注册 371
13.5.4 网络设备数据结构 372
13.5.5 支持函数 375
13.5.6 device数据结构 377
13.6 本章小结 380