一个64位操作系统的设计与实现
上QQ阅读APP看书,第一时间看更新

1.2 操作系统的组成结构

一款功能完备、方便易用的操作系统,是由一套庞大的结构组成的,图1-1描述了操作系统的整体结构。

从图1-1可以看出,操作系统由内核层与应用层两部分组成。内核层主要由引导启动、内存管理、异常/中断处理、进程管理、设备驱动、文件系统等模块组成,而系统API库和应用程序则属于应用层的范畴。之所以将内核层和应用层分开,是因为内核层主要负责控制硬件设备、分配系统资源、为应用层提供健全的接口支持、保证应用程序正常稳定运行等全局性工作。而应用层主要负责的是人机交互工作。下面将对各个模型逐一进行介绍。

引导启动。引导启动是指,计算机从BIOS上电自检后到跳转至内核程序执行前这一期间执行的一段或几段程序。这些程序主要用于检测计算机硬件,并配置内核运行时所需的参数,然后再把检测信息和参数提交给内核解析,内核会在解析数据的同时对自身进行配置。如图1-1所示,使用横线将引导启动模块与其他内核层模块分隔开,是考虑到引导启动模块只是为了辅助内核启动,而并非真正属于内核。一旦内核开始执行后,引导程序便再无他用。如果把内核比作卫星的话,那么引导程序就相当于运载火箭,卫星进入轨道后,火箭就完成了它的使命。引导启动程序曾经分为两部分——Boot和Loader,现在通常把两者的功能合二为一,并统称为BootLoader。

图1-1 操作系统整体结构图

目前,比较流行的引导启动程序有Grub和Uboot等,它们的功能都比较强大,用户可以通过它们自带的终端命令行与之进行简单的交互,此举为控制内核的加载和使用提供了诸多便利。

内存管理。内存管理单元是内核的基础功能,它的主要作用是有效管理物理内存,这样可以简化其他模块开辟内存空间(连续的或非连续的)的过程,为页表映射和地址变换提供配套函数。Linux内存管理单元的伙伴算法,算是一种稳定成熟的内存管理算法,它可以长时间保持内存的稳定分配,防止内存碎片过多。还有内存线性地址空间的红黑树管理算法,它将原有的线性地址结构转换为树状结构以缩短搜索时间,同时又在每次插入新节点时调整树的高度(或者深度),来维持树的形状进而保证搜索时间的相对稳定,该算法既兼顾搜索时间损耗又兼顾插入时间损耗。因此,Linux选择红黑树这种近似平衡树来代替之前的AVL树(绝对平衡树)也是出于这方面的考虑。

异常/中断处理。此处的异常是指处理器在执行程序时产生的错误或者问题,比如除零、段溢出、页错误、无效指令、调试错误等。有的异常经过处理后,程序仍可继续执行,有的则不能继续执行,必须根据错误类型和程序逻辑进行相应的处理。而中断处理是指处理器接收到硬件设备发来的中断请求信号并作出相应处理操作。这部分内容与外围硬件设备关系非常密切,它的处理效率会影响操作系统整体的执行速度。通常,中断处理会被分为中断上半部和中断下半部。中断上半部要求快速响应中断,在取得必要的数据和信息后尽早开启中断,以使处理器能够再次接收中断请求信号。中断下半部被用来执行剩余中断内容,像数据解析、驱动程序状态调整等更耗时的内容均在这里完成。为了让更紧迫的进程优先执行,中断下半部还可将处理内容安放在一个进程中,以让更高优先级的进程得到快速执行。

进程管理。说到进程,想必会有人疑惑进程和程序的区别。程序是静静地躺在文件系统里的二进制代码,属于静止状态。一旦把这个程序加载到操作系统内运行,它就变成了进程。进程是程序的运行状态,所以它会比程序拥有更多管理层面的信息和数据。

说到进程管理功能,不得不提进程调度策略,一个好的进程调度策略,会提高程序的执行效率和反应速度。现代Linux内核的发展从早期的O(1)调度策略,到楼梯调度策略,再到现在的CFS完全公平调度策略,随着调度策略逐步升级,进程的执行效率也越来越高。进程管理的另一个重要部分是进程间通信。进程间通信有很多种方法,如SIGNAL信号、管道、共享内存、信号量等,这些通信机制各有特点,互相弥补不足。

设备驱动。随着硬件设备的不断增多,与之对应的设备驱动程序也渐渐占据了操作系统的很大一部分空间。为了给开发和使用设备驱动程序带来方便,不管是Linux操作系统还是Windows操作系统,它们都为驱动程序提供了一套或几套成熟的驱动框架供程序员使用。同时,为了便于驱动程序的调试、提高即插即用设备的灵活性及缩减内核体积,操作系统逐渐把驱动程序从内核中移出,仅当使用驱动时再将其动态挂载到内核空间,从而做到驱动程序即插即用。这样一来大大缩小内核体积,加快系统启动速度。

设备驱动程序会与内存管理、中断处理、文件系统及进程管理等多个模块共同协作。为了让硬件设备给应用程序提供接口,设备驱动程序几乎调用了内核层的所有资源。这也是开发操作系统的目的之一,即方便人们与设备交互。

文件系统。文件系统用于把机械硬盘的部分或全部扇区组织成一个便于管理的结构化单元。此处的扇区也可以是内存块,这样便组成了一个RAMDisk(内存式硬盘)。这样一个内存式硬盘单单在文件读写速度上就比普通机械硬盘高出一个数量级,其显而易见的缺点是掉电后数据全部丢失。不过与它的优点相比,这个缺点是完全可以忍受的,比如Linux内核的sys文件系统便是在RAMDisk中创建的。

文件系统的种类也是纷繁复杂的,像上面提到的sys文件系统,还有大家耳熟能详的FAT类文件系统,以及Linux的EXT类文件系统,它们对扇区的组织形式虽各具特色,却都是为了给原生操作系统提供方便、快捷的使用体验而设计的。

系统调用API库。系统调用API库接口有很多规范标准,比如Linux兼容的POSIX规范标准。对于不同的接口标准来说,其定义和封装的函数实现是不一样的。不管怎么说,系统调用API库最终都是为了给应用程序提供简单、快捷、便于使用的接口。

应用程序。应用程序包括我们自己安装的软件和系统提供的工具、软件与服务。

在众多应用程序中,比较特殊的一个应用程序是系统的窗口管理器,它主要用于管理图形界面的窗口,具体包括窗口的位置布局、鼠标键盘的消息投递、活动窗口仲裁等功能。

■ 窗口的位置布局负责控制窗口的比例大小、显示位置、标题栏及按钮等一系列与窗口的显示效果相关的功能。

■ 键盘鼠标的消息投递负责将键盘鼠标发送来的消息发往到活动窗口,这个过程会涉及窗口管理器对活动窗口的仲裁。

■ 活动窗口仲裁会依据鼠标采用的仲裁模式(包括鼠标跟随式、鼠标按下式等)来确定正在操作的窗口。