4. 内核源码目录结构解析:核心目录功能详解
Linux 内核源码是一个庞大而高度模块化的工程,理解其顶层目录结构是进行内核裁剪与 ARM 平台移植的第一步。本章将深入解析 arch/、drivers/、fs/、include/、kernel/、mm/、net/ 等核心目录的功能、组织方式及其在 ARM 移植中的关键作用。
4.1 内核源码顶层目录全景
Linux 内核源码根目录下包含数十个子目录,每个目录负责内核的一个核心子系统。下表列出了 ARM 移植中最常打交道的核心目录及其功能概要:
| 目录名 | 功能描述 | ARM 移植关注点 |
|---|---|---|
| arch/ | 体系结构相关代码,含 CPU、板级、启动、内存映射 | ARM 架构核心,移植主战场 |
| drivers/ | 设备驱动,含字符、块、网络、总线、平台设备 | 外设驱动适配与裁剪 |
| fs/ | 文件系统实现,含 VFS 层及具体文件系统 | 根文件系统类型选择 |
| include/ | 内核头文件,含架构无关与架构相关 API | ARM 特有头文件路径 |
| kernel/ | 核心调度、进程管理、中断、时间子系统 | 调度策略与抢占模型 |
| mm/ | 内存管理,含页分配、SLAB、VMA、DMA | ARM 页表与 DMA 配置 |
| net/ | 网络协议栈,含 socket、TCP/IP、netfilter | 网络驱动与协议裁剪 |
| init/ | 内核初始化入口与 main.c | 启动参数与 initcall |
| scripts/ | 编译配置脚本、Kconfig、DT 编译工具 | 裁剪配置与设备树编译 |
arch/arm/ 和 arch/arm64/ 是修改最频繁的目录,其次是 drivers/ 和 include/。裁剪时优先关注 arch/ 下的 Kconfig 和 Makefile。
4.2 arch/ — 体系结构核心目录
arch/ 是 ARM 移植的“心脏”。该目录按 CPU 体系结构分门别类,每种架构一个子目录。对于 ARM 平台,主要关注 arch/arm/(32位)和 arch/arm64/(64位)。
4.2.1 arch/arm/ 内部结构
进入 arch/arm/ 后,可以看到以下关键子目录:
- boot/:压缩后的内核镜像生成逻辑,含
compressed/解压缩代码。 - configs/:ARM 平台默认配置文件,如
s3c2410_defconfig、vexpress_defconfig。 - include/:ARM 架构特有头文件,如
asm/下的系统调用、页表、寄存器定义。 - kernel/:ARM 架构核心代码,如
entry-armv.S(中断向量表)、process.c、setup.c。 - mach-*/:特定 SoC/板级支持代码,如
mach-exynos/、mach-omap2/。 - mm/:ARM 内存管理,含
mmu.c、dma-mapping.c。 - plat-*/:平台级通用代码,如
plat-samsung/。
arch/arm/configs/ 中,每个 defconfig 文件对应一个参考板级配置。移植时通常基于最接近的 defconfig 修改,而非从零开始。
下图展示了 ARM 架构代码在 arch/arm/ 中的组织层次:
4.3 drivers/ — 设备驱动仓库
drivers/ 是内核中代码量最大的目录,包含所有外设的驱动实现。在 ARM 嵌入式系统中,驱动裁剪直接决定内核镜像大小和功能集。
4.3.1 驱动子目录分类
| 子目录 | 驱动类型 | ARM 常见设备 |
|---|---|---|
| gpio/ | GPIO 控制器驱动 | SoC 内置 GPIO、I2C/SPI 扩展 GPIO |
| i2c/ | I2C 总线与设备驱动 | 温度传感器、RTC、EEPROM |
| spi/ | SPI 总线与设备驱动 | LCD、ADC、Flash |
| tty/ | 串口与终端驱动 | UART、USB 串口 |
| mmc/ | MMC/SD/SDIO 驱动 | eMMC、SD 卡、WiFi SDIO |
| net/ | 网络接口驱动 | 以太网 PHY、无线网卡 |
| usb/ | USB 主机/设备/OTG 驱动 | USB 键盘、U 盘、网卡 |
| video/ | 显示与帧缓冲驱动 | LCD 控制器、HDMI |
| dma/ | DMA 控制器驱动 | PL080、DMA Engine |
| clk/ | 时钟框架驱动 | SoC 时钟树、PLL |
drivers/ 下的目录。许多驱动之间存在依赖关系,例如 i2c/ 可能被 rtc/、hwmon/ 依赖。建议使用 make menuconfig 的依赖追踪功能。
4.4 fs/ — 文件系统实现
fs/ 目录实现了虚拟文件系统(VFS)层以及所有具体的文件系统类型。在 ARM 嵌入式系统中,文件系统的选择直接影响启动速度、存储寿命和可靠性。
4.4.1 常见嵌入式文件系统对比
| 文件系统 | 适用场景 | 特点 | ARM 裁剪建议 |
|---|---|---|---|
| ext4 | 大容量 eMMC/SD 卡 | 成熟稳定、日志、大文件 | 保留,但可裁剪日志特性 |
| squashfs | 只读根文件系统 | 高压缩、只读、启动快 | 强烈推荐用于生产环境 |
| jffs2 | 原始 NAND Flash | 磨损均衡、掉电安全 | 仅用于 NAND 设备 |
| ubifs | MLC NAND / eMMC | UBI 层之上、高性能 | 替代 jffs2 的首选 |
| tmpfs | 内存文件系统 | 基于 RAM、高速 | 用于 /tmp、/var |
| proc | 进程与内核信息 | 虚拟文件系统 | 必须保留 |
| sysfs | 设备与驱动信息 | 虚拟文件系统 | 必须保留 |
下图展示了 VFS 层与具体文件系统、块设备之间的关系:
4.5 include/ — 内核头文件集合
include/ 目录存放所有内核头文件,分为架构无关和架构相关两部分。在 ARM 移植中,头文件的路径选择直接影响编译结果。
4.5.1 头文件路径规则
- include/linux/:架构无关的通用内核 API,如
kernel.h、sched.h、device.h。 - include/asm-generic/:架构无关的通用汇编/宏定义,作为各架构的默认实现。
- include/uapi/:用户空间可用的内核接口头文件,如
uapi/linux/ioctl.h。 - arch/arm/include/:ARM 架构特有头文件,编译时通过
-I路径优先搜索。 - arch/arm/include/asm/:ARM 汇编级头文件,如
ptrace.h、system.h、page.h。
arch/arm/include 会被软链接为 include/asm。因此代码中 #include <asm/xxx.h> 实际指向 arch/arm/include/asm/xxx.h。
4.6 kernel/ — 核心调度与进程管理
kernel/ 目录实现操作系统的核心机制:进程调度、中断管理、时间子系统、工作队列、RCU 等。在 ARM 嵌入式场景中,以下模块与裁剪密切相关:
| 子模块 | 文件/目录 | ARM 裁剪影响 |
|---|---|---|
| 进程调度 | sched/ |
选择 CFS 或 RT 调度器,影响实时性 |
| 中断管理 | irq/ |
ARM GIC 驱动依赖,必须保留 |
| 时间子系统 | time/ |
tickless 模式可省电,ARM 常用 |
| 工作队列 | workqueue.c |
驱动依赖,建议保留 |
| RCU 锁 | rcu/ |
可裁剪为 tiny RCU 节省内存 |
| 模块加载 | module.c |
若不需动态模块,可完全裁剪 |
4.7 mm/ — 内存管理子系统
mm/ 目录实现物理页管理、虚拟内存、SLAB 分配器、DMA 内存管理等。ARM 平台的内存管理有其特殊性:
- 页表管理:ARM 使用二级页表(L1/L2),
mm/mmu.c中实现页表创建。 - DMA 内存:
mm/dma-mapping.c处理一致性映射,ARM 需配置CONFIG_ARM_DMA_USE_IOMMU。 - 内存回收:
mm/vmscan.c实现 kswapd,在内存紧张时回收页面。 - SLAB 分配器:可选 SLAB、SLUB、SLOB,SLOB 适合小内存 ARM 设备。
CONFIG_SLOB 替代默认的 SLUB,可减少约 50KB 内核内存占用。
4.8 net/ — 网络协议栈
net/ 目录实现完整的网络协议栈,从 socket 层到具体协议。在 ARM 嵌入式系统中,网络功能裁剪是减小内核体积的重要手段。
4.8.1 网络协议栈裁剪层次
| 层次 | 目录/文件 | 裁剪选项 |
|---|---|---|
| Socket 层 | net/socket.c |
必须保留 |
| TCP/IP | net/ipv4/ |
可裁剪为仅 IPv4 或仅 IPv6 |
| 网络过滤 | net/netfilter/ |
无防火墙需求时可裁剪 |
| 无线 | net/wireless/ |
无 WiFi 时可裁剪 |
| 桥接 | net/bridge/ |
无桥接需求时可裁剪 |
| 802.1Q VLAN | net/8021q/ |
无 VLAN 需求时可裁剪 |
| 蓝牙 | net/bluetooth/ |
无蓝牙时可裁剪 |
| CAN 总线 | net/can/ |
工业控制场景保留 |
4.9 其他重要目录
除了上述核心目录,以下目录在 ARM 移植中也扮演重要角色:
- init/:内核启动入口
main.c,包含start_kernel()函数,以及initcall机制。 - scripts/:包含
Kconfig解析器、dtc(设备树编译器)、checkpatch.pl等工具。 - Documentation/:内核文档,ARM 相关文档在
Documentation/arm/下。 - tools/:用户空间工具,如
perf、selftests,不参与内核编译。 - crypto/:加密 API,ARM 硬件加密引擎驱动在此注册。
- security/:安全模块,如 SELinux、AppArmor,嵌入式系统通常裁剪。
init/ 或 kernel/ 中的功能时,务必检查 arch/arm/ 下的代码是否依赖这些功能。例如,ARM 的 setup.c 可能调用 kernel/ 中的 parse_early_param()。
4.10 本章小结
理解内核源码目录结构是 ARM 移植和裁剪的基础。核心要点总结如下:
- arch/ 是移植主战场,ARM 代码集中在
arch/arm/和arch/arm64/。 - drivers/ 是裁剪重点,按需保留外设驱动,注意依赖关系。
- fs/ 决定根文件系统类型,嵌入式推荐 squashfs 或 ubifs。
- include/ 头文件路径由编译系统自动管理,ARM 特有头文件在
arch/arm/include/。 - kernel/ 和 mm/ 提供核心机制,ARM 平台需关注调度策略和内存分配器选择。
- net/ 协议栈可按需裁剪,无网络功能时可大幅减小内核体积。