2.1 Linux内核模式和体系结构
一个完整可用的操作系统主要由4部分组成:硬件、操作系统内核、操作系统服务和用户应用程序,如图2-1所示。用户应用程序是指那些字处理程序、互联网浏览器程序或用户自行编制的各种应用程序;操作系统服务程序是指向用户提供的服务,被看作是操作系统部分功能的程序。在Linux操作系统上,这些程序包括X窗口系统、shell命令解释系统以及内核编程接口等系统程序;操作系统内核是本书所感兴趣的部分,它主要用于对硬件资源的抽象和访问调度。
图2-1 操作系统组成部分
目前,操作系统内核的结构模式主要可分为整体式的单内核模式和层次式的微内核模式。而本书所注释的Linux 0.11内核,则采用了单内核模式。单内核模式的主要优点是内核代码结构紧凑、执行速度快,不足之处主要是层次结构性不强。
在单内核模式系统中,操作系统提供服务的流程为:应用主程序使用指定的参数执行系统调用指令(int x80),使CPU从用户态(User Mode)切换到内核态(Kernel Mode),然后系统根据参数值调用特定的系统调用服务程序,而这些服务程序则根据需要调用底层的支持函数以完成特定的功能。在完成了应用程序要求的服务后,操作系统又从内核态切换回用户态,回到应用程序中继续执行后续指令。因此,单内核模式的内核也可粗略地分为三层:调用服务的主程序层、执行系统调用的服务层和支持系统调用的底层函数,如图2-2所示。
图2-2 单内核模式的简单结构模型
Linux内核主要由5个模块构成,它们分别是:进程调度模块、内存管理模块、文件系统模块、进程间通信模块和网络接口模块。
进程调度模块用来负责控制进程对CPU资源的使用。所采取的调度策略使各进程能够公平合理地访问CPU,同时保证内核能及时地执行硬件操作。内存管理模块用于确保所有进程能够安全地共享机器主内存区,同时,内存管理模块还支持虚拟内存管理方式,使Linux的进程可以使用比实际内存空间更多的内存容量。并可以利用文件系统把暂时不用的内存数据块交换到外部存储设备上去,当需要时再交换回来。文件系统模块用于支持对外部设备的驱动和存储。虚拟文件系统模块通过向所有的外部存储设备提供一个通用的文件接口,隐藏了各种硬件设备的不同细节,从而提供并支持与其他操作系统兼容的多种文件系统格式。进程间通信模块子系统用于支持多种进程间的信息交换方式。网络接口模块提供对多种网络通信标准的访问并支持许多网络硬件。
这几个模块之间的依赖关系见图2-3。其中的连线代表它们之间的依赖关系,虚线和虚框部分表示Linux 0.11中还未实现的部分(从Linux 0.95版才开始逐步实现虚拟文件系统,而网络接口的支持到0.96版才有)。
图2-3 Linux内核系统模块结构及相互依赖关系
由图可以看出,所有的模块都与进程调度模块存在依赖关系。因为它们都需要依靠进程调度程序来挂起(暂停)或重新运行它们的进程。通常,一个模块会在等待硬件操作期间被挂起,而在操作完成后才可继续运行。例如,当一个进程试图将一数据块写到软盘上去时,软盘驱动程序就可能在启动软盘加速期间将该进程置为挂起等待状态,而在软盘进入正常转速后再使得该进程能继续运行。另外3个模块也是由于类似的原因而与进程调度模块存在依赖关系。
其他几个依赖关系有些不太明显,但同样很重要。进程调度子系统需要使用内存管理子系统来调整一些特定进程所使用的物理内存空间。进程间通信子系统则需要依靠内存管理子系统来支持共享内存通信机制。这种通信机制允许两个进程访问内存的同一个区域以进行进程间信息的交换。虚拟文件系统也会使用网络接口来支持网络文件系统(NFS),同样也能使用内存管理子系统来提供内存虚拟盘(ramdisk)设备。而内存管理子系统也会使用文件系统来支持内存数据块的交换操作。若从单内核模式结构模型出发,我们还可以根据Linux 0.11内核源代码的结构将内核主要模块绘制成图2-4所示的框图结构。
其中内核级中的几个方框,除了硬件控制方框以外,其他粗线方框分别对应内核源代码的目录组织结构。除了这些图中已经给出的依赖关系以外,所有这些模块还会依赖于内核中的通用资源。这些资源包括内核所有子系统都会调用的内存分配和收回函数、打印警告或出错信息函数以及一些系统调试函数。
图2-4 内核结构框图