本书在详细分析操作系统原理的基础上,用丰富的实例代码,一步一步地指导读者用C语言和汇编语言编写出一个具备操作系统基本功能的操作系统框架。本书不同于其他的理论型书籍,而是提供给读者一个动手实践的路线图。书中讲解了大量在开发操作系统中需注意的细节问题,这些细节不仅能使读者更深刻地认识操作系统的核心原理,而且使整个开发过程少走弯路。全书共分7章。\r\n 本书适合各类程序员、程序开发爱好者阅读,也可作为高等院校操作系统课程的实践参考书。
第1章 马上动手写一个最小的“操作系统”1\r\n1.1 准备工作1\r\n1.2 10分钟完成的操作系统1\r\n1.3 Boot Sector3\r\n1.4 代码解释3\r\n1.5 水面下的冰山5\r\n1.6 回顾6\r\n第2章 搭建你的工作环境7\r\n2.1 虚拟计算机(Virtual PC)7\r\n2.1.1 Virtual PC初体验8\r\n2.1.2 创建你的第一个Virtual PC9\r\n2.1.3 虚拟软盘研究12\r\n2.1.4 虚拟软盘实战14\r\n2.2 编译器(NASM & GCC)18\r\n2.3 安装虚拟Linux19\r\n2.4 在虚拟Linux上访问Windows文件夹26\r\n2.5 安装虚拟PCDOS26\r\n2.6 其他要素29\r\n2.7 Bochs29\r\n2.7.1 Bochs vs. Virtual PC vs. VMware30\r\n2.7.2 Bochs的使用方法31\r\n2.7.3 用Bochs进行调试33\r\n2.7.4 在Linux上开发34\r\n2.8 总结与回顾36\r\n第3章 保护模式(Protect Mode)37\r\n3.1 认识保护模式37\r\n3.1.1 GDT(Global Descriptor Table) 42\r\n3.1.2 实模式到保护模式,不一般的jmp45\r\n3.1.3 描述符属性47\r\n3.2 保护模式进阶50\r\n3.2.1 海阔凭鱼跃50\r\n3.2.2 LDT(Local Descriptor Table)58\r\n3.2.3 特权级62\r\n3.3 页式存储82\r\n3.3.1 分页机制概述83\r\n3.3.2 编写代码启动分页机制84\r\n3.3.3 PDE和PTE85\r\n3.3.4 cr388\r\n3.3.5 回头看代码88\r\n3.3.6 克勤克俭用内存90\r\n3.3.7 进一步体会分页机制100\r\n3.4 中断和异常107\r\n3.4.1 中断和异常机制109\r\n3.4.2 外部中断111\r\n3.4.3 编程操作8259A113\r\n3.4.4 建立IDT116\r\n3.4.5 实现一个中断117\r\n3.4.6 时钟中断试验119\r\n3.4.7 几点额外说明121\r\n3.5 保护模式下的I/O122\r\n3.5.1 IOPL122\r\n3.5.2 I/O许可位图(I/O Permission Bitmap)123\r\n3.6 保护模式小结123\r\n第4章 让操作系统走进保护模式125\r\n4.1 突破512字节的限制125\r\n4.1.1 FAT12126\r\n4.1.2 DOS可以识别的引导盘131\r\n4.1.3 一个最简单的Loader132\r\n4.1.4 加载Loader入内存133\r\n4.1.5 向Loader交出控制权142\r\n4.1.6 整理boot.asm142\r\n4.2 保护模式下的“操作系统”144\r\n第5章 内核雏形146\r\n5.1 用NASM在Linux下写Hello World146\r\n5.2 再进一步,汇编和C同步使用148\r\n5.3 ELF(Executable and Linkable Format)150\r\n5.4 从Loader到内核155\r\n5.4.1 用Loader加载ELF155\r\n5.4.2 跳入保护模式161\r\n5.4.3 重新放置内核170\r\n5.4.4 向内核交出控制权175\r\n5.4.5 操作系统的调试方法176\r\n5.5 扩充内核184\r\n5.5.1 切换堆栈和GDT184\r\n5.5.2 整理我们的文件夹191\r\n5.5.3 Makefile191\r\n5.5.4 添加中断处理200\r\n5.5.5 两点说明218\r\n5.6 小结219\r\n第6章 进程221\r\n6.1 迟到的进程221\r\n6.2 概述222\r\n6.2.1 进程介绍222\r\n6.2.2 未雨绸缪——形成进程的必要考虑222\r\n6.2.3 参考的代码224\r\n6.3 最简单的进程224\r\n6.3.1 简单进程的关键技术预测225\r\n6.3.2 第一步——ring0→ring1227\r\n6.3.3 第二步——丰富中断处理程序243\r\n6.3.4 进程体设计技巧254\r\n6.4 多进程256\r\n6.4.1 添加一个进程体256\r\n6.4.2 相关的变量和宏257\r\n6.4.3 进程表初始化代码扩充258\r\n6.4.4 LDT260\r\n6.4.5 修改中断处理程序261\r\n6.4.6 添加一个任务的步骤总结263\r\n6.4.7 号外:Minix的中断处理265\r\n6.4.8 代码回顾与整理269\r\n6.5 系统调用280\r\n6.5.1 实现一个简单的系统调用280\r\n6.5.2 get_ticks的应用286\r\n6.6 进程调度292\r\n6.6.1 避免对称——进程的节奏感292\r\n6.6.2 优先级调度总结300\r\n第7章 输入/输出系统302\r\n7.1 键盘302\r\n7.1.1 从中断开始——键盘初体验302\r\n7.1.2 AT、PS/2键盘304\r\n7.1.3 键盘敲击的过程304\r\n7.1.4 解析扫描码309\r\n7.2 显示器325\r\n7.2.1 初识TTY325\r\n7.2.2 基本概念326\r\n7.2.3 寄存器328\r\n7.3 TTY任务332\r\n7.3.1 TTY任务框架的搭建334\r\n7.3.2 多控制台340\r\n7.3.3 完善键盘处理346\r\n7.3.4 TTY任务总结354\r\n7.4 区分任务和用户进程354\r\n7.5 printf357\r\n7.5.1 为进程指定TTY357\r\n7.5.2 printf()的实现358\r\n7.5.3 系统调用write()361\r\n7.5.4 使用printf()363\r\n后记366\r\n参考文献369\r\n附录书中的章节和代码对照表370
你是否有过这样的经历,有一天你兴致勃勃买来一堆菜谱想学厨艺,翻开之后却发现自己根本没见过那些材料的名字,也不知道什么叫文火什么叫武火,什么叫上浆什么叫勾芡。而菜谱里根本没告诉你!你扔掉菜谱,垂头丧气,从此对厨艺失去兴趣。
你也可能会有这样的经历,当你在计算机课上学完了一堆C语言语法,想要大展身手实践一番的时候,突然发现你居然不知道源代码应该敲到哪里,是Word还是NotePad?
很多计算机自学者可能有过这样的经历,由于不知道如何跟踪调试,在辛辛苦苦编写的程序得不出正确的结果时,要么束手无策,要么用打印语句输出很多东西,费时费力,而教科书根本没教你这些操作的细节。
有可能在这些教科书作者的眼里,操作的细节不属于课程的一部分,或者这些细节看上去太容易,根本不值一提,甚至作者认为这些属于所谓“经验”的一部分,约定俗成是由学习者本人去摸索出来的。但是实际情况恰恰是,这些书中忽略掉的内容可能占去了一个初学者大部分的时间,甚至因此影响了学习的热情。
学C语言是很容易找到老师的,你会被详细地告知IDE是什么,以及如何使用。但是学习操作系统呢?你会发现绝大多数操作系统书籍都只讲原理,讲各种各样的算法和策略。如果是为了考试,你将内容背下来,最后可能得一个高分;如果是出于兴趣,怕是读了没几页就感到索然无味了。你或许的确能找到极少数的书籍告诉你怎样去写,比如Andrew S. Tanenbaum和Albert S. Woodhull的《操作系统:设计与实现》,但是两位先生还是没能告诉你从哪里开始。你还是不得不在一开始的时候在浩瀚的因特网上搜索一个BootSector的写法。
你或许听说过张五常,他为了研究经济学问题亲自跑到大街上去卖橘子,后来写成了著名的《卖橘者言》,成为了实证经济学的典范。他没有仅仅躲在房子里研究,因为他相信通过实践得来的经验才最可靠、最深刻的。我想他真的是一个喜欢追根究底的人。
你可能也喜欢探求问题的本质,想了解事情的各个细节。面对神奇的计算机世界,很想知道为什么打开电源,电脑屏幕上就能出现这样色彩斑斓的图像,很想知道操作系统理论书籍中讲到的进程管理到底怎样实现,很想知道DOS和Windows到底有什么本质上的区别,想知道怎样才能像那些伟大的黑客一样参与修改Linux的源代码。是的,我就是这样一个喜欢探求本质的人,对这一切怀有极大的兴趣,于是我想写一个自己的操作系统,因为我知道只有通过自己动手,才能对它有真正深刻的了解。经过一段时间的努力,我终于完成了一个雏形。回头想想,很庆幸自己能克服困难走了过来。同时,我在网上了解到还有很多朋友也在写自己的操作系统,也遇到了许多困难。为了跟大家分享其中的经验,让后来者不至于走同样的弯路,我把自己的开发过程记录下来,希望能为初学者们做参考。
本书有幸得到国内操作系统方面的研究权威、上海交通大学尤晋元教授的审校和指点,在此我要表示最真心的敬意和最诚挚的感谢!
在本书的写作过程中,我也有幸得到了许多人的帮助。在我遇到一些未曾预料的困难和变故时,得到了电子工业出版社的张毅编辑以及《程序员》杂志社的孟岩先生的理解、宽容和支持,在这里,我要对你们表示衷心的感谢!
我同样想把感谢献给朱风明、郝慎水、包立光、李雷、郭洪桥和张璐。在整个过程中,你们都在方法上、精神上和物质上给予我巨大而无私的帮助。没有你们的付出,我不可能完成这项工作。
我还要感谢我的家人,爷爷、爸爸和妈妈,你们的爱和关怀是本书得以完成的保障。
要列出所有帮助过我的人的名字是不可能的,因为有些困难是通过因特网解决的,我甚至不知道他们的名字。在此,谨向他们一并表示感谢!
最后,以下面四句诗与读者共勉:
在你立足处深挖下去,
就会有泉水涌出!
别管蒙昧者们叫嚷:
“下面永远是地狱!”
——尼采
于渊