本文整理内核的职责与分类,以及用户态/内核态的划分、系统调用切换过程和用户态线程与内核态线程的映射模型。
内核(Kernel)是操作系统连接应用与硬件的桥梁,至少提供以下 4 种基本能力:
操作系统通常分为三层:最底层硬件设备抽象、中间的内核、最上层应用。

进程与内核之间采用类似请求/响应的模型:进程向内核发起请求,让出 CPU 执行权限;内核接手 CPU,完成请求后再将执行权限交还调用进程。这一隔离是必需的——内核可直接访问全部内存、管理所有进程,必须与进程之间保持权限边界。

Linux 采用宏内核架构:内核是一个完整的可执行程序,以最高权限运行,文件系统、驱动、内存管理等大多打包在内核中。现代 Linux 支持动态加载内核模块,无需重新编译内核即可安装驱动。
微内核只保留最基本能力(进程调度、虚拟内存、中断),驱动、文件系统等多数功能放在用户空间管理。其优势是体积小、可移植性强;代价是驱动与硬件交互需频繁进行内核态切换,性能开销较大。

架构上抽象出微内核(内部有最小内核模块),但实现上用宏内核方式——整体作为一个完整程序,包含大量功能。Windows NT 属于混合内核。
| 维度 | Linux | Windows NT |
|---|---|---|
| 内核类型 | 宏内核 | 混合内核 |
| 开源 | 是 | 否 |
| 可执行文件格式 | ELF(Executable and Linkable Format) | PE(Portable Executable,.exe/.dll/.sys) |
| 多任务/多处理 | 支持 Multitask、SMP | 支持 Multitask、SMP |
| 虚拟化 | KVM 等 | Hyper-V |
两者均支持对称多处理(SMP):各处理器地位平等,共享内存与硬件资源,任务可被调度到任意处理器执行。
ELF 将可执行文件划分为多个段(Segment),每段有特定用途;PE 结构与之相通。
内核运行在超级权限模式(Supervisor Mode),内存因此被划分为两部分:
用户空间代码被限制只能使用一个局部内存空间,称为运行在用户态(User Mode);内核空间代码可访问全部内存,称为运行在内核态(Kernel Mode)。
用户态程序需要执行特权指令时必须切换到内核态。过程如下(图中 Trap 即一种中断):

应用程序启动后在内存中创建执行副本,即进程。进程可分成用户态进程(应用程序副本)与内核态进程(内核自身进程)。现代操作系统以**线程(Thread,轻量级进程 LWP)**为执行单位,一个进程可拥有多个线程。
线程的创建位置有两种选择:用户态(用户空间 API)或内核态(系统调用)。
完全在用户空间创建,内核不知其存在。
优势:
劣势:
执行在内核态,通过系统调用创建。
优势:
劣势:
用户态线程创建成本低但无法利用多核,内核态线程可利用多核但创建/切换成本高。常见做法是在内核中预创建并复用一批内核线程,用户态线程附着其上执行。两者存在 4 种映射关系:
多个用户态线程复用 1 个内核态线程。创建成本低,但线程无法并发,现已很少使用。

每个用户态线程绑定 1 个独立内核态线程,允许全部线程并发、充分利用多核。Windows NT 与 Linux(NPTL 线程库)均采用此模型,但内核调度压力较大。

n 个用户态线程分配 m 个内核态线程((m \le n),常取 (m=) 核数)。兼顾内核线程数量与多核并发,早期 Solaris 等系统采用过此模型。

混合多对多与一对一:多数用户态线程为 n 对 m,少量用户线程可指定为 1 对 1。
