第1章 从头说起 1
1.1 简介 1
1.1.1 UNIX简史 1
1.1.2 起源 1
1.1.3 扩散 2
1.1.4 BSD 3
1.1.5 System V 4
1.1.6 商业化 5
1.1.7 Mach 5
1.1.8 标准 5
1.1.9 OSF和UI 6
1.1.10 SVR4及其之后 7
1.2 变革使命 8
1.2.1 功能 8
1.2.2 网络 8
1.2.3 性能 9
1.2.4 硬件变化 9
1.2.5 质量提升 10
1.2.6 变革 10
1.2.7 其他应用程序领域 11
1.2.8 小即是美 11
1.2.9 灵活性 12
1.3 回顾过去,展望未来 13
1.3.1 UNIX系统的优点是什么 13
1.3.2 UNIX系统的缺点是什么 14
1.4 本书内容说明 15
参考文献 15
第2章 进程与内核 17
2.1 简介 17
2.2 模式、空间和上下文 19
2.3 进程抽象 21
2.3.1 进程状态 21
2.3.2 进程上下文 23
2.3.3 用户凭据 23
2.3.4 u区和proc结构 24
2.4 执行在内核态中 26
2.4.1 系统调用接口 26
2.4.2 中断处理 27
2.5 同步 29
2.5.1 阻塞操作 29
2.5.2 中断 30
2.5.3 多处理器 31
2.6 进程调度 31
2.7 信号 32
2.8 新的进程和程序 33
2.8.1 fork和exec 33
2.8.2 进程的创建 34
2.8.3 fork的优化 35
2.8.4 调用新的程序 35
2.8.5 进程终止 37
2.8.6 等待进程终止 37
2.8.7 僵死进程 38
2.9 小结 39
2.10 练习题 39
参考文献 39
第3章 线程和轻量级进程 41
3.1 简介 41
3.1.1 动机 41
3.1.2 多线程和多处理器 42
3.1.3 并发和并行 43
3.2 基本抽象 44
3.2.1 内核线程 45
3.2.2 轻量级进程 45
3.2.3 用户线程 46
3.3 轻量级线程设计时要考虑的问题 49
3.3.1 fork的语义 49
3.3.2 其他系统调用 50
3.3.3 信号传递和处理 50
3.3.4 可见性 51
3.3.5 栈增长 51
3.4 用户级别的线程库 51
3.4.1 编程接口 52
3.4.2 线程库的实现 52
3.5 调度器激活 53
3.6 Solaris和SVR4上的多线程 54
3.6.1 内核线程 54
3.6.2 轻量级进程的实现 55
3.6.3 用户线程 56
3.6.4 用户线程的实现 56
3.6.5 中断处理 57
3.6.6 系统调用处理 58
3.7 Mach的线程 58
3.7.1 Mach抽象:任务和线程 58
3.7.2 Mach的C-threads 59
3.8 Digital UNIX 60
3.8.1 UNIX接口 60
3.8.2 系统调用和信号 62
3.8.3 pthreads库 62
3.9 Mach3.0的continuation 63
3.9.1 编程模型 63
3.9.2 使用continuation 63
3.9.3 优化 65
3.9.4 分析 65
3.10 小结 65
3.11 练习题 66
参考文献 66
第4章 信号和会话管理 68
4.1 简介 68
4.2 信号生成和处理 68
4.2.1 信号处理 69
4.2.2 信号的生成 71
4.2.3 典型场景 72
4.2.4 睡眠与信号 72
4.3 不可靠的信号 73
4.4 可靠的信号 74
4.4.1 主要特性 74
4.4.2 SVR3实现 75
4.4.3 BSD信号管理 75
4.5 SVR4上的信号 76
4.6 信号的实现 77
4.6.1 信号生成 78
4.6.2 交付和处理 78
4.7 异常 79
4.8 Mach的异常处理 79
4.8.1 异常端口 80
4.8.2 错误处理 80
4.8.3 调试器交互 81
4.8.4 分析 81
4.9 进程组和终端管理 82
4.9.1 基本概念 82
4.9.2 SVR3模型 83
4.9.3 限制 84
4.9.4 4.3BSD的进程组和终端 84
4.9.5 缺点 86
4.10 SVR4的会话体系结构 86
4.10.1 动机 87
4.10.2 会话和进程组 87
4.10.3 数据结构 88
4.10.4 控制终端 89
4.10.5 4.4BSD的会话实现机制 89
4.11 小结 90
4.12 练习题 90
参考文献 91
第5章 进程调度 92
5.1 简介 92
5.2 时钟中断处理 93
5.2.1 callout 93
5.2.2 告警 95
5.3 调度器目标 95
5.4 传统的UNIX调度 96
5.4.1 进程优先级 97
5.4.2 调度器的实现 98
5.4.3 运行队列的操作 99
5.4.4 分析 99
5.5 SVR4调度器 100
5.5.1 类无关层 100
5.5.2 调度类的接口 101
5.5.3 分时类 103
5.5.4 实时类 104
5.5.5 priocntl系统调用 105
5.5.6 分析 106
5.6 Solaris 2.x调度的改善 107
5.6.1 可抢占的内核 107
5.6.2 多处理器的支持 107
5.6.3 隐式调度 108
5.6.4 优先级反转 109
5.6.5 优先级继承的实现 110
5.6.6 优先级继承的局限性 112
5.6.7 turnstile 113
5.6.8 分析 113
5.7 Mach上的调度 113
多处理器支持 114
5.8 Digital UNIX的实时调度 116
多处理器支持 116
5.9 其他调度实现 117
5.9.1 公平调度方法 117
5.9.2 最终期限驱动调度方法 117
5.9.3 三级调度器 118
5.10 小结 119
5.11 练习题 119
参考文献 120
第6章 进程间通信 121
6.1 简介 121
6.2 通用的IPC方法 121
6.2.1 信号 122
6.2.2 管道 122
6.2.3 SVR4管道 124
6.2.4 进程跟踪 124
6.3 System V IPC 126
6.3.1 公共元素 126
6.3.2 信号量 127
6.3.3 消息队列 130
6.3.4 共享内存 131
6.3.5 讨论 133
6.4 Mach IPC 133
基本概念 134
6.5 消息 135
6.5.1 消息数据结构 135
6.5.2 消息传递接口 136
6.6 端口 137
6.6.1 端口命名空间 137
6.6.2 端口数据结构 138
6.6.3 端口转换 138
6.7 消息传递 139
6.7.1 转换端口权利 140
6.7.2 out-of-line内存 141
6.7.3 控制流 142
6.7.4 通知 143
6.8 端口操作 143
6.8.1 销毁端口 143
6.8.2 备份端口 144
6.8.3 端口集合 144
6.8.4 端口插补 145
6.9 扩展性 145
6.10 Mach3.0的增强 146
6.10.1 一次性的发送权利 147
6.10.2 Mach3.0的通知 147
6.10.3 发送权利的用户引用计数 148
6.11 讨论 148
6.12 小结 149
6.13 练习题 149
参考文献 149
第7章 同步和多处理器 151
7.1 简介 151
7.2 传统UNIX内核里的同步机制 152
7.2.1 中断屏蔽 152
7.2.2 睡眠和唤醒 152
7.2.3 传统方法的局限性 153
7.3 多处理器系统 154
7.3.1 内存模型 154
7.3.2 同步支持 155
7.3.3 软件体系架构 156
7.4 多处理器的同步问题 157
7.4.1 唤醒丢失问题 157
7.4.2 惊群问题 158
7.5 信号量 158
7.5.1 信号量提供互斥操作 159
7.5.2 使用信号量提供事件等待 159
7.5.3 使用信号量来控制可计数的资源 160
7.5.4 信号量的缺点 160
7.5.5 Convoy 161
7.6 自旋锁 162
7.7 条件变量 163
7.7.1 实现问题 164
7.7.2 事件 165
7.7.3 阻塞锁 165
7.8 读写锁 165
7.8.1 设计考虑 165
7.8.2 实现 166
7.9 引用计数 167
7.10 其他考虑 168
7.10.1 死锁避免 168
7.10.2 递归锁 169
7.10.3 阻塞还是自旋 170
7.10.4 锁什么 170
7.10.5 粒度和持续时间 170
7.11 案例研究 171
7.11.1 SVR4.2 /MP 171
7.11.2 Digital UNIX 172
7.11.3 其他实现 173
7.12 小结 174
7.13 练习题 174
参考文献 175
第8章 文件系统接口和框架 176
8.1 简介 176
8.2 文件的用户接口 176
8.2.1 文件和目录 177
8.2.2 文件属性 178
8.2.3 文件描述符 179
8.2.4 文件I/O 181
8.2.5 分散-聚集I/O 182
8.2.6 文件锁机制 183
8.3 文件系统 183
8.4 特殊文件 184
8.4.1 符号链接 184
8.4.2 管道和FIFO 185
8.5 文件系统框架 186
8.6 Vnode/Vfs架构 187
8.6.1 目标 187
8.6.2 从设备I/O得到的注解 187
8.6.3 vnode/vfis接口概览 190
8.7 实现概览 191
8.7.1 目标 191
8.7.2 Vnoces以及打开文件 191
8.7.3 Vnode 192
8.7.4 Vnode引用计数 193
8.7.5 Vfs对象 194
8.8 文件系统相关对象 194
8.8.1 每个文件的私有数据 194
8.8.2 vnodeops结构 195
8.8.3 vfs层中文件系统相关部分 196
8.9 挂载文件系统 196
8.9.1 虚拟文件系统转换表 196
8.9.2 mount函数实现 197
8.9.3 VFS MOUNT过程 197
8.10 文件操作 197
8.10.1 路径遍历 198
8.10.2 目录名查找缓存 199
8.10.3 VOP LOOKUP操作 199
8.10.4 打开文件 200
8.10.5 文件I/O 201
8.10.6 文件属性 201
8.10.7 用户凭据 201
8.11 分析 202
8.11.1 SVR4系统实现的缺点 202
8.11.2 4.4 BSD模型 203
8.11.3 OSF/l方法 204
8.12 小结 205
8.13 练习题 205
参考文献 206
第9章 文件系统的实现 207
9.1 简介 207
9.2 System V文件系统(s5fs) 208
9.2.1 目录 208
9.2.2 inode 209
9.2.3 超级块 210
9.3 s5fs内核组织 211
9.3.1 内存inode 211
9.3.2 inode查找 212
9.3.3 文件I/O 213
9.3.4 inode的分配和回收 214
9.4 s5fs的分析 215
9.5 伯克利快速文件系统(FFS) 216
9.6 硬盘结构 216
9.7 磁盘组织 216
9.7.1 块和片段 217
9.7.2 分配策略 218
9.8 FFS的增强功能 219
9.9 分析 220
9.10 临时文件系统 221
9.10.1 内存文件系统 221
9.10.2 tmpfs文件系统 222
9.11 特殊用途文件系统 223
9.11.1 specfs文件系统 223
9.11.2 /proc文件系统 223
9.11.3 处理器文件系统 225
9.11.4 Trans lucent文件系统 225
9.12 旧的缓冲区缓存 226
9.12.1 基本操作 227
9.12.2 缓冲区头结构 228
9.12.3 优点 228
9.12.4 缺点 228
9.12.5 保证文件系统的一致性 229
9.13 小结 230
9.14 练习题 230
参考文献 231
第10章 分布式文件系统 232
10.1 简介 232
10.2 分布式文件系统的一般特征 232
10.3 网络文件系统 233
10.3.1 用户视角 234
10.3.2 设计目标 235
10.3.3 NFS的组件 235
10.3.4 无状态设计 237
10.4 NFS协议集 238
10.4.1 外部数据表示 238
10.4.2 远程过程调用 239
10.5 NFS实现 240
10.5.1 控制流 240
10.5.2 文件句柄 241
10.5.3 挂载操作 241
10.5.4 路径名的查找 242
10.6 UNIX语义 243
10.6.1 打开文件许可 243
10.6.2 已打开文件的删除 243
10.6.3 读写操作 244
10.7 NFS性能 244
10.7.1 性能瓶颈 244
10.7.2 客户端缓存 244
10.7.3 延迟写 245
10.7.4 重传缓存 246
10.8 专用NFS服务器 247
10.8.1 Auspex的Functional Multiprocessor架构 247
10.8.2 IBM的HA-NFS服务器 248
10.9 NFS安全 249
10.9.1 NFS访问控制 249
10.9.2 UID重映射 250
10.9.3 根用户重映射 250
10.10 NFS版本3 251
10.11 远程文件共享 252
10.12 RFS架构 252
10.12.1 远程消息协议 253
10.12.2 有状态操作 253
10.13 RFS实现 254
10.13.1 远程挂载 254
10.13.2 RFS客户端和服务器 255
10.13.3 崩溃恢复 255
10.13.4 其他问题 256
10.14 客户端缓存 256
10.15 Andrew文件系统 258
10.15.1 可伸缩架构 258
10.15.2 存储和命名空间的组织 259
10.15.3 会话级语义 260
10.16 AFS实现 260
10.16.1 缓存与一致性 261
10.16.2 路径名查找 261
10.16.3 安全性 262
10.17 AFS的不足 262
10.18 DCE的分布式文件系统 263
10.18.1 DFS架构 263
10.18.2 缓存一致性 264
10.18.3 令牌管理器 265
10.18.4 DFS的其他服务 266
10.18.5 分析 266
10.19 小结 267
10.20 练习题 267
参考文献 268
第11章 高级文件系统 271
11.1 简介 271
11.2 传统文件系统的局限 271
11.2.1 FFS磁盘布局 272
11.2.2 磁盘上写操作的主导 273
11.2.3 元数据更新 274
11.2.4 故障修复 274
11.3 文件系统簇(SUN-FFS) 275
11.4 日志方法 276
11.5 日志结构文件系统 277
11.6 4.4BSD日志结构文件系统 277
11.6.1 日志写入 278
11.6.2 数据检索 279
11.6.3 崩溃恢复 279
11.6.4 cleaner进程 280
11.6.5 分析 280
11.7 元数据日志 281
11.7.1 正常操作 282
11.7.2 日志的一致性 283
11.7.3 崩溃恢复 284
11.7.4 分析 284
11.8 Episode文件系统 285
11.8.1 基本抽象 285
11.8.2 结构 286
11.8.3 日志记录 287
11.8.4 其他特性 287
11.9 “看门狗”监视器 288
11.9.1 目录的“看门狗”进程 289
11.9.2 消息通道 289
11.9.3 “看门狗”进程的应用 290
11.10 4.4BSD的portal文件系统 290
11.11 可堆叠文件系统层次 291
11.11.1 框架和接口 292
11.11.2 SunSoft原型 293
11.12 4.4 BSD文件系统接口 294
11.13 小结 295
11.14 练习题 295
参考文献 296
第12章 内核内存分配 298
12.1 简介 298
12.2 功能需求 299
12.3 资源映射分配器 301
12.4 简单的幂空闲链表分配器 303
12.5 McKusick-Karels分配器 305
12.6 伙伴系统 307
12.7 SVR4的惰性伙伴算法 308
12.7.1 惰性合并 309
12.7.2 SVR4的实现细节 310
12.8 Mach和OSF/1的区块分配器 310
12.8.1 垃圾回收 311
12.8.2 分析 312
12.9 一种针对多处理器系统的分层式分配器 312
12.10 Solaris 2.4的Slab分配器 314
12.10.1 复用对象 314
12.10.2 利用硬件缓存 315
12.10.3 分配器足迹 315
12.10.4 设计与接口 316
12.10.5 实现细节 317
12.10.6 分析 318
12.11 小结 318
12.12 练习题 319
参考文献 320
第13章 虚拟内存 321
13.1 简介 321
13.2 按需分页 324
13.2.1 功能需求 324
13.2.2 虚拟地址空间 325
13.2.3 页面的首次访问 326
13.2.4 交换区 326
13.2.5 转换映射 327
13.2.6 页面替换策略 328
13.3 对硬件的需求 328
13.3.1 MMU缓存 330
13.3.2 Intel 80x86 331
13.3.3 IBM RS/6000 333
13.3.4 MIPS R3000 335
13.4 4.3 BSD——案例研究 336
13.4.1 物理内存 337
13.4.2 地址空间 338
13.4.3 页在哪里 339
13.4.4 交换空间 340
13.5 4.3 BSD内存管理操作 341
13.5.1 创建进程 341
13.5.2 缺页异常处理 342
13.5.3 空闲页面链表 344
13.5.4 交换 345
13.6 分析 346
13.7 练习题 347
参考文献 348
第14章 SVR4VM架构 349
14.1 简介 349
14.2 内存映射文件 349
14.3 VM的设计理念 351
14.4 基础抽象 352
14.4.1 物理内存 353
14.4.2 地址空间 353
14.4.3 地址映射 354
14.4.4 匿名页 355
14.4.5 硬件地址转换 356
14.5 段驱动程序 357
14.5.1 seg_vn 357
14.5.2 seg_map 358
14.5.3 seg dev 359
14.5.4 seg_kmem 359
14.5.5 seg_kp 359
14.6 交换层 359
14.7 VM操作 361
14.7.1 创建新映射 361
14.7.2 匿名页处理 361
14.7.3 创建进程 363
14.7.4 共享匿名页 364
14.7.5 处理缺页异常 364
14.7.6 共享内存 365
14.7.7 其他组件 366
14.8 与vnode子系统的交互 367
14.8.1 对vnode接口的修改 367
14.8.2 统一文件访问机制 368
14.8.3 其他细节 370
14.9 Solaris的虚拟交换空间 370
14.9.1 交换空间扩展 370
14.9.2 虚拟交换管理 371
14.9.3 讨论 372
14.10 分析 372
14.11 性能改进 374
14.11.1 缺页异常率偏高的原因 374
14.11.2 SVR4对SunOS VM实现的改进 375
14.11.3 结果与讨论 375
14.12 小结 376
14.13 练习题 376
参考文献 377
第15章 其他内存管理技术 378
15.1 简介 378
15.2 Mach的内存管理设计 378
15.2.1 设计目标 378
15.2.2 对外接口 379
15.2.3 基础抽象 380
15.3 内存共享机制 381
15.3.1 写时复制共享 382
15.3.2 读写共享 383
15.4 内存对象与Pager 384
15.4.1 初始化内存对象 384
15.4.2 内核与pager的接口 384
15.4.3 内核与Pager的交互 385
15.5 外部pager和内部pager 386
15.6 页面替换 388
15.7 分析 389
15.8 4.4BSD的内存管理 390
15.9 旁路转换缓冲区的一致性 391
15.9.1 单处理器上的TLB一致性 392
15.9.2 多处理器问题 393
15.10 Mach中的TLB击落算法 394
15.10.1 同步与死锁的避免 395
15.10.2 讨论 395
15.11 SVR4和SVR4.2UNIX中的TLB一致性 396
15.11.1 SVR4/MP 396
15.11.2 SVR4.2/MP 397
15.11.3 惰性击落算法 397
15.11.4 立即击落算法 398
15.11.5 讨论 399
15.12 其他TLB一致性算法 399
15.13 虚拟地址缓存 400
15.13.1 修改映射 401
15.13.2 地址别名 402
15.13.3 DMA操作 402
15.13.4 维护缓存一致性 403
15.13.5 分析 404
15.14 练习题 404
参考文献 405
第16章 设备驱动和I/O 407
16.1 简介 407
16.2 概述 407
16.2.1 硬件配置 408
16.2.2 设备中断 409
16.3 设备驱动程序框架 410
16.3.1 设备和驱动的分类 410
16.3.2 调用驱动程序代码 411
16.3.3 设备转换表 412
16.3.4 驱动入口点函数 413
16.4 输入输出(I/O)子系统 414
16.4.1 主设备号和从设备号 415
16.4.2 设备文件 416
16.4.3 specfs文件系统 417
16.4.4 通用snode结构 418
16.4.5 设备克隆 419
16.4.6 针对字符设备的I/O操作 420
16.5 poll系统调用 420
16.5.1 poll系统调用的实现 421
16.5.2 BSD 4.3 系统select系统调用 422
16.6 块设备I/O操作 423
16.6.1 buf数据结构 424
16.6.2 与vnode结构的交互 425
16.6.3 设备访问方法 425
16.6.4 块设备的裸I/O 427
16.7 DDI/DKI规范 428
16.7.1 一般建议 429
16.7.2 Section 3函数 429
16.7.3 其他种类接口 430
16.8 更新的SVR4发行版 431
16.8.1 多处理器安全的驱动 431
16.8.2 SVR4.1 /ES的变化 432
16.8.3 动态加载和卸载 432
16.9 未来方向 434
16.10 小结 435
16.11 练习题 435
参考文献 436
第17章 STREAMS 437
17.1 动机 437
17.2 概述 438
17.3 消息和队列 439
17.3.1 消息 440
17.3.2 虚拟复制 440
17.3.3 消息类型 441
17.3.4 队列和模块 442
17.4 流I/O 443
17.4.1 STREAMS调度程序 444
17.4.2 优先级组 445
17.4.3 流量控制 445
17.4.4 驱动程序尾部 446
17.4.5 流头 447
17.5 配置和设置 448
17.5.1 配置一个STREAMS模块或驱动程序 448
17.5.2 打开流 449
17.5.3 推送一个模块到流上 451
17.5.4 克隆设备 451
17.6 STREAMS的ioctl命令 452
17.6.1 带有I_STR的ioctl命令处理 452
17.6.2 透明的ioctl命令 453
17.7 内存分配 453
17.8 多路复用 455
17.8.1 上部多路复用器 455
17.8.2 下部多路复用器 456
17.8.3 链接流 456
17.8.4 数据流 458
17.8.5 普通链接和持久链接 458
17.9 FiFO和管道 459
17.9.1 FiFO中STREAMS的应用 459
17.9.2 使用STREAMS的管道 460
17.10 网络接口 461
17.10.1 传输提供者接口 461
17.10.2 传输层接口 462
17.10.3 socket 463
17.10.4 SVR4的socket实现 464
17.11 小结 464
17.12 练习题 465
参考文献 466