Linux Kernel 内核整体架构

2026年7月23日 · 5310 字 · 11 分钟 · Linux 操作系统 内核 源码阅读

元信息

  • 类型:技术博客 / 架构总览
  • 作者/机构:知乎「玩转Linux内核」
  • 原文链接:https://zhuanlan.zhihu.com/p/438248184
  • 阅读日期:2026-07-23
  • 关联主题:Linux 内核整体架构、子系统划分、源码目录
  • 阅读状态:粗读并整理为架构地图

一句话结论

这篇文章适合当 Linux 内核入门的“地图”:Linux 内核的核心任务是向下管理硬件,向上通过系统调用给应用提供统一接口;为了完成这个任务,内核可以先粗分为进程调度、内存管理、VFS、网络、IPC 五类核心子系统,再把这些子系统映射到源码目录。

需要注意:原文基于 Linux 3.10.29,且体系结构相关内容偏 ARM。它适合作为整体认知框架,不适合直接当作现代 Linux 最新目录和实现细节的精确说明。

阅读目的

  • 建立 Linux 内核“为什么这样分层”的第一张地图。
  • 知道进程调度、内存管理、VFS、网络、IPC 各自解决什么问题。
  • 把内核子系统和源码顶层目录对应起来,后续读源码时知道先去哪里找。
  • 为后续专题阅读提供导航:调度看 kernel/,内存看 mm/,文件系统看 fs/,网络看 net/,驱动看 drivers/

1. Linux 内核处在什么位置

Linux 内核在系统中的位置

从这张图看,Linux 内核夹在两层之间:

应用程序 / C 库 / Library Routine
  -> 系统调用
Linux Kernel
  -> 驱动和硬件控制
CPU / Memory / I/O / Network / 外设

直觉解释:应用程序不能随便直接操作硬件,否则系统会失控。内核就是中间的管理者,负责把危险、复杂、硬件相关的操作封装起来。

技术解释:用户态程序通过系统调用进入内核态,内核再调度 CPU、分配内存、访问文件、收发网络包、驱动硬件设备。

应用解释:写 read()write()malloc()fork()socket() 这类代码时,表面上调用的是库函数或系统调用,背后最终都会落到某个内核子系统。

2. 内核整体架构:五大核心子系统

Linux 内核整体子系统

原文把 Linux 内核核心功能拆成五类:

子系统 主要管理对象 给用户/上层提供什么
Process Scheduler CPU 时间 让多个进程/线程共享 CPU
Memory Manager 物理内存、虚拟内存 地址空间、内存分配、内存映射、换页
VFS 文件、目录、设备抽象 open/read/write/close 等统一文件接口
Network 网卡、协议栈、socket TCP/IP、UDP、socket 通信接口
IPC 进程间通信对象 信号量、消息队列、共享内存、信号等通信机制

这五个子系统可以用一句话记:

调度管 CPU,内存管地址,VFS 管文件和设备入口,网络管包,IPC 管进程之间说话。

3. 进程调度:谁来用 CPU

进程调度子系统

进程调度解决的问题是:CPU 数量有限,但系统里有很多可运行任务,内核必须决定“下一刻谁上 CPU”。

原文把调度子系统拆成四层:

模块 作用
Scheduling Policy 调度策略,决定哪个任务优先运行
Architecture-independent Scheduler 体系结构无关的调度核心,负责通用调度逻辑
Architecture-specific Schedulers 体系结构相关部分,处理寄存器、上下文切换、CPU 指令差异
System Call Interface 向用户态暴露调度相关接口

直觉解释:调度器像一个 CPU 时间分配员,决定每个进程什么时候跑、跑多久、什么时候被换下。

技术解释:调度策略选择下一个任务,通用调度代码维护运行队列和调度类,架构相关代码完成上下文切换,把 CPU 寄存器状态从旧任务切到新任务。

应用解释:当程序调用 sched_yield()、设置优先级,或者系统发生时钟中断时,都可能影响调度决策。

源码入口先记:

目录 关系
kernel/ 调度、进程核心逻辑所在的主要目录之一
arch/<arch>/ 上下文切换、体系结构相关调度支持
include/linux/sched.h 调度和任务结构相关头文件,后续读源码常遇到

4. 内存管理:虚拟地址和物理内存之间的桥

内存管理子系统

内存管理解决的问题是:应用看到的是自己的虚拟地址空间,但机器上真实存在的是有限的物理内存。内核负责建立、维护和保护这层映射。

原文把内存管理拆成三层:

模块 作用
Architecture Specific Managers 体系结构相关部分,处理页表格式、MMU、TLB、硬件访问细节
Architecture Independent Manager 体系结构无关部分,处理通用内存管理机制
System Call Interface 向用户态提供内存分配、释放、文件映射等接口

直觉解释:每个进程像拿到一张“自己的地址地图”,但这些地址不直接等于真实内存位置。内核和硬件一起把虚拟地址翻译到物理内存。

技术解释:内核以进程为单位维护地址空间,通过页表、缺页异常、页面分配、回收、交换、文件映射等机制管理内存。体系结构相关代码负责适配不同 CPU 的页表和 MMU 细节。

应用解释:malloc()mmap()、进程启动、动态库加载、缺页异常、swap,都离不开内存管理子系统。

源码入口先记:

目录 关系
mm/ 内存管理核心代码
arch/<arch>/mm/ 体系结构相关内存管理代码
include/linux/mm.h 内存管理常见结构和接口

5. VFS:把不同文件系统和设备统一成文件接口

VFS 子系统

VFS 解决的问题是:磁盘文件、设备、伪文件系统、不同格式的文件系统差异很大,但用户态希望用统一接口访问它们。

原文把 VFS 相关结构拆成这些模块:

模块 作用
Device Drivers 具体设备驱动,控制外部设备和控制器
Device Independent Interface 统一设备模型,屏蔽具体硬件差异
Logical Systems 具体逻辑文件系统,例如 ext、FAT 等
System Independent Interface 用统一接口表示设备和文件系统
System Call Interface 向用户态提供文件访问系统调用

直觉解释:VFS 是“文件访问的统一前台”。用户说我要 open/read/write,VFS 再把请求分发给具体文件系统或设备驱动。

技术解释:VFS 定义 inode、dentry、file、super_block 等统一对象,以及 file_operations、inode_operations 等操作表。具体文件系统和设备驱动实现这些接口。

应用解释:为什么 Linux 可以用 read() 读普通文件,也可以读设备文件?因为上层看到的是统一文件接口,底层由 VFS 和驱动完成分发。

源码入口先记:

目录 关系
fs/ VFS 和具体文件系统核心目录
drivers/ 设备驱动,很多设备最终以文件接口暴露
block/ 块设备层,和磁盘/文件系统 IO 密切相关
include/linux/fs.h VFS 核心结构和接口

这里要记住一个边界:原文说“一切皆文件”不是绝对的。Linux 大量设备和资源可以通过文件接口访问,但 CPU、内存、网络协议栈内部状态并不都天然是文件。它更准确的意思是:Linux 倾向于用文件抽象统一很多系统资源的访问入口。

6. 网络子系统:从 socket 到网卡

网络子系统

网络子系统解决的问题是:应用使用 socket 收发数据,但底层涉及协议栈、路由、缓存队列、网卡驱动和硬件。

原文把网络子系统拆成五层:

模块 作用
Network Device Drivers 网卡驱动,负责具体网络设备
Device Independent Interface 屏蔽网卡硬件差异
Network Protocols 实现 IP、TCP、UDP 等协议
Protocol Independent Interface 屏蔽协议差异,向上提供 socket 抽象
System Call Interface 向用户态提供网络相关系统调用

直觉解释:socket 是应用看到的“网络文件句柄”,网络子系统负责把写入 socket 的数据变成网卡能发出去的包。

技术解释:用户态系统调用进入 socket 层,再经过协议无关接口、具体协议栈、路由、邻居子系统、队列和网卡驱动,最后到硬件。

应用解释:connect()send()recv()epoll() 背后都和网络子系统相关。后续读网络协议栈时,可以沿着“系统调用 -> socket -> TCP/UDP/IP -> device driver”这条链走。

源码入口先记:

目录 关系
net/ 网络协议栈核心代码
drivers/net/ 网络设备驱动
include/net/ 网络子系统内部头文件
include/linux/net.h Linux 网络相关通用接口之一

7. IPC:进程之间怎么通信

原文没有展开 IPC,只把它列为核心子系统之一。

IPC 解决的问题是:进程默认有独立地址空间,不能直接随便读写彼此内存,但很多场景需要协作,所以内核提供受控通信机制。

常见 IPC 机制包括:

机制 用途
signal 异步通知进程发生了某件事
pipe 父子进程或相关进程之间的字节流通信
message queue 按消息传递数据
semaphore 进程间同步
shared memory 多进程共享同一段内存
futex 用户态锁和内核等待队列配合的基础机制

源码入口先记:

目录 关系
ipc/ System V IPC 等实现
kernel/signal.c 信号相关核心逻辑
kernel/futex/ 或相关 futex 文件 futex 机制,具体路径随内核版本变化

8. 源码顶层目录怎么对应子系统

Linux 内核源码顶层目录

原文最后给出 Linux 源码顶层目录说明。后续阅读时,可以先按下面这张表导航:

目录/文件 主要作用 对应主题
include/ 内核头文件,很多核心结构和接口定义在这里 全局
kernel/ 进程、调度、时间、信号等核心内核逻辑 进程管理 / 调度
mm/ 内存管理 内存管理
fs/ VFS 和具体文件系统 文件系统
net/ 网络协议栈,不含大部分网卡驱动 网络
ipc/ 进程间通信 IPC
arch/<arch>/ 体系结构相关代码,例如 x86、arm 架构适配
arch/<arch>/boot/dts Device Tree 文件,常见于 ARM/嵌入式 设备树
init/ 内核启动初始化 启动流程
block/ 块设备层 存储 / IO
drivers/ 设备驱动 驱动
lib/ 内核内部库函数 通用工具
crypto/ 加密/解密算法 安全 / 加密
security/ 安全框架,例如 SELinux 安全
virt/ 虚拟化支持,例如 KVM 虚拟化
usr/ initramfs 相关 启动
firmware/ 固件文件 驱动
samples/ 示例代码 学习参考
tools/ 辅助工具,例如性能分析、自测试 工具
Kconfig 配置系统入口 编译配置
Kbuild Kbuild 构建规则 编译系统
Makefile 顶层构建入口 编译系统
scripts/ 构建、配置、检查脚本 编译系统
Documentation/ 内核文档 官方说明
MAINTAINERS 维护者名单 查模块归属

机制拆解

输入

Linux 内核面对的输入不是一种,而是多类资源和请求:

  • 应用程序发起的系统调用。
  • 硬件设备产生的中断。
  • CPU 时间片和调度事件。
  • 缺页异常、内存压力。
  • 网络包、磁盘 IO、设备事件。

处理过程

内核把这些输入分发给不同子系统:

系统调用
  -> syscall interface
  -> 调度 / 内存 / VFS / 网络 / IPC
  -> 具体文件系统、协议栈、驱动或硬件相关代码

不同子系统之间不是孤立的。例如:

  • read() 可能经过 VFS、具体文件系统、块设备层、驱动、调度和内存管理。
  • send() 可能经过 socket、TCP/IP 协议栈、网卡驱动、内存分配和调度。
  • fork() 同时涉及进程管理、内存管理、文件描述符、信号等。

输出

内核最终给用户态或硬件产生结果:

  • 返回系统调用结果。
  • 修改进程状态。
  • 分配或回收内存。
  • 读写文件或设备。
  • 发送/接收网络包。
  • 唤醒等待中的任务。

边界条件

  • 原文是架构总览,不是实现细节说明。
  • 原文基于 Linux 3.10.29,现代内核目录和实现已有变化。
  • 原文偏 ARM 视角,x86、RISC-V 等体系结构相关路径和机制会不同。
  • “五大子系统”是学习分类,不是内核源码中的硬边界。真实调用路径经常跨多个子系统。

关键细节

  • Linux 内核的核心功能可以压缩成一句话:管理硬件资源,并通过系统调用向上提供受控接口。
  • 子系统划分要围绕资源看:CPU、内存、文件/设备、网络、进程间通信。
  • VFS 是理解 Linux 的关键抽象之一,因为它把普通文件、设备文件、伪文件系统统一到类似的访问模型下。
  • 网络子系统虽然也提供 socket 这种“类文件描述符”接口,但内部协议栈和 VFS 不是一回事。
  • drivers/ 占据大量代码量,但驱动代码多不等于内核最核心思想都在驱动里;调度、内存、VFS、网络协议栈才是理解内核机制的主线。
  • 源码目录是阅读入口,不等于模块边界。比如一次文件读取可能同时经过 fs/mm/block/drivers/

常见误解

误解 更准确的理解
Linux 内核就是驱动集合 驱动很多,但内核还包括调度、内存、VFS、网络、IPC、安全、虚拟化等核心机制
每个子系统只在一个目录里 顶层目录只是主要入口,真实实现经常跨目录
“一切皆文件”表示所有资源都是文件 更准确地说,Linux 用文件接口统一了很多资源,但并非所有内部资源天然都是文件
VFS 只管理磁盘文件 VFS 还参与设备文件、伪文件系统、内存文件系统等统一抽象
系统调用就是 C 库函数 C 库函数可能封装系统调用;真正进入内核的是 syscall

我的理解

这篇文章最有用的地方不是每个模块的细节,而是提供了一个“阅读坐标系”。

学 Linux 内核很容易迷路,因为一个功能会跨很多目录。比如执行 ls,表面是用户命令,背后会走系统调用、VFS、目录项缓存、具体文件系统、块设备层、内存分配、调度。没有整体地图时,会以为每个文件都是孤立知识点。

更好的读法是先建立资源主线:

CPU -> 调度
内存 -> mm
文件和设备入口 -> VFS
网络包 -> net
进程协作 -> IPC
硬件差异 -> arch + drivers
启动和构建 -> init + Kbuild/Makefile/scripts

后续读任何专题,都先问:这个问题主要管理哪类资源?它从哪个系统调用或硬件事件进入?它最终落到哪个子系统?

和当前主题的关系

这是 Linux 内核阅读项目的“总览入口”。后续可以按它拆出几条阅读路线:

路线 先读目录 适合问题
进程与调度 kernel/include/linux/sched.harch/<arch>/ 进程如何创建、切换、睡眠、唤醒
内存管理 mm/arch/<arch>/mm/ 虚拟内存、缺页、页表、分配器
文件系统 fs/block/drivers/ open/read/write 怎么落到磁盘或设备
网络协议栈 net/drivers/net/ socket、TCP/IP、网卡收发包路径
设备驱动 drivers/arch/<arch>/boot/dts 设备如何描述、匹配、初始化和访问
编译系统 MakefileKbuildKconfigscripts/ 内核如何配置和编译

疑问

问题 为什么重要 下一步
原文基于 Linux 3.10.29,现代内核顶层目录是否有明显变化? 后续读当前内核源码时不能照搬旧版本说明 对照当前 Linux 源码顶层目录更新一版现代目录表
原文把 VFS 和设备驱动放在同一张图里,容易让人误以为驱动属于 VFS 子系统内部 驱动、设备模型、VFS、块层之间边界需要进一步澄清 后续读设备模型和 VFS 时画一张更准确的数据流图
IPC 原文没有展开 IPC 是理解进程协作和同步的重要入口 后续单独读 IPC、signal、futex、pipe 相关资料

可迁移启发

  • 学复杂系统先找资源主线,再看模块目录。
  • 总览图的价值是导航,不是替代源码细节。
  • 读内核源码时,最好把“用户态 API / 系统调用 / 子系统 / 驱动或硬件”串成路径,不要只背目录名。

来源摘记

  • 原文说明 Linux 内核对下管理硬件设备,对上通过系统调用向库函数或应用提供接口。
  • 原文将内核核心功能划分为 Process Scheduler、Memory Manager、VFS、Network、IPC 五个子系统。
  • 原文基于 Linux 3.10.29,并约定体系结构相关内容以 ARM 为分析对象。