操作系统结构

1.3.1 说内核运行在内核态,但没说”哪些东西该放进内核”。这一节讲的正是这个设计决策。

五种结构可以放在同一根轴上看:内核里装多少东西。装得越多性能越高(不用来回切模式),装得越少可靠性越好(出问题的代码少)——五种结构就是这条轴上的五个位置。

机制

分层法

把内核分成若干层,每层只能调用紧邻的低一层。

优点是便于调试和验证、易于扩充和维护:验证第 层时,可以认为第 层已经是正确的,于是复杂的正确性问题被拆成了一串简单问题。

缺点有两条:仅可调用紧邻的低一层,效率低——一个请求要逐层传递下去,每层都有开销;难以合理定义各层的边界——很多功能之间是互相依赖的,硬要排成线性次序并不自然。

模块化

把内核划分为若干模块,各模块之间通过接口相互协作,不再要求严格的层次次序。内核由一个主模块和若干可加载的内核模块构成。

优点是模块间逻辑清晰、易于维护,并且支持动态加载新的内核模块——需要某个设备驱动时才装进来,不需要就卸掉。

缺点是模块间的接口定义未必合理实用,且模块之间相互依赖,难以调试和验证——这恰好是分层法优点的反面。

宏内核(大内核)

把操作系统的主要功能模块都作为一个紧密整体运行在内核态。

优点是性能高:各功能之间是普通的函数调用,不需要任何模式切换。

缺点是内核庞大、结构混乱、难以维护,且可靠性差——内核态的一个错误就可能拖垮整个系统,而内核里的代码越多,出错的机会越大。

微内核

只把最基本的功能保留在内核,把那些不需要在内核态执行的功能移到用户态执行。

内核中通常只保留:低级进程/线程管理、低级存储管理、中断和陷入处理、进程间通信。而文件系统、设备驱动、网络协议栈等都作为用户态的服务进程运行。

优点是内核小、可靠性高、可扩展性好、可移植性好——某个服务崩了只是一个用户态进程挂掉,可以重启,不会拖垮系统。

缺点是性能开销大,原因见下面的边界分析。

外核

内核负责为程序分配硬件资源,并保证资源使用的安全(不越权),而把资源的”抽象”工作交给上层。

普通操作系统给你的是”文件”和”虚拟内存”这些抽象;外核直接给用户程序分配”未经抽象的”硬件资源——比如直接给你几个物理磁盘块、几个物理页框,由应用程序自己决定怎么用。

优点是应用可以更灵活地使用硬件(数据库可以按自己的方式管理磁盘,不必迁就通用文件系统),并且减少了虚拟硬件资源的映射层,可以提升效率。

缺点是降低了系统的一致性,也使系统变得更复杂。

边界

微内核为什么性能差

这是本节唯一需要论证的地方,也是最常考的”为什么”。

在宏内核中,一次读文件是这样的:用户程序执行系统调用进入内核态 → 内核里的文件系统代码直接以函数调用的方式调设备驱动 → 返回用户态。全程只有两次模式切换。

在微内核中,文件系统是一个用户态的服务进程,于是同一次读文件变成:用户程序 → 陷入内核 → 内核把请求通过进程间通信转发给文件系统服务进程 → 切换到该进程 → 文件系统服务进程又要读磁盘,于是它再陷入内核、内核再转发给设备驱动服务进程……

每一次服务之间的协作,都要付出”模式切换 + 进程切换 + 消息传递”的代价,而在宏内核里这只是一次函数调用。

所以微内核的开销不在于”内核小”,而在于”被拆开的部分之间必须靠昂贵的方式通信”。

微内核不是”没有内核”

“微”指的是内核里保留的功能少,不是没有内核。

微内核仍然运行在内核态,仍然掌握着最基本的机制——进程管理、内存管理的最低层、中断处理、进程间通信。这四样是无论如何都搬不出去的:进程间通信本身就是搬出去的那些服务赖以协作的手段,它必须留在内核。

同理,宏内核也不是”没有模块”——宏内核完全可以是模块化实现的(Linux 就是),只是这些模块统统运行在内核态。

判据:区分宏内核与微内核,看的是”服务运行在哪个模式”,不是”代码有没有分模块”。

分层法与模块化的优缺点恰好互补

这一对值得放在一起记,因为它们的优缺点是镜像的:

分层法限制严格(只能调低一层),因此易于验证、但效率低且边界难定。

模块化限制宽松(模块间自由协作),因此灵活、易维护、可动态加载,但相互依赖导致难以调试验证。

一句话:分层法用”限制”换”可验证性”,模块化用”自由”换”灵活性”。

五种结构在同一根轴上的位置

把它们按”内核里装多少”排开,规律非常清楚:

宏内核装得最多 → 性能最高、可靠性最差。 模块化 / 分层法是宏内核内部的组织方式 → 仍然都在内核态。 微内核装得最少 → 可靠性最高、性能最差。 外核则换了一个维度——它不是”装多少”,而是”抽不抽象”:内核只做分配与保护,不做抽象。

做选择题时,看到”效率高/内核庞大”想宏内核;看到”可靠性、可扩展、可移植”想微内核;看到”只保护和复用硬件、把控制权交给上层”想外核。

对照速查

结构核心思想优点缺点
分层法每层只能调用紧邻的低一层便于调试和验证、易扩充维护效率低;层的边界难以合理定义
模块化主模块 + 可加载内核模块逻辑清晰易维护、支持动态加载接口未必合理;相互依赖,难调试验证
宏内核主要功能都在内核态性能高(函数调用)内核庞大、可靠性差
微内核只保留最基本功能在内核可靠、可扩展、可移植性能开销大(模式切换 + IPC)
外核内核只做分配与保护,不做抽象灵活、减少映射层、效率高降低一致性、系统更复杂
微内核保留在内核的四样
①低级进程 / 线程管理
②低级存储管理
③中断和陷入处理
④进程间通信(搬不出去,它是其余服务协作的手段)
常见题眼多半对应
效率高、内核庞大、服务都在内核态宏内核
只保留最基本机制、服务外移、可靠可扩展微内核
按层调用、下层为上层服务、便于验证分层法
高内聚低耦合、可动态加载模块化
只负责保护和复用硬件、把控制权交给上层外核

考点

  • 五种结构及其优缺点,分层法与模块化的优缺点互补
  • 微内核性能差的原因是”模式切换 + 进程切换 + 消息传递”取代了函数调用
  • 微内核不是没有内核;宏内核也可以是模块化的
  • 判据:宏内核 vs 微内核看”服务运行在哪个模式”,不看代码是否分模块
  • 进程间通信必须留在微内核里,因为其余服务靠它协作
  • 外核的特点是”不做抽象”,直接分配未经抽象的硬件资源

链接