猜你喜欢
穿越操作系统迷雾

穿越操作系统迷雾

书籍作者:王柏生 ISBN:9787111732884
书籍语言:简体中文 连载状态:全集
电子书格式:pdf,txt,epub,mobi,azw3 下载次数:1532
创建日期:2024-04-20 发布日期:2024-04-20
运行环境:PC/Windows/Linux/Mac/IOS/iPhone/iPad/Kindle/Android/安卓/平板
内容简介

这是一本能指导零计算机基础的读者轻松理解计算机软硬件和操作系统工作原理,从而自己动手从0到1编写出一个操作系统的著作。
作者在操作系统领域深度耕耘20余载,不仅一直奋斗在百度等企业一线,而且一直致力于操作系统的教育和布道,希望能帮助和指导越来越多的人,尤其是青少年,能从学生时代开始学习操作系统,能从底层原理真正理解操作系统,改变我国基础软件受制于人的现状。
本书不仅是作者悟透操作系统本质、厚积薄发的成果,而且是他将复杂的操作系统原理化繁为简、举重若轻,成功指导自己9岁的孩子从0到1编写出一个操作系统的过程的全面复盘和复现。本书驱散了操作系统的迷雾,让操作系统不再神秘和高不可攀,让每一个怀揣操作系统梦的中国人都能理解并实现自己的操作系统。
全书一共14章,逻辑上分为上下两篇。
上篇(第1~5章) 计算机软硬件基础和原理
从计算机如何使用电进行计算开始,首先讲述了电是如何抽象为信息的,处理器是怎样进行运算的,内存是怎样存储信息的,处理器和内存是怎样通过总线连接起来的,处理器是如何访问外设的,之后讲述了这些部件是如何结合起来运行程序的。然后通过使用机器语言编写一个程序,让读者深刻地理解指令和程序。接下来,结合汇编语言讲述了计算机体系结构。最后,从C编译器如何将C语法翻译为汇编语言的角度,聚焦语法后面的本质,让读者彻底地理解C语言,而不再纠结在语言表面的语法。
下篇(第6~14章) 从0到1实现一个操作系统
从系统引导(包含32位和64位)开始讲起,先后实现并阐述了内存管理、进程管理、中断、进程调度、系统调用、进程间通信,最后实现了在显示器上实现字符以及图形输出,并能接收键盘输入。除了直接从应用程序直接访问内核外,还展示了C库等概念,展示了从应用软件到C库、图形库,最后到内核的完整软件栈。

作者简介

王柏生
资深操作系统技术专家,北京市科学技术进步奖一等奖获得者。有20余年操作系统研发经验,现任百度主任架构师,曾就职于中国科学院软件研究所、红旗Linux,一直从事操作系统相关领域的研发工作,在操作系统领域有深厚积累。著有《深度探索Linux系统虚拟化》《深度探索Linux操作系统》等畅销书。

王晟寒
对计算机技术有着浓厚的兴趣,9岁开始跟随爸爸学习编写操作系统,在爸爸的指导下,自己动手完成了本书操作系统的编写。5岁开始学习小提琴,现为学校交响乐团成员。业余时间热爱阅读,喜欢游泳、篮球等体育运动。

编辑推荐
适读人群 :1.以中小学生为主的青少年;2.大学生;3.非计算机科班毕业的工程师;4.计算机技术爱好者

(1)作者背景资深:在百度等企业一线从事操作系统研发20余年,对操作系统有极为深入的理解,是行业里知名的专家。
(2)作者善于布道:一直致力于操作系统的教育和布道,深知学习操作系统的难点和痛点,能将复杂的操作系统知识化繁为简、举重若轻,让学习过程事半功倍。
(3)成功实践复盘:作者指导自己9岁的孩子学习操作系统,并成功从0到1编写出操作系统,本书内容是整个学习过程的深度复盘。
(4)真正零基础,人人学得会:即便你是电信号和二进制都不懂的小学生,你也能跟随本书理解计算机的软硬件和操作系统的工作原理,自己动手编写操作系统。
(5)攻克操作系统难关,筑基中国基础软件:本书希望能帮助越来越多的青少年在学生时代就能掌握正确的学习操作系统的方法,理解操作系统和计算机的本质,从小打牢基础,改变我国基础软件受制于人的现状。

前言

Preface 前  言

为什么要写本书

在做云计算时,某天我突然兴起,探究了一下QEMU的作者,当时非常好奇是什么人能写出这么强大的融合计算机软件和硬件的作品。那是我第一次知道计算机奇才——Fabrice Bellard。除了QEMU, Bellard还开发了大名鼎鼎的被称作音视频领域 “瑞士军刀”的FFmpeg,编写了编译器TinyCC和3D渲染引擎TinyGL。此外,他仅用10个月的时间就实现了一个软基站。Bellard的著名作品不胜枚举。

Bellard的触类旁通能力令人叹为观止,有人说他一个人就可以抵得上一个精英团队,这种能力与他对计算机本质的理解是分不开的。在Andy Gocke和Nick Pizzolato写的关于Bellard的一篇小传中提到,Bellard认为学习计算机最重要的两个方面是研究计算机是如何工作的以及对计算本身的研究。

Bellard放在第一位的就是学习计算机的基本工作原理。Andy Gocke和Nick Pizzolato认为,Bellard自9岁就开始使用类似机器代码的语言编程,后来逐渐扩展到高级语言,这种学习经历使他对计算机原理的理解非常深刻。时至今日,Bellard依然认为有抱负的计算机科学家必须通过学习汇编语言以及计算机硬件来深入理解计算机的工作方式。

要理解计算机是如何工作的,没有什么是比写一个操作系统更好的方式了。通过动手编写操作系统,我们可以深刻地洞悉计算机的运行原理。在深刻理解计算机的运行原理后,在编写程序时,我们的思路将不再局限于使用语法表达逻辑的层面,而是能够站在计算机的角度思考,每写出一行代码,都能清楚每一个变量在内存中是如何分配和存储的,以及在计算机系统的各个部件间是如何流转的,从而理解每一个计算是如何完成的。这不仅对开发操作系统本身有意义,还可以使我们在全栈开发中写出高质量的程序。

回顾我自己的经历,我曾经认为汇编、微机原理等在编程中根本用不到,所以简单地应付考试了之,没有深入理解相关内容。之后我花了大量的时间来学习各种编程语言的语法,但还是常被各种纷繁复杂的“语法糖”绕得晕头转向。直到自己动手写操作系统,因为需要而逼迫自己学习汇编,我才越来越深刻地体会到,如果基础打得好,根本不需要耗费那么多时间去学习那些语法。我们在大好的青春年华中本末倒置地花费了太多时间去学习表面上的东西,花了太多的时间在语言层面兜兜转转,而没有触碰本质。

在这些年的探索过程中,我发现很多计算机领域的著名人物都是很小就开始学习计算机,他们都是在学生时代参透了计算机的本质,在年富力强时开始产出。而我们则更多是在年富力强时才懂得并且开始学习,虽然也很勤奋努力,但事实上起步晚了若干年。虽然我们现在也开始提倡青少年学习编程,但是基本还是在学习语言,而不是学习深层次的计算机工作原理。

于是,在我自己的孩子过了9岁时,我就开始让他接触计算机,首先让他从了解计算机的基本原理开始,然后学习汇编语言和高级语言,最后带着他动手写操作系统。我希望他在学习知识的黄金时期,能正向地学习计算机,悟透计算机的本质,而不要再重复我在探索过程中走过的各种弯路,少浪费青春年华。

我们想将这些经验分享给所有学习计算机的人,于是就有了今天这本书。

本书读者对象

少年强则国强,青少年是我国计算机发展的未来。本书刻意兼顾了青少年的知识储备和理解能力,希望能帮助他们深入了解计算本质,而不仅仅是浮在编程表面。

对于正在学习或者准备学习操作系统技术的大学生来说,这本书可以作为操作系统课程的实践教材。他们可以结合书中内容自己动手实现一个完整的操作系统,以对抽象的理论知识有一个感性的认识。这本书也可以作为汇编语言以及C语言的实践教材。

对于软件研发相关的从业人员来说,这本书可以帮助他们深刻地理解计算机和操作系统的原理。无论是应用软件开发人员,还是中间件以及操作系统底层开发人员,要想成为一名合格的程序员,深入学习操作系统技术是必不可少的。

最后,这本书写给所有想了解计算机如何工作以及所有和我一样怀揣操作系统梦的操作系统爱好者,希望这本书能让他们顺利地穿越操作系统迷雾,深刻领悟计算机工作原理。

如何阅读本书

本书从逻辑上可以分为上、下两篇。上篇(第1~5章)首先讲述了计算机的基本原理,从电子计算机如何使用电进行计算开始,讲述了电是如何抽象为信息的,处理器是怎样进行运算的,内存是怎样存储信息的,处理器和内存是如何通过总线通信的,处理器又是如何访问外设的,等等。接着讲述了这些部件是如何结合起来运行程序的。

然后从机器语言开始讲起,通过使用机器语言编写程序,帮助读者深刻理解指令和程序。接着讲述了汇编语言和C语言。第4章结合汇编语言讲述了计算机体系结构。第5章从C编译器如何将C语法翻译为汇编语言的角度入手,聚焦于语法后面的本质,希望能让读者彻底地理解C语言,而不再纠缠在指针等复杂的语法上。

下篇(第6~14章)从0到1实现了一个操作系统。我们从引导开始讲起,然后阐述了内存管理、进程、中断和异常、进程调度、系统调用、进程间通信,最后实现了显示器上的字符和图形输出以及从键盘接收输入。除了从应用程序直接访问内核外,下篇还展示了什么是C库、图形库等,以及从应用程序到C库、图形库,最后到内核的完整软件栈 。

勘误和支持

由于水平有限,加之编写时间仓促,书中难免出现一些错误或者不准确的地方,恳请读者批评指正。


王柏生

2023年5月


目录

前 言

第1章 计算机基础 1

1.1 认识电 1

1.2 信息表示 5

1.2.1 二进制 5

1.2.2 十六进制 6

1.3 计算 7

1.3.1 逻辑运算 8

1.3.2 逻辑门 8

1.3.3 加法器 10

1.4 内存 12

1.4.1 物理实现 12

1.4.2 数学抽象 16

1.5 总线 17

1.6 寄存器 20

1.7 程序 22

1.8 外存 26

1.9 外设及接口 27

1.9.1 I/O地址空间 28

1.9.2 内存映射I/O 29

1.10 地址空间 30

1.11 数学模型到物理世界 31

第2章 认识Linux 34

2.1 什么是操作系统 34

2.2 文件系统 35

2.3 终端 37

2.4 shell 39

2.5 Linux常用命令 40

2.6 ANSI转义序列 43

2.7 编辑器 45

2.8 准备“物理”计算机 47

第3章 机器语言程序设计 49

3.1 程序及指令 49

3.2 补码 50

3.3 ASCII码 52

3.4 串口 53

3.5 “向串口写字符A”的

程序流程 55

3.6 写外设指令 55

3.7 准备源操作数 57

3.8 准备目的操作数 58

3.9 跳转指令 59

3.10 创建程序文件 60

3.11 程序执行过程 61

3.12 使用kvmtool运行程序 69

第4章 汇编语言程序设计 71

4.1 初识汇编语言 71

4.2 段及段寄存器 72

4.3 指令指针寄存器 74

4.4 通用寄存器 75

4.5 标志寄存器 76

4.6 汇编指令格式 78

4.7 第一个汇编程序 78

4.7.1 汇编和链接 79

4.7.2 运行 80

4.7.3 显式设置操作数的

段寄存器 83

4.7.4 伪指令.code16 85

4.8 构建工具Make 85

4.9 操作数寻址 86

4.9.1 立即数寻址 87

4.9.2 直接寻址 88

4.9.3 ModR/M寻址 89

4.9.4 SIB寻址 94

4.9.5 SIB + disp寻址 98

4.10 程序运行流程控制 101

4.10.1 选择 101

4.10.2 循环 102

4.11 栈 103

4.12 函数及x86调用约定 107

4.12.1 call和ret指令 108

4.12.2 栈帧 110

4.12.3 多模块及符号可见性 113

4.12.4 参数传递 114

4.12.5 局部变量 116

4.12.6 返回值及参数清理 118

4.12.7 寄存器保存和恢复 119

4.13 链接 122

4.13.1 目标文件合并 123

4.13.2 符号解析 125

4.13.3 符号的可见性 128

第5章 C语言程序设计 129

5.1 基本语法 130

5.1.1 词法元素 130

5.1.2 表达式 131

5.1.3 声明 132

5.1.4 语句 133

5.1.5 标识符 135

5.1.6 对象的存储类别 138

5.1.7 头文件 138

5.1.8 预处理指令 139

5.2 C语言入口 141

5.3 第一个C程序 142

5.4 从C语言到机器语言 143

5.5 变量 145

5.5.1 变量类型 146

5.5.2 局部变量 147

5.5.3 全局变量 150

5.5.4 全局变量的链接性 151

5.5.5 静态局部变量 152

5.5.6 变量类型转换 154

5.5.7 溢出 155

5.6 运算 157

5.6.1 算术运算 157

5.6.2 递增和递减 158

5.6.3 关系运算 159

5.6.4 逻辑运算 161

5.6.5 位运算 163

5.6.6 赋值运算 164

5.6.7 运算的优先级和结合性 165

5.7 程序运行流程控制 166

5.7.1 选择 166

5.7.2 循环 168

5.8 数组 172

5.9 结构体 175

5.9.1 基本语法 175

5.9.2 内存布局 176

5.9.3 位域 179

5.10 指针 180

5.10.1 基本语法 181

5.10.2 指向结构体的指针 183

5.10.3 指针的+/-运算 185

5.10.4 双指针 186

5.10.5 void指针 188

5.10.6 空指针 189

5.11 函数 189

5.11.1 基本语法 189

5.11.2 参数的值传递和

指针传递 191

5.11.3 const参数 195

5.11.4 函数指针 195

5.12 内联汇编 197

第6章 32位引导过程 200

6.1 实模式 200

6.2 保护模式 201

6.3 内核映像组成及布局 203

6.3.1 实模式地址空间 203

6.3.2 内核映像的布局 205

6.3.3 内核映像文件组织 206

6.4 创建保护模式的段描述符 207

6.4.1 段描述符格式 207

6.4.2 保护模式的内核代码段

描述符 208

6.4.3 保护模式的内核数据段

描述符 210

6.4.4 创建保护模式的段

描述符表 210

6.5 告知处理器段描述符表地址 211

6.6 开启处理器保护模式 212

6.7 跳转到内核保护模式部分 213

6.7.1 准备保护模式部分 213

6.7.2 跳转到保护模式部分 214

6.8 编译及创建内核映像文件 215

6.8.1 编译内核 215

6.8.2 组装内核映像文件 217

6.9 使用Make构建内核 220

第7章 64位引导过程 222

7.1 内存分页 222

7.1.1 为什么要分页 222

7.1.2 分页模式下的地址

翻译过程 224

7.1.3 程序的虚拟地址空间 225

7.1.4 分页模式下的寻址 225

7.1.5 页表 226

7.2 64位模式下程序的虚拟

地址空间 228

7.3 创建64位模式的临时段

描述符表 229

7.3.1 代码段 230

7.3.2 数据段 231

7.3.3 为64位模式创建临时段

描述符表 231

7.4 建立内核映像的虚拟地址到

物理地址的映射 233

7.4.1 建立四级页表映射 234

7.4.2 建立三级页表映射 235

7.4.3 建立二级页表映射 236

7.4.4 建立一级页表映射 239

7.5 建立恒等映射 240

7.6 切入64位模式 244

7.6.1 使能PAE 244

7.6.2 设置CR3指向页表 244

7.6.3 使能64位模式 245

7.6.4 开启分页 245

7.6.5 跳转到64位部分 246

7.7 走进内核64位部分 248

7.7.1 创建64位模式段描述符表 248

7.7.2 转换到内核地址空间 251

7.7.3 构建内核64位部分 254

第8章 内存管理 258

8.1 获取内存信息 258

8.1.1 BIOS简介 258

8.1.2 读取内存信息 260

8.1.3 E820的C数据结构表示 262

8.1.4 计算物理内存大小 263

8.1.5 print的实现 264

8.1.6 使用Make内置函数

提取文件 266

8.1.7 创建Make中的文件

依赖关系 267

8.2 页面管理 269

8.2.1 划分页面 269

8.2.2 为内核映像保留页面 270

8.2.3 分配页面 271

8.2.4 归还页面 272

8.3 映射物理内存 272

8.3.1 线性映射 274

8.3.2 第1阶段映射 275

8.3.3 第2阶段映射 278

8.4 内存块管理 281

8.4.1 块管理数据组织 281

8.4.2 分配内存块 284

8.4.3 释放内存块 289

第9章 进程 292

9.1 程序运行环境 292

9.2 创建应用程序 293

9.3 创建任务结构体 295

9.4 建立进程地址映射 297

9.4.1 内核空间映射 298

9.4.2 用户空间映射 299

9.5 创建进程任务状态段及

内核栈 300

9.5.1 准备任务状态段及内核栈 302

9.5.2 创建任务状态段的

段描述符 304

9.5.3 设置任务寄存器 307

9.6 伪造中断现场 307

9.7 设置CR3指向进程页表 310

9.8 进入用户空间 310

9.9 I/O端口访问权限控制 311

第10章 中断和异常 313

10.1 中断及其处理过程 313

10.1.1 可编程中断控制器

8259A 314

10.1.2 高级可编程中断控制器

APIC 317

10.1.3 MSI 317

10.2 初始化8259A 318

10.3 组织中断描述符表 321

10.3.1 初始化中断描述符表 322

10.3.2 设置中断寄存器 324

10.4 时钟中断 325

10.4.1 时钟中断处理函数 325

10.4.2 设置时钟中断描述符 327

10.4.3 编程时钟芯片8254 327

10.4.4 开启中断 329

10.4.5 现场保存和恢复 329

10.5 缺页异常 334

第11章 进程调度 338

11.1 任务状态 338

11.2 创建进程 339

11.3 空闲任务 341

11.4 任务调度 342

11.5 任务切换 345

第12章 系统调用 349

12.1 系统调用工作机制 349

12.2 内核系统调用入口 351

12.3 设置MSR寄存器 354

12.4 实现系统调用sleep 357

12.5 C库 360

12.6 应用调用sleep挂起 362

第13章 进程间通信 364

13.1 共享内存原理 364

13.2 内核共享内存实现 366

13.3 C库实现共享内存接口 368

13.4 应用使用共享内存通信 368

第14章 显示及输入 370

14.1 图形处理器 370

14.2 文本模式和图形模式 371

14.3 获取模式信息 373

14.4 将framebuffer映射到

用户空间 374

14.5 应用获取模式信息 376

14.6 设计字体 377

14.7 图形库 379

14.8 应用绘制 383

14.9 键盘输入 384


产品特色