内核源码目录结构:从根目录看懂Linux内核

说实话,我第一次打开Linux内核源码的时候,整个人是懵的。几千个文件夹,几万个文件,完全不知道从哪下手。后来跟着前辈一点点啃,才慢慢摸清了门道。

今天我就带你走一遍内核源码的顶层目录。这些目录就像城市的各个功能区——有的管交通,有的管通信,有的管安全。搞清楚了它们,你以后裁剪内核、调试驱动,心里就有底了。

核心观点:内核源码的顶层目录,每个都对应一个独立的功能子系统。理解它们,就等于拿到了内核的“地图”。

1. arch/ —— 架构相关代码

这是内核里最“硬”的部分。arch 是 architecture 的缩写,存放着针对不同CPU架构的代码。

你想想看,ARM和x86的启动流程能一样吗?中断处理能一样吗?当然不能。所以这部分代码是平台相关的。

  • arch/arm/ —— ARM架构,手机、嵌入式设备的主力
  • arch/x86/ —— 桌面和服务器,我们最熟悉的平台
  • arch/arm64/ —— 64位ARM,现在的服务器和高端手机都在用
  • arch/riscv/ —— RISC-V,开源指令集,最近很火

我的经验:做嵌入式开发时,我习惯先看 arch/arm/boot/dts/ 下的设备树文件。有一次调试一块新板子,死活起不来,最后发现是设备树里GPIO的引脚号写错了。嗯,这种坑踩过一次就记住了。

2. block/ —— 块设备层

block 目录管的是硬盘、SSD、U盘这类块设备。它负责I/O调度、请求合并、电梯算法这些底层逻辑。

说白了,你的数据怎么从应用程序写到磁盘上,中间经过哪些排队和优化,都是这里说了算。

关键文件:block/blk-core.c 是块设备的核心,我建议初学者先看这个文件里的函数调用关系。

3. crypto/ —— 加密API

这个目录存放着内核的加密算法实现。AES、SHA、RSA……你能想到的加密算法,这里基本都有。

为什么内核需要加密?文件系统加密(比如fscrypt)、网络加密(IPsec)、设备加密(dm-crypt)都依赖它。

4. drivers/ —— 设备驱动

这是内核里最大的目录,没有之一。它占了整个内核代码量的60%以上。

drivers/ 下面按设备类型分了子目录:

  • drivers/gpio/ —— GPIO驱动
  • drivers/i2c/ —— I2C总线驱动
  • drivers/spi/ —— SPI总线驱动
  • drivers/net/ —— 网卡驱动
  • drivers/mmc/ —— SD卡、eMMC驱动
  • drivers/usb/ —— USB驱动

注意:我曾经在裁剪内核时,把 drivers/ 下的某个目录整个删掉了,结果系统启动后USB鼠标键盘全不认。后来学乖了——裁剪驱动时,先看 Kconfig 和 Makefile,搞清楚依赖关系再动手。

5. fs/ —— 文件系统

fs 目录实现了各种文件系统。ext4、btrfs、xfs、fat、ntfs……每种文件系统在这里都有一个子目录。

文件系统的核心是 VFS(虚拟文件系统)层,它在上层应用和底层存储之间搭了一座桥。你执行 open()、read()、write() 这些系统调用时,最终都会走到 fs/ 下的代码。

6. include/ —— 头文件

这是内核的“公共接口”。所有模块共享的数据结构、宏定义、函数声明都在这里。

  • include/linux/ —— 核心头文件,比如 list.h、spinlock.h
  • include/uapi/ —— 用户空间和内核空间的接口定义
  • include/asm-generic/ —— 架构无关的汇编头文件

7. init/ —— 内核初始化

init 目录是内核的“入口”。从 start_kernel() 函数开始,内核的整个初始化流程都在这里。

我记得第一次看 init/main.c 时,被里面密密麻麻的函数调用吓到了。其实不用怕,你只需要关注几个关键点:

  • setup_arch() —— 架构相关的初始化
  • sched_init() —— 调度器初始化
  • rest_init() —— 启动第一个用户进程

8. ipc/ —— 进程间通信

IPC 是 Inter-Process Communication 的缩写。这个目录实现了:

  • 信号量(semaphore)
  • 消息队列(message queue)
  • 共享内存(shared memory)

这些机制让不同的进程可以互相通信、同步数据。

9. kernel/ —— 内核核心

这是内核的“大脑”。调度器、进程管理、信号处理、时间管理……这些最核心的功能都在这里。

kernel/sched/ 下面就是调度器的代码。CFS(完全公平调度器)的实现就在这个目录里。

10. lib/ —— 内核库函数

lib 目录提供了一些通用的工具函数,比如:

  • 字符串操作(string.c)
  • 链表操作(list_sort.c)
  • CRC校验(crc32.c)
  • 红黑树(rbtree.c)

这些函数在内核各个模块里被广泛使用。

11. mm/ —— 内存管理

mm 目录实现了虚拟内存、页分配、slab分配器、内存映射等机制。

为什么这个目录重要?因为内存是系统最宝贵的资源之一。mm/ 下的代码决定了你的程序能申请多少内存、申请速度有多快。

12. net/ —— 网络协议栈

net 目录实现了整个网络协议栈。从链路层到应用层,TCP/IP、UDP、ICMP、ARP……全在这里。

net/ipv4/ 下面是TCP和UDP的实现。net/core/ 是网络核心层,比如sk_buff结构体的操作。

13. scripts/ —— 编译脚本

scripts 目录存放着内核编译时用到的各种脚本和工具。比如:

  • Kconfig 解析脚本
  • 设备树编译工具
  • 模块签名工具

做内核裁剪时,你经常要跟 scripts/kconfig/ 下的代码打交道。

14. security/ —— 安全模块

security 目录实现了内核的安全框架。SELinux、AppArmor、Tomoyo 这些安全模块都在这里。

它还提供了 LSM(Linux Security Module)框架,允许第三方安全模块以插件形式接入内核。

15. sound/ —— 音频子系统

sound 目录实现了音频驱动和ALSA(高级Linux声音架构)。

ALSA 是现代Linux音频的基石。它提供了统一的音频接口,让应用程序不用关心底层硬件差异。

16. usr/ —— 初始ramfs

usr 目录用于生成 initramfs(初始内存文件系统)。initramfs 是内核启动早期加载的一个临时根文件系统,里面包含了必要的驱动和工具。

17. virt/ —— 虚拟化

virt 目录实现了KVM(基于内核的虚拟机)的代码。它让Linux可以充当Hypervisor,运行其他操作系统。

我最近在做一个嵌入式虚拟化项目,virt/ 下的代码帮了大忙。

Linux内核源码顶层目录结构图 kernel/ 核心 mm/ 内存管理 init/ 初始化 drivers/ 驱动 fs/ 文件系统 net/ 网络 sound/ 音频 arch/ 架构 include/ 头文件 lib/ 库函数 scripts/ 脚本 核心层 → 子系统层 → 支撑层

总结一下:内核源码的顶层目录,每个都有明确的职责。做内核裁剪时,你只需要关注你需要的功能对应的目录。比如做嵌入式系统,重点看 arch/、drivers/、fs/;做网络设备,重点看 net/、drivers/net/。

我的建议:刚开始接触内核源码时,不要试图一次性搞懂所有目录。先挑一个你最感兴趣的子系统,比如网络或文件系统,深入进去。等熟悉了一个,再看其他的就轻松多了。

好了,这一章就到这里。记住这些目录的作用,后面我们做内核裁剪时,你会经常用到它们。