View on GitHub

紫宸

计算机学院拔尖人才工程组

内核之路:稳扎稳打,直指操作系统

操作系统内核学习的重要性不言而喻。大到研发具有自主知识产权可信操作系统这一国家战略,小到程序员内功的自我修炼,内核学习都是绕不开的关键环节之一。另一方面,操作系统内核是多种技术知识的交汇处,比如体系结构、编译链接、数据结构与算法、网络技术、存储技术等等。因此,内核的学习既是对前期所学知识的检验,又是帮助我们将这些知识融会贯通的好机会。

下面仅以Linux操作系统为例,分析、讨论内核的学习方法。在内核的学习过程中,我们除了面临内核本身技术复杂度的挑战,还不得不应对内核版本变化快、各种技术书籍资料相对滞后等不利因素。因此,内核的学习不能囿于某个或某些技术点的掌握,而应将重点放在内核技术学习的方法上。总体而言,内核技术的学习方法,就是不停地应用程序员技术手段(编写调试内核模块,阅读、修改、调试内核源码,阅读内核技术文档),以探索内核技术的原理,并在此过程中,遵循“问题-猜想-实证-构建”的学习方式。下面仅以一例说明如何在内核学习中应用上述方法。

在学习Linux内核地址分段管理机制的过程中,特别是结合《微机原理》、《汇编语言》、《计算机操作系统》等课程,很自然会产生一个疑惑,指针变量到底存储的是什么。这就是提出了“问题”。通过阅读有关x86地址转换机制的技术文档,可以大胆“猜想”指针变量中存储的其实是偏移量。而这又带来新的疑惑:为什么平时编程时没有感知到指针实质是偏移量,但却并没有带来什么不利影响。接下来,就需要通过我们应用程序员技术手段,分析并解决这一疑惑。通过编写内核模块访问GDTR寄存器,进而获取全局段描述符表信息;并结合x86技术手册,分析段描述符中的内容,从而发现常见段的范围是整个线性地址空间,即偏移量数值上等于线性地址。这一过程,就是利用程序员手段进行“实证”。“实证”之后,事情并没有结束,还需要应用学到的知识。比如,分段机制看似没有多大用处了,但是还可用于线程局部存储的构建。使用学到的分段管理机制,“构建”一个线程局部存储,而这又是内核学习的进一步深化。

从上面可以看出,内核学习的关键就是程序员技术手段,而线索就是“问题-猜想-实证-构建”。下面从学习路线角度,分析Linux内核的具体学习步骤。

第一步,学习Linux内核之前,需要满足如下要求:

第二步,有了前面的基础,就可以着手开始内核的学习,但绝不是从学习内核源码开始,而应从内核使用者的角度入手,即学习编写内核模块。这一步中,将会通过各种编程练习,掌握字符设备驱动程序、内核态同步、中断、内核与内核模块跟踪和调试等关键技术。推荐的书籍是《Linux设备驱动程序》。

第三步,有了内核模块的编写经验,自然而然就会对内核有一定的感性认识。在此基础之上,可以根据自己的兴趣或需要,选择一个内核子系统进行学习,比如地址空间与内存管理、存储I/O栈、进程调度等等。切忌内核学习没有方向性,特别是直接从内核启动代码入手。下面以地址空间与内存管理、存储I/O栈这两个在实际开发中经常碰到的子系统为例,说明学习路线。

对于地址空间与内存管理而言,可以按照如下路线进行:

对于存储I/O栈而言,可以按照如下路线进行: