前言 操作系统在计算机系统中处于承上启下的重要地位,它对下管理计算机的硬件资源,对上服务应用程序和用户。阅读内核源码是学习操作系统原理及实现和理解计算机系统的重要途径,但实际的操作系统太过庞大,以致让人无法窥其全貌,例如2021年4月发布的Linux内核版本5.10稳定版已经达到了约3000万行源码的规模。 小巧的UNIX早期版本UNIX V6曾经是MIT等众多高校操作系统课程源码研读的首选,而且Linux、iOS和Android都基于UNIX V6,通过研读UNIX V6源码可以更深入理解UNIX、Linux等操作系统内核的基本概念及实现原理。 但UNIX V6基于的PDP-11硬件平台早已被淘汰,而UNIX V6部分汇编代码直接使用了PDP-11指令;UNIX V6所用的C语言也是最早期的版本;而且UNIX V6部分代码略显粗糙,这些因素给学习者造成了极大障碍。因此,2006年MIT基于Intel 的32位x86处理器用标准C语言重新实现了UNIX V6并命名为UNIX xv6,简称xv6。于2018年9月发布的xv6最终修订版rev11总共只有9300多行,xv6沿袭了UNIX V6的基本架构并对其粗糙的地方进行了改进。xv6及其变种目前被麻省理工学院(MIT)、耶鲁大学、清华大学、北京航空航天大学和哈尔滨工业大学等众多高校选为操作系统教学和实验平台。 《UNIX xv6内核源码深入剖析》结合源码深度剖析xv6如何在Intel的32位x86架构上实现UNIX V6操作系统,配套源码读者可以扫描下方二维码获取,《UNIX xv6内核源码深入剖析》涉及的思想和概念可以为Linux、iOS、Android乃至嵌入式系统的开发人员理解操作系统底层原理提供一条便捷之道。 源码 考虑到部分读者对如何学习操作系统及为何研究xv6源码存在疑问,因此《UNIX xv6内核源码深入剖析》先阐述操作系统的学习之道,然后再解释xv6为何适合作为打开操作系统内核的钥匙,最后给出《UNIX xv6内核源码深入剖析》的结构。 1. 操作系统的学习之道 操作系统的学习有以下4个循序渐进的途径和层次。 1)读原著 首先读一本经典的操作系统书籍,如Tanenbaum的《操作系统:设计与实现(第3版)》《现代操作系统》或者Silberschatz的《操作系统概念》,以对操作系统的基本概念(如进程管理、内存管理、文件系统和I/O管理)有基本的理解;此外还可动手编写一些程序来调用操作系统核心API,实现进程管理、内存分配和文件创建等功能。 如果对计算机系统基本原理不太熟悉,《深入理解计算机系统》可帮助读者对计算机系统有全面且深入的认识;学习操作系统需要理解CPU的6个重要机制:寄存器、多级缓存、分段、分页、中断以及多核同步,读者可参阅计算机组成原理方面的书籍,如David A. Patterson的《计算机组成与设计》;对于x86处理器的技术细节,Intel的开发手册Software Developer Manuals for Intel? 64 and IA-32 Architectures(简称Intel SDM)是权威的参考资料,但Intel SDM近5000页的体量过于庞大,所以更适合作为工具书查阅。 2)探源码 只了解操作系统的一些概念对于学习操作系统来说还只能算是纸上谈兵,如同医生要学习人体解剖学,计算机相关专业的从业者应该“解剖”一个操作系统。源码面前了无秘密,探究内核源码是剖析操作系统的最佳途径,研读内核源码会让读者对计算机系统从硬件到操作系统原理及实现有一个清晰完整的理解。另外,一些操作系统内核源码堪称大师杰作,是学习编程的典范;很多操作系统内核如UNIX、Linux等都是用C语言编写的,因此内核源码也是程序员学习C语言的优秀范本,C语言的指针、结构体和宏等高级特性在操作系统内核源码中体现得淋漓尽致。 研读源码经常涉及函数的调用与实现、变量和类型的定义,常常在源码之间来回跳转,而且对于一些很隐晦的部分如函数指针,只有具体分析上下文才能确定它关联到哪个函数,因此需要一个专业工具来阅读源码,Source Insight是阅读源码的利器,Visual Studio Code也是不错的选择。 3)改源码 对源码研习到一定阶段,读者可尝试修改操作系统内核源码。首先可以尝试在虚拟机上编译、运行并调试内核,让源码“活”起来;然后找到自己关注的模块动手修改,例如可以修改调度算法,实现内存映射、设备驱动、文件系统或者某个用户命令(如ls)等。 4)做原型 如果到第三个层次仍有余力,读者不妨尝试从零开始编写一个简单的操作系统内核。计算机界的大师如UNIX的作者Ken、Linux的作者Linus以及Minix的作者Andrew Stuart Tanenbaum就是这样做的。为实现操作系统原型,读者可参考于渊的《Orange’s 一个操作系统的实现》、川合秀实的《30天自制操作系统》以及田宇的《一个64位操作系统的设计与实现》。 2. 选择xv6源码的原因 研读操作系统源码可帮助读者真正理解操作系统的原理及实现技术,但实际的操作系统内核往往太过庞大。源码只有1万多行的UNIX V6是现代操作系统的鼻祖,UNIX V6曾经是众多高校操作系统课程研习内核源码的首选。 《UNIX xv6内核源码深入剖析》选择xv6的原因如下。 1)xv6基于UNIX V6 Linux、Minix、BSD、iOS和Android等众多现代操作系统都是在UNIX V6的基础上发展而来的,xv6也基于UNIX V6。xv6 基本沿袭UNIX V6的结构和风格,并对其粗糙的地方进行了改进,还增加了对多处理器的支持。 2)xv6基于Intel 的32位架构 UNIX V6基于古老的PDP-11系统, MIT将xv6移植到了Intel的32位x86架构,该架构支持多任务、虚拟内存和多核等现代处理器的基本特征。当代的计算机专业人员对x86架构更为熟悉,研读xv6源码时无须再去完成对PDP-11的“考古”工作。 3)xv6基于ANSI C C语言经过多年的发展形成了标准化的ANSI C版本,ANSI C被众多编译器支持,ANSI C与UNIX V6使用的早期C语言版本已经有很大差别;xv6采用ANSI C来书写,为阅读、修改、编译和调试源码带来了极大方便。 4)xv6足够精干 xv6内核只有约8800行C语言代码、350行汇编语言代码、100行链接脚本和50行Perl脚本,但麻雀虽小五脏俱全,实现了包含进程管理、内存管理、完整的文件系统以及键盘、显示器和IDE硬盘等I/O设备管理、多核支持以及一个简单的Shell。此外还实现了mkfs、cat、grep和ls等命令。 5)xv6足够典型 读者进一步阅读Linux内核源码将会发现,xv6与现代操作系统如Linux无论是在设计思想上还是在启动、内存空间管理、中断、进程管理等功能实现上都已经足够相似。 6)xv6为学习而生 MIT开发xv6的初衷就是为了操作系统的学习,其设计简洁而优美,通过研读xv6,读者更容易进入Linux等操作系统的内核。 3. 《UNIX xv6内核源码深入剖析》的结构 《UNIX xv6内核源码深入剖析》共16章。 第1章是xv6 的整体概述,简要介绍xv6的前身UNIX、xv6的诞生及源码和文档。 第2章介绍xv6操作系统的整体结构,主要包括xv6的体系结构、进程管理、内存管理、设备驱动与文件系统,以及系统调用与API。 第3章介绍xv6操作系统使用的C语言高级特性和AT&T汇编语言与内联汇编、编译与链接工具,以及调试工具和运行环境。 第4章简要介绍x86体系32位计算机的组成原理,包括CPU、内存、外设、中断系统、I/O端口、I/O接口控制器与外设。 第5章介绍x86体系32位计算机的实模式与保护模式、分段管理与分页管理。 第6章介绍xv6的引导、内核进入与初始化过程。 第7章介绍xv6的虚拟空间管理,包括虚拟空间布局与映射、空间分配与释放以及进程内核空间与用户空间管理。 第8章介绍xv6的中断处理机制、系统调用和设备驱动,包括中断系统初始化、中断处理过程、系统调用与驱动程序以及中断过程的堆栈。 第9章介绍自旋锁、睡眠锁与内核死锁。 第10章介绍进程管理,包括进程的概念、进程调度与切换和进程生命周期的主要函数。 第11章介绍文件系统的I/O 处理、磁盘块缓冲与日志、块分配、i节点与目录管理。 第12章介绍文件描述符与文件系统调用。 第13章介绍exec()函数、管道以及基本的字符串处理函数。 第14章介绍多处理器的系统架构、数据结构和硬件。 第15章介绍键盘、串口和控制台等字符设备的驱动。 第16章介绍用户进程初始化、接口函数和Shell。 xv6的整体结构和《UNIX xv6内核源码深入剖析》各章之间的对应关系如图0.1所示。 图0.1 xv6的整体结构和《UNIX xv6内核源码深入剖析》各章之间的对应关系 由于编者水平有限,书中不当之处在所难免,欢迎广大同行和读者批评指正。 高联雄 2022年7月