从零开始写Linux内核:一书学透核心原理与实现
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

前言

为何要写作本书

作为当今世界上最成功的开源项目之一,Linux内核源码具有巨大的学习价值。学习内核不仅仅能提升编码水平、架构能力,更能全面地了解硬件接口和计算机原理。但是随着Linux内核的功能越来越强大,内核变得越来越复杂,代码量也在急剧地膨胀。这就给刚入门的新手带来了巨大的学习困难。

学习一个复杂的系统有两种常用的方式。

一种是直接扎进系统源码中,按逻辑顺序逐个分析各个模块。但复杂系统的特点是模块之间的关联非常强,相关的数据结构非常庞大,调试环境的搭建也往往比较烦琐。这就使得很多人在开始阶段就困难重重,要想坚持下去,往往需要很大的定力。

另一种是从零开始将系统从简单到复杂地实现一遍。这种学习方式的优点非常明显,入门阶段比较容易,每次新增几十行甚至几行代码就可以实现一个新的功能,整个学习过程是循序渐进的。但对Linux系统来说,从零开始写一遍并不容易。这是因为Linux诞生于1991年,当时Linus Torvalds所使用的很多构建工具现在已经很难找到了,例如ld86等编译工具,有些工具即使找到了也很难运行在现代的操作系统上。

为了解决这个问题,我编写了本书。本书的目标是使用现代的操作系统(例如Ubuntu 20)和编译器(例如GCC7或者GCC9)从零开始实现Linux 0.12的内核代码。在这个过程中,我改写了很多不适用于现代编译器的代码,并且通过链接选项或者链接脚本重现了早期的文件系统和可执行文件格式,让操作系统可以运行在现代的Bochs或者QEMU等仿真软件上。

读者对象

本书面向的人群主要是对操作系统感兴趣的人,尤其是那些想深入学习Linux内核但又不知道该如何入门的人。对于计算机专业的学生而言,本书则是一本非常好的实验指导书,通过一步步地跟随本书实现全部的功能,不仅可以深入地掌握操作系统的基本功能,还可以加深对计算机接口的了解。

如何阅读本书

本书共8章,从逻辑上分为四部分。

第一部分(第1和2章)是基础知识,介绍开发内核所需的基础知识,包括开发环境和调试环境的搭建,以及i386保护模式等。

第二部分(第3~6章)是核心模块,逐步实现进程、中断、系统调用、内存管理、字符设备驱动和块设备驱动等模块。这一部分涉及的也是传统操作系统内核最主要的模块,这些模块之间相互依赖,彼此联系,实现起来难度很大。在写这一部分的时候,我花了很多心思进行构思,自始至终坚持每次只实现一个小功能,这样阅读的难度就不大了。

第三部分(第7章)是文件系统。Linux 0.12沿用了Minix这一早期的文件系统,早期的文件系统所支持的文件大小、磁盘大小都不算大,数据结构相对比较简单。这一部分篇幅虽然不小,但是难度并不大,因为这一部分几乎不涉及硬件操作,相比前面的章节,文件系统实现起来没有那么烦琐。Linux 0.12的文件系统虽然相对简单,但是它的超级块、inode等设计却被一直沿用下来,文件系统中的mount、unmount等系统调用,以及将管道、字符设备都抽象成文件的设计也一直沿用至今。现代Linux的VFS(Virtual File System,虚拟文件系统)的设计哲学是“一切皆文件”,这种设计思想在早期的文件系统中已经初见端倪。相比现代文件系统的完备和庞大,学习早期的文件系统无疑要简单很多。

在文件系统中还有一个非常重要的话题,那就是如何加载运行一个可执行程序。在现代操作系统中,可执行程序的文件格式是ELF,但在Linux 1.0版本之前,则主要使用a.out格式。a.out格式是一种古老但非常简单的二进制文件格式,它只有代码段和数据段,而代码会被加载到进程空间的0地址处,所以它的加载过程非常简单。ELF文件是由专门的加载器(也称为loader,在Linux上主要就是ld.so)加载运行的,而a.out则由内核直接实现。鉴于此,我们采用Minix文件系统和a.out格式。

在这三个主要部分之外,本书第四部分(第8章)实现了一些重要的系统服务接口,例如用于管理系统时间的一大类函数,用于管理输入/输出的ioctl等,这一部分的篇幅不算大,不是内核的主要部分,但为了让shell程序正确地运行,这些函数也是必须要实现的。

本书是一本非常偏重实践的书,实践性远强于理论性。跟随本书可以一步步地实现一个完整的操作系统,学习曲线非常平缓,这对新手非常友好。但这样的安排也会带来一个问题:本书不适宜段落式地阅读和学习,因为后面的很多功能都依赖于前面的实现。当然,如果你完全掌握了本书的内容,再回头阅读本书的代码,完全可以根据自己的喜好重新安排进程,那时就不必遵循本书的章节顺序了。等到那个时候,读者也完全有能力沿着Linux的主线代码继续深入学习,如进一步支持图形界面、网络等功能。

勘误与支持

由于水平有限,编写时间仓促,书中难免会出现一些错误或者不准确的地方,恳请读者批评指正。如果读者有更多的宝贵意见,可以通过邮箱hinus@163.com联系我,期待得到读者的反馈,让我们在技术之路上互勉共进。

致谢

在本书写作期间,王帅负责内存管理部分的资料整理与校对,段富臣则负责编译和可执行程序加载部分的资料整理与校对,在此向他们表示感谢。本书在编写的过程中还得到了华为公司操作系统首席架构师陈海波老师的指导,在这里向海波老师表示诚挚的谢意。顾波飞对本书进行了仔细的校对,也向他表示感谢。

海纳