第1章 从开机加电到执行main函数之前的过程 1
1.1 启动BIOS,准备实模式下的中断向量表和中断服务程序 1
1.1.1 BIOS的启动原理 2
1.1.2 BIOS在内存中加载中断向量表和中断服务程序 3
1.2 加载操作系统内核程序并为保护模式做准备 4
1.2.1 加载第一部分代码——引导程序(bootsect) 5
1.2.2 加载第二部分代码——setup 7
1.2.3 加载第三部分代码——system模块 12
1.3 开始向32位模式转变,为main函数的调用做准备 16
1.3.1 关中断并将system移动到内存地址起始位置0x00000 16
1.3.2 设置中断描述符表和全局描述符表 18
1.3.3 打开A20,实现32位寻址 20
1.3.4 为在保护模式下执行head.s做准备 21
1.3.5 head.s开始执行 24
1.4 本章小结 41
第2章 从main到怠速 42
2.1 开中断之前的准备工作 43
2.1.1 复制根设备号和硬盘参数表 44
2.1.2 物理内存规划格局 45
2.1.3 虚拟盘设置与初始化 46
2.1.4 内存管理结构mem_map初始化 47
2.1.5 异常处理类中断服务程序挂接 48
2.1.6 初始化块设备请求项结构 50
2.1.7 与建立人机交互界面相关的外设的中断服务程序挂接 52
2.1.8 开机启动时间设置 55
2.1.9 系统开始激活进程0 56
2.1.10 进程相关事务初始化设置 57
2.1.11 时钟中断设置 59
2.1.12 系统调用服务程序挂接 59
2.1.13 初始化缓冲区管理结构 61
2.1.14 初始化硬盘 63
2.1.15 初始化软盘 65
2.1.16 开中断 66
2.2 进程创建的最基本动作 67
2.2.1 操作系统为进程0创建进程1做准备 67
2.2.2 在进程槽中为进程1申请一个空闲位置并获取进程号 71
2.2.3 复制进程信息之前,先将一些数据压栈 73
2.2.4 初步设置进程1管理结构 74
2.2.5 进程0创建进程1的过程中发生时钟中断 76
2.2.6 从时钟中断返回 78
2.2.7 调整进程1管理结构 79
2.2.8 设置进程1的线性地址空间及物理页面 81
2.2.9 继续调整进程1管理结构 84
2.2.10 操作系统如何区分进程0和进程1 87
2.2.11 进程0准备切换到进程1 89
2.2.12 系统切换到进程1执行 90
2.3 加载根文件系统 92
2.3.1 进程1如何开始执行 96
2.3.2 进程1开始执行 98
2.3.3 进程1开始以数据块的形式操作硬盘 99
2.3.4 将找到的缓冲块与请求项挂接 101
2.3.5 将请求项与硬盘处理函数挂接 104
2.3.6 进行硬盘读盘前的准备工作 105
2.3.7 给硬盘下达读盘指令 106
2.3.8 进程1由于等待读盘操作挂起 107
2.3.9 系统切换到进程0执行 109
2.3.10 进程0的执行过程 110
2.3.11 进程0执行过程中发生硬盘中断 111
2.3.12 硬盘中断服务程序响应后,进程0继续执行 113
2.3.13 再次响应硬盘中断并唤醒进程1 114
2.3.14 读盘操作完成后,进程1继续执行 116
2.3.15 进程1继续设置硬盘管理结构 117
2.3.16 进程1获取软盘超级块,为加载根文件系统做准备 118
2.3.17 进程1备份超级块数据 119
2.3.18 进程1将根文件系统从软盘拷贝到虚拟盘 120
2.3.19 进程1开始加载根文件系统 122
2.3.20 进程1准备加载根文件系统超级块 123
2.3.21 进程1加载根文件系统超级块 124
2.3.22 进程1继续加载根文件系统 126
2.3.23 进程1准备读取根目录i节点 127
2.3.24 进程1加载根目录i节点 128
2.3.25 进程1结束加载根文件系统的过程 129
2.4 打开终端设备文件及复制文件句柄 131
2.4.1 进程1与内核文件表挂接,为打开文件做准备 133
2.4.2 确定打开操作的起点 135
2.4.3 获得枝梢i节点——dev目录文件的i节点 136
2.4.4 确定dev目录文件i节点为枝梢i节点 137
2.4.5 继续返回枝梢i节点 138
2.4.6 查找tty0文件的i节点 138
2.4.7 将tty0设备文件的i节点返回给sys_open系统调用 139
2.4.8 分析tty0文件i节点 140
2.4.9 设置文件管理结构并返回给用户进程 141
2.4.10 进程1复制tty0文件句柄 142
2.4.11 进程1继续复制tty0文件句柄 144
2.5 创建进程2 145
2.5.1 进程1准备创建进程2 145
2.5.2 复制进程2管理结构并进行调整 146
2.5.3 设置进程2的页目录项并复制进程2的页表 146
2.5.4 调整进程2管理结构中与文件有关的内容 146
2.5.5 进程1执行过程中发生时钟中断 148
2.5.6 进程1从时钟中断返回,准备切换到进程2 150
2.6 进程1等待进程2退出 150
2.6.1 进程1查找它自己的子进程 151
2.6.2 对进程2的状态进行处理 151
2.6.3 切换到进程2执行 153
2.7 shell程序的加载 154
2.7.1 进程2开始执行 156
2.7.2 为打开/etc/rc文件做准备 156
2.7.3 进程2打开“/etc/rc”配置文件 157
2.7.4 通过压栈为加载shell文件做准备 158
2.7.5 为参数和环境变量设置做准备 159
2.7.6 得到shell文件的i节点 160
2.7.7 为加载参数和环境变量做准备 161
2.7.8 根据i节点,对shell文件进行检测 162
2.7.9 检测shell文件头 163
2.7.10 备份文件头并进行分析 163
2.7.11 对shell文件进行进一步分析 165
2.7.12 拷贝参数和环境变量 166
2.7.13 调整进程2的管理结构 167
2.7.14 继续调整进程2管理结构 168
2.7.15 释放进程2继承的页面 169
2.7.16 检测协处理器 170
2.7.17 调整shell程序所在的线性空间地址 171
2.7.18 为shell程序准备参数和环境变量 172
2.7.19 继续调整进程2管理结构 173
2.7.20 调整EIP,使其指向shell程序入口地址 173
2.7.21 shell程序执行引发缺页中断 175
2.7.22 缺页中断中Shell程序加载前的检测 175
2.7.23 为即将载入的内容申请页面 177
2.7.24 将shell程序载入新获得的页面 177
2.7.25 根据shell程序的情况,调整页面的内容 178
2.7.26 将线性地址空间与程序所在的物理页面对应 179
2.8 系统实现怠速 180
2.8.1 Shell进程准备创建update进程 180
2.8.2 进程2开始执行/etc/rc文件 181
2.8.3 准备加载update进程 181
2.8.4 update进程的作用 182
2.8.5 shell程序检测“/etc/rc”文件 183
2.8.6 shell进程退出 184
2.8.7 shell进程退出善后处理 185
2.8.8 进程1清理shell进程管理结构 187
2.8.9 系统开始重建shell 190
2.8.10 shell进程为何不会再次退出 192
2.9 小结 194
第3章 安装文件系统 195
3.1 获取硬盘设备号 196
3.1.1 用户发出安装硬盘文件系统指令 196
3.1.2 从分析路径开始,准备查找hd1设备的挂接点 197
3.1.3 以根目录i节点为依托,得到dev目录文件的i节点 197
3.1.4 从dev目录文件中找到代表hd1设备文件的目录项 198
3.1.5 得到hd1设备文件的i节点号 199
3.1.6 释放dev目录文件的相关内容 200
3.1.7 得到hd1设备文件的i节点 200
3.1.8 获得hd1设备的设备号 200
3.1.9 释放hd1设备文件的i节点 201
3.2 获取虚拟盘上的挂接点 202
3.3 得到hd1设备文件的超级块 202
3.3.1 准备读取hd1设备文件超级块 203
3.3.2 为hd1设备文件的超级块找到存储位置 203
3.3.3 初始化空闲超级块并加锁 203
3.3.4 从硬盘获得hd1设备文件的超级块 204
3.3.5 加载逻辑块位图和i节点位图 205
3.4 将hd1设备文件与mnt目录文件的i节点挂接 206
3.5 小结 207
第4章 文件操作 208
4.1 打开文件 211
4.1.1 用户程序调用open库函数产生软中断 212
4.1.2 建立用户进程与文件管理表的关系 213
4.1.3 从硬盘上获取helloc.txt文件的i节点 214
4.1.4 将helloc.txt文件与文件管理表相挂接 226
4.2 读文件 227
4.2.1 为按照用户要求读入文件做准备 228
4.2.2 确定要读入的数据块的位置 230
4.2.3 将指定的数据块从硬盘读入到高速缓冲块 233
4.2.4 将数据拷贝到用户指定的内存 234
4.3 新建文件 237
4.3.1 查找路径“/mnt/user/hello.txt” 238
4.3.2 为hello.txt文件新建一个i节点 240
4.3.3 为hello.txt文件新建目录项 242
4.3.4 完成hello.txt新建操作并返回给用户进程 245
4.4 写文件 246
4.4.1 文件写入前的准备工作 248
4.4.2 确定hello.txt文件的写入位置 249
4.4.3 为数据的写入申请缓冲块 252
4.4.4 将指定的写入数据从用户数据区拷贝到缓冲块 253
4.4.5 数据同步到硬盘的方法1 255
4.4.6 将文件写入硬盘的情况2 257
4.5 修改文件 260
4.5.1 对文件的当前操作指针进行重定位 261
4.5.2 对文件进行修改 261
4.6 关闭文件 263
4.6.1 当前进程与文件管理表“脱钩” 264
4.6.2 将文件管理表中hello.txt对应的引用次数减1 265
4.6.3 hello.txt文件与文件管理表“脱钩” 266
4.7 删除文件 268
4.7.1 系统准备删除hello.txt文件 268
4.7.2 删除hello.txt文件在硬盘上对应的数据和i节点 270
4.7.3 对hello.txt文件所在的user目录做处理 275
4.8 本章小结 275
第5章 用户进程与内存管理 277
5.1 用户进程的创建 277
5.1.1 为创建进程str1准备条件 277
5.1.2 为str1进程管理结构找到存储空间 279
5.1.3 复制str1进程管理结构 281
5.1.4 确定str1进程在线性空间中的位置 282
5.1.5 复制str1进程页表并设置其对应的页目录项 283
5.1.6 调整str1进程中与文件相关的结构 285
5.1.7 建立str1进程与全局描述符表GDT的关联 286
5.1.8 将str1进程设为就绪态 287
5.2 为用户进程str1的加载做准备 288
5.2.1 为str1进程加载自身对应的程序做准备 288
5.2.2 读取str1可执行文件的i节点并统计参数和环境变量 289
5.2.3 读取str1可执行文件的文件头 290
5.2.4 对str1可执行程序文件头进行分析 291
5.2.5 拷贝str1可执行程序的参数和环境变量 292
5.2.6 调整str1进程管理结构中可执行程序对应的i节点 292
5.2.7 继续调整str1进程管理结构——文件和信号相关的字段 293
5.2.8 释放str1进程的页表 294
5.2.9 重新设置str1的程序代码段和数据段 295
5.2.10 创建环境变量和参数指针表 296
5.2.11 继续根据str1可执行程序情况调整str1进程管理结构 297
5.2.12 设置str1可执行程序的栈指针和eip值 297
5.3 对缺页中断的处理 298
5.3.1 产生缺页中断并由操作系统响应 298
5.3.2 为str1程序申请一个内存页面 299
5.3.3 将str1程序加载到新分配的页面中 300
5.3.4 检测是否需要对页面剩余空间清0 300
5.3.5 将str1程序占用的物理内存地址与str1进程的线性地址空间对应 301
5.3.6 不断通过缺页中断加载str1程序的全部内容 301
5.3.7 str1程序需要压栈 302
5.3.8 str1程序第一次调用foo程序压栈 302
5.3.9 str1程序第二次压栈,产生缺页中断 302
5.3.10 处理str1程序第二次压栈产生的缺页中断 302
5.3.11 str1程序继续执行,反复压栈并产生缺页中断 303
5.3.12 str1程序运行结束后清栈 303
5.4 str1用户进程的退出 305
5.4.1 str1进程准备退出 305
5.4.2 释放str1程序所占页面 305
5.4.3 解除str1程序与文件有关的内容并给父进程发信号 306
5.4.4 str1程序退出后执行进程调度 307
5.5 多个用户进程“同时”运行 308
5.5.1 依次创建str1、str2和str3进程 308
5.5.2 str1进程压栈的执行效果 309
5.5.3 str1运行过程中产生时钟中断并切换到str2执行 309
5.5.4 str2执行过程遇到时钟中断切换到str3执行 310
5.5.5 三个程序执行一段时间后在主内存的分布格局 311
5.6 进程的调度与切换 311
5.6.1 str1刚被shell创建并处于就绪态 311
5.6.2 shell进程将自己挂起,然后准备切换到str1执行 311
5.6.3 准备切换到str1进程执行 312
5.6.4 str1执行时发生时钟中断 314
5.6.5 时钟中断递减str1运行的时间片 315
5.6.6 str1执行一段时间后挂起,shell进程新建str2进程 315
5.6.7 str2运行期间发生时钟中断 316
5.6.8 系统切换到str1程序执行 317
5.7 内核的分页 318
5.7.1 为设置内核的页目录表和页表做准备——所占空间清0 318
5.7.2 设置内核对应的页目录项和页表项的内容 319
5.7.3 设置内核对应的全局描述符表GDT 320
5.8 页写保护 321
5.8.1 进程A和进程B共享页面 321
5.8.2 进程A准备进行压栈操作 322
5.8.3 进程A的压栈动作引发页写保护 322
5.8.4 将进程A的页表指向新申请的页面 323
5.8.5 拷贝原页面内容到进程A新申请的页面 324
5.8.6 进程B准备操作共享页面 325
5.8.7 假设进程B先执行压栈操作的情况 325
5.9 小结 326
第6章 多个进程“同时”操作一个文件 327
6.1 三个进程操作同一个文件 327
6.1.1 进程A执行,hello.txt文件被打开 328
6.1.2 进程A读取hello.txt文件并由于等待硬盘中断而被系统挂起 328
6.1.3 进程B准备打开hello.txt文件 330
6.1.4 系统准备为进程B获取hello.txt文件的i节点 332
6.1.5 系统找到hello.txt文件已经载入的i节点 333
6.1.6 系统准备为进程B从硬盘上读取hello.txt文件 334
6.1.7 系统找到了正在操作的缓冲块,将进程B挂起 335
6.1.8 系统再次切换到进程0执行 337
6.1.9 进程C启动并打开hello.txt文件 337
6.1.10 进程C也由于等待缓冲块解锁而被系统挂起 338
6.1.11 缓冲块解锁后先唤醒进程C 339
6.1.12 系统将进程B设为就绪状态 340
6.1.13 系统将指定数据写入缓冲块 341
6.1.14 写入完成后,进程C继续执行 341
6.1.15 进程C准备切换到进程B 342
6.1.16 进程C切换到进程B执行,进程B唤醒进程A 342
6.1.17 进程B不断执行,直到时间片减为0后切换到进程A执行 343
6.1.18 进程A、B、C退出,写入数据由update进程同步 344
6.2 缓冲区与外设的数据同步 344
6.2.1 系统不断为进程A向缓冲区写入数据 346
6.2.2 继续执行引发缓冲块数据需要同步 346
6.2.3 将缓冲区中的数据同步到硬盘上 347
6.2.4 进程A由于等待空闲请求项而被系统挂起 349
6.2.5 进程B开始执行 350
6.2.6 进程B也被挂起 351
6.2.7 进程C开始执行并随后被挂起 352
6.2.8 进程A和进程C均被唤醒 352
6.2.9 进程B切换到进程A执行 354
6.3 小结 356
第7章 IPC问题 358
7.1 管道机制 358
7.1.1 为管道文件在文件管理表中申请空闲项 360
7.1.2 为管道文件与进程建立联系创造条件 360
7.1.3 创建管道文件i节点 361
7.1.4 将管道文件i节点与文件管理表建立联系 362
7.1.5 将管道文件句柄返回给用户进程 363
7.1.6 读管道进程开始操作管道文件 363
7.1.7 写管道进程向管道中写入数据 364
7.1.8 写管道进程继续向管道写入数据 366
7.1.9 写管道进程已将管道空间写满 366
7.1.10 写管道进程挂起 366
7.1.11 读管道进程从管道中读出数据 367
7.1.12 读管道进程继续执行,不断从管道中读出数据 369
7.1.13 读管道进程执行中发生时钟中断 369
7.1.14 读管道进程执行过程中再次发生时钟中断 370
7.1.15 读管道进程切换到写管道进程执行 371
7.1.16 写管道进程挂起切换到读管道进程执行 371
7.1.17 读管道进程继续执行,直到把管道中的数据读完 372
7.1.18 读取完成后,读进程挂起,写进程继续执行 373
7.2 信号机制 374
7.2.1 processig进程开始执行 376
7.2.2 processig进程进入可中断等待状态 377
7.2.3 sendsig进程开始执行并向processig进程发信号 379
7.2.4 系统检测当前进程接收到信号并准备处理 381
7.2.5 系统检测信号处理函数指针挂接是否正常 382
7.2.6 调整processig进程的内核栈结构,使之先执行信号处理函数 383
7.2.7 信号对进程执行状态的影响 386
7.3 小结 393
第8章 操作系统的设计指导思想 395
8.1 运行一个最简单的程序,看操作系统为程序运行做了哪些工作 395
8.2 操作系统的设计指导思想——主奴机制 398
8.2.1 主奴机制中的进程及进程创建机制 399
8.2.2 操作系统在内存管理中的主奴机制 400
8.2.3 操作系统在文件系统中体现的主奴机制 401
8.3 实现主奴机制的三种关键技术 402
8.3.1 保护和分页 402
8.3.2 特权级 405
8.3.3 中断 405
8.4 建立主奴机制的决定性因素——先机 407
8.5 软件和硬件的关系:主机与进程、外设与文件 408
8.5.1 非用户进程——进程0、进程1、shell进程 408
8.5.2 文件与数据存储 409
8.6 父子进程共享页面 414
8.7 操作系统的全局中断与进程的局部中断——信号 414
8.8 小结 415
结束语 415
“新设计团队”简介 416
附录 搭建Linux0.11系统环境 421