资源名称:操作系统真象还原

内容简介:

大学及研究生都有操作系统课程,这类人群具有很高的学术能力,但书中讲的过于抽象与晦涩,以至于很多学生对于此门课程恐惧到都提不出问题,只有会的人才能提出问题。操作系统理论书是无法让读者理解什么是操作系统的,学操作系统不能靠想像,他们需要看到具体的东西。

绝大多数技术人都对操作系统怀着好奇的心,他们渴望一本告诉操作系统到底是什么的书,里面不要掺杂太多无关的管理性的东西,代码量不大且是现代操作系统雏形,他们渴望很快看到本质而不花费大量的时间成本。

作者简介:

郑钢,毕业于北京大学,前百度运维高级工程师,对操作系统有深入的研究。好运动,喜钻研,热衷于尝试前沿技术,乐于分享学习成果。

资源目录:

第0章 一些你可能正感到迷惑的问题1

0.1 操作系统是什么1

0.2 你想研究到什么程度2

0.3 写操作系统,哪些需要我来做2

0.4 软件是如何访问硬件的2

0.5 应用程序是什么,和操作系统是如何

配合到一起的3

0.6 为什么称为“陷入”内核4

0.7 内存访问为什么要分段4

0.8 代码中为什么分为代码段、数据段?

这和内存访问机制中的段是一回事吗6

0.9 物理地址、逻辑地址、有效地址、线性

地址、虚拟地址的区别11

0.10 什么是段重叠12

0.11 什么是平坦模型12

0.12 cs、ds这类sreg段寄存器,位宽是

多少12

0.13 什么是工程,什么是协议13

0.14 为什么Linux系统下的应用程序不能在

Windows系统下运行14

0.15 局部变量和函数参数为什么要放在

栈中14

0.16 为什么说汇编语言比C语言快15

0.17 先有的语言,还是先有的编译器,第1个

编译器是怎么产生的16

0.18 编译型程序与解释型程序的区别19

0.19 什么是大端字节序、小端字节序19

0.20 BIOS中断、DOS中断、Linux中断的

区别21

0.21 Section和Segment的区别25

0.22 什么是魔数29

0.23 操作系统是如何识别文件系统的30

0.24 如何控制CPU的下一条指令30

0.25 指令集、体系结构、微架构、编程

语言30

0.26 库函数是用户进程与内核的桥梁33

0.27 转义字符与ASCII码37

0.28 MBR、EBR、DBR和OBR各是

什么39

第1章 部署工作环境42

1.1 工欲善其事,必先利其器42

1.2 我们需要哪些编译器42

1.2.1 世界顶级编译器GCC42

1.2.2 汇编语言编译器新贵NASM43

1.3 操作系统的宿主环境43

1.3.1 什么是虚拟机44

1.3.2 盗梦空间般的开发环境,虚拟机

中再装一个虚拟机45

1.3.3 virtualBox下载,安装46

1.3.4 Linux发行版下载46

1.3.5 Bochs下载安装46

1.4 配置bochs48

1.5 运行bochs49

第2章 编写MBR主引导记录,让我们开始

掌权52

2.1 计算机的启动过程52

2.2 软件接力第一棒,BIOS52

2.2.1 实模式下的1MB内存布局52

2.2.2 BIOS是如何苏醒的54

2.2.3 为什么是0x7c0056

2.3 让MBR先飞一会儿58

2.3.1 神奇好用的$和$$,令人迷惑的

section58

2.3.2 NASM简单用法60

2.3.3 请下一位选手MBR同学做

准备60

第3章 完善MBR65

3.1 地址、section、vstart浅尝辄止65

3.1.1 什么是地址65

3.1.2 什么是section67

3.1.3 什么是vstart68

3.2 CPU的实模式70

3.2.1 CPU的工作原理71

3.2.2 实模式下的寄存器72

3.2.3 实模式下内存分段由来76

3.2.4 实模式下CPU内存寻址方式78

3.2.5 栈到底是什么玩意儿81

3.2.6 实模式下的ret84

3.2.7 实模式下的call85

3.2.8 实模式下的jmp92

3.2.9 标志寄存器flags97

3.2.10 有条件转移99

3.2.11 实模式小结101

3.3 让我们直接对显示器说点什么吧101

3.3.1 CPU如何与外设通信—IO

接口101

3.3.2 显卡概述105

3.3.3 显存、显卡、显示器106

3.3.4 改进MBR,直接操作显卡110

3.4 bochs调试方法112

3.4.1 bochs一般用法113

3.4.2 bochs调试实例118

3.5 硬盘介绍122

3.5.1 硬盘发展简史122

3.5.2 硬盘工作原理123

3.5.3 硬盘控制器端口126

3.5.4 常用的硬盘操作方法128

3.6 让MBR使用硬盘129

3.6.1 改造MBR130

3.6.2 实现内核加载器134

第4章 保护模式入门136

4.1 保护模式概述136

4.1.1 为什么要有保护模式136

4.1.2 实模式不是32位CPU,变成了

16位137

4.2 初见保护模式137

4.2.1 保护模式之寄存器扩展137

4.2.2 保护模式之寻址扩展140

4.2.3 保护模式之运行模式反转141

4.2.4 保护模式之指令扩展145

4.3 全局描述符表150

4.3.1 段描述符150

4.3.2 全局描述符表GDT、局部描述

符表LDT及选择子155

4.3.3 打开A20地址线157

4.3.4 保护模式的开关,CR0寄存器的

PE位158

4.3.5 让我们进入保护模式158

4.4 处理器微架构简介165

4.4.1 流水线166

4.4.2 乱序执行168

4.4.3 缓存168

4.4.4 分支预测169

4.5 使用远跳转指令清空流水线,更新段描述

符缓冲寄存器172

4.6 保护模式之内存段的保护173

4.6.1 向段寄存器加载选择子时的

保护173

4.6.2 代码段和数据段的保护174

4.6.3 栈段的保护175

第5章 保护模式进阶,向内核迈进177

5.1 获取物理内存容量177

5.1.1 学习Linux获取内存的方法177

5.1.2 利用BIOS中断0x15子功能

0xe820获取内存177

5.1.3 利用BIOS中断0x15子功能

0xe801获取内存179

5.1.4 利用BIOS中断0x15子功能

0x88获取内存180

5.1.5 实战内存容量检测181

5.2 启用内存分页机制,畅游虚拟空间186

5.2.1 内存为什么要分页186

5.2.2 一级页表188

5.2.3 二级页表192

5.2.4 规划页表之操作系统与用户

进程的关系197

5.2.5 启用分页机制198

5.2.6 用虚拟地址访问页表204

5.2.7 快表TLB(Translation Lookaside

Buffer)简介206

5.3 加载内核207

5.3.1 用C语言写内核207

5.3.2 二进制程序的运行方法211

5.3.3 elf格式的二进制文件213

5.3.4 elf文件实例分析218

5.3.5 将内核载入内存222

5.4 特权级深入浅出229

5.4.1 特权级那点事229

5.4.2 TSS简介230

5.4.3 CPL和DPL入门232

5.4.4 门、调用门与RPL序235

5.4.5 调用门的过程保护240

5.4.6 RPL的前世今生243

5.4.7 IO特权级248

第6章 完善内核252

6.1 函数调用约定简介252

6.2 汇编语言和C语言混合编程256

6.2.1 浅析C库函数与系统调用256

6.2.2 汇编语言和C语言共同协作259

6.3 实现自己的打印函数261

6.3.1 显卡的端口控制261

6.3.2 实现单个字符打印265

6.3.3 实现字符串打印275

6.3.4 实现整数打印277

6.4 内联汇编281

6.4.1 什么是内联汇编281

6.4.2 汇编语言AT&T语法简介281

6.4.3 基本内联汇编283

6.4.4 扩展内联汇编284

6.4.5 扩展内联汇编之机器模式简介294

第7章 中断298

7.1 中断是什么,为什么要有中断298

7.2 操作系统是中断驱动的299

7.3 中断分类299

7.3.1 外部中断299

7.3.2 内部中断301

7.4 中断描述符表304

7.4.1 中断处理过程及保护306

7.4.2 中断发生时的压栈308

7.4.3 中断错误码310

7.5 可编程中断控制器8259A311

7.5.1 8259A介绍311

7.5.2 8259A的编程314

7.6 编写中断处理程序319

7.6.1 从最简单的中断处理程序

开始319

7.6.2 改进中断处理程序335

7.6.3 调试实战:处理器进入中断时

压栈出栈完整过程339

7.7 可编程计数器/定时器8253简介346

7.7.1 时钟—给设备打拍子346

7.7.2 8253入门348

7.7.3 8253控制字349

7.7.4 8253工作方式350

7.7.5 8253初始化步骤353

7.8 提高时钟中断的频率,让中断来得更

猛烈一些354

第8章 内存管理系统357

8.1 makefile简介357

8.1.1 makefile是什么357

8.1.2 makefile基本语法358

8.1.3 跳到目标处执行360

8.1.4 伪目标361

8.1.5 make:递归式推导目标362

8.1.6 自定义变量与系统变量363

8.1.7 隐含规则365

8.1.8 自动化变量366

8.1.9 模式规则367

8.2 实现assert断言367

8.2.1 实现开、关中断的函数367

8.2.2 实现ASSERT370

8.2.3 通过makefile来编译372

8.3 实现字符串操作函数374

8.4 位图bitmap及其函数的实现377

8.4.1 位图简介377

8.4.2 位图的定义与实现378

8.5 内存管理系统381

8.5.1 内存池规划381

8.5.2 内存管理系统第一步,分配页

内存388

第9章 线程398

9.1 实现内核线程398

9.1.1 执行流398

9.1.2 线程到底是什么399

9.1.3 进程与线程的关系、区别简述402

9.1.4 进程、线程的状态405

9.1.5 进程的身份证—PCB405

9.1.6 实现线程的两种方式—内核或

用户进程406

9.2 在内核空间实现线程409

9.2.1 简单的PCB及线程栈的实现409

9.2.2 线程的实现413

9.3 核心数据结构,双向链表417

9.4 多线程调度421

9.4.1 简单优先级调度的基础421

9.4.2 任务调度器和任务切换425

第10章 输入输出系统439

10.1 同步机制——锁439

10.1.1 排查GP异常,理解原子操作439

10.1.2 找出代码中的临界区、互斥、

竞争条件444

10.1.3 信号量445

10.1.4 线程的阻塞与唤醒447

10.1.5 锁的实现449

10.2 用锁实现终端输出452

10.3 从键盘获取输入456

10.3.1 键盘输入原理简介456

10.3.2 键盘扫描码457

10.3.3 8042简介463

10.3.4 测试键盘中断处理程序465

10.4 编写键盘驱动468

10.4.1 转义字符介绍468

10.4.2 处理扫描码469

10.5 环形输入缓冲区476

10.5.1 生产者与消费者问题简述476

10.5.2 环形缓冲区的实现478

10.5.3 添加键盘输入缓冲区481

10.5.4 生产者与消费者实例测试482

第11章 用户进程485

11.1 为什么要有任务状态段TSS485

11.1.1 多任务的起源,很久很久

以前…… 485

11.1.2 LDT简介486

11.1.3 TSS的作用488

11.1.4 CPU原生支持的任务切换

方式492

11.1.5 现代操作系统采用的任务

切换方式495

11.2 定义并初始化TSS497

11.3 实现用户进程501

11.3.1 实现用户进程的原理501

11.3.2 用户进程的虚拟地址空间501

11.3.3 为进程创建页表和3特权

级栈502

11.3.4 进入特权级3505

11.3.5 用户进程创建的流程506

11.3.6 实现用户进程—上507

11.3.7 bss简介513

11.3.8 实现用户进程—下515

11.3.9 让进程跑起来—用户进程的

调度519

11.3.10 测试用户进程520

第12章 进一步完善内核523

12.1 Linux系统调用浅析523

12.2 系统调用的实现527

12.2.1 系统调用实现框架527

12.2.2 增加0x80号中断描述符527

12.2.3 实现系统调用接口528

12.2.4 增加0x80号中断处理例程528

12.2.5 初始化系统调用和实现

sys_getpid530

12.2.6 添加系统调用getpid531

12.2.7 在用户进程中的系统调用532

12.2.8 系统调用之栈传递参数534

12.3 让用户进程“说话”536

12.3.1 可变参数的原理536

12.3.2 实现系统调用write538

12.3.3 实现printf539

12.3.4 完善printf542

12.4 完善堆内存管理545

12.4.1 malloc底层原理545

12.4.2 底层初始化548

12.4.3 实现sys_malloc550

12.4.4 内存的释放555

12.4.5 实现sys_free558

12.4.6 实现系统调用malloc和free562

第13章 编写硬盘驱动程序566

13.1 硬盘及分区表566

13.1.1 创建从盘及获取安装的

磁盘数566

13.1.2 创建磁盘分区表567

13.1.3 磁盘分区表浅析571

13.2 编写硬盘驱动程序578

13.2.1 硬盘初始化578

13.2.2 实现thread_yield和idle线程582

13.2.3 实现简单的休眠函数584

13.2.4 完善硬盘驱动程序585

13.2.5 获取硬盘信息,扫描分区表590

第14章 文件系统595

14.1 文件系统概念简介595

14.1.1 inode、间接块索引表、文件

控制块FCB简介595

14.1.2 目录项与目录简介597

14.1.3 超级块与文件系统布局599

14.2 创建文件系统601

14.2.1 创建超级块、i结点、目录项601

14.2.2 创建文件系统603

14.2.3 挂载分区609

14.3 文件描述符简介612

14.3.1 文件描述符原理612

14.3.2 文件描述符的实现614

14.4 文件操作相关的基础函数615

14.4.1 inode操作有关的函数616

14.4.2 文件相关的函数620

14.4.3 目录相关的函数623

14.4.4 路径解析相关的函数628

14.4.5 实现文件检索功能630

14.5 创建文件633

14.5.1 实现file_create633

14.5.2 实现sys_open636

14.5.3 在文件系统上创建第1个

文件639

14.6 文件的打开与关闭640

14.6.1 文件的打开640

14.6.2 文件的关闭642

14.7 实现文件写入643

14.7.1 实现file_write643

14.7.2 改进sys_write及write系统

调用648

14.7.3 把数据写入文件650

14.8 读取文件651

14.8.1 实现file_read651

14.8.2 实现sys_read与功能验证653

14.9 实现文件读写指针定位功能655

14.10 实现文件删除功能657

14.10.1 回收inode657

14.10.2 删除目录项660

14.10.3 实现sys_unlink与功能验证663

14.11 创建目录665

14.11.1 实现sys_mkdir创建目录666

14.11.2 创建目录功能验证669

14.12 遍历目录671

14.12.1 打开目录和关闭目录671

14.12.2 读取1个目录项673

14.12.3 实现sys_readdir及sys_

rewinddir674

14.13 删除目录676

14.13.1 删除目录与判断空目录676

14.13.2 实现sys_rmdir及功能验证677

14.14 任务的工作目录679

14.14.1 显示当前工作目录的原理及

基础代码679

14.14.2 实现sys_getcwd681

14.14.3 实现sys_chdir改变工作目录683

14.15 获得文件属性684

14.15.1 ls命令的幕后功臣684

14.15.2 实现sys_stat685

第15章 系统交互687

15.1 fork的原理与实现687

15.1.1 什么是fork687

15.1.2 fork的实现689

15.1.3 添加fork系统调用与实现init

进程695

15.2 添加read系统调用,获取键盘输入696

15.3 添加putchar、clear系统调用697

15.4 实现一个简单的shell699

15.4.1 shell雏形699

15.4.2 添加Ctrl+u和Ctrl+l快捷键701

15.4.3 解析键入的字符703

15.4.4 添加系统调用705

15.4.5 路径解析转换708

15.4.6 实现ls、cd、mkdir、ps、rm等

命令712

15.5 加载用户进程717

15.5.1 实现exec717

15.5.2 让shell支持外部命令723

15.5.3 加载硬盘上的用户程序执行724

15.5.4 使用户进程支持参数727

15.6 实现系统调用wait和exit731

15.6.1 wait和exit的作用731

15.6.2 孤儿进程和僵尸进程732

15.6.3 一些基础代码733

15.6.4 实现wait和exit737

15.6.5 实现cat命令741

15.7 管道745

15.7.1 管道的原理745

15.7.2 管道的设计747

15.7.3 管道的实现748

15.7.4 利用管道实现进程间通信752

15.7.5 在shell中支持管道754

参考文献760

资源截图:

操作系统真象还原