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 编译工具 裁剪配置与设备树编译
移植提示: 在 ARM 平台移植中,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/ 中的组织层次:

arch/arm/ 目录结构层次图 arch/arm/ boot/ configs/ kernel/ mm/ compressed/ dts/ entry-armv.S setup.c piggy.gzip vexpress.dts 说明 mach-*/ 和 plat-*/ 目录位于 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 层与具体文件系统、块设备之间的关系:

Linux 文件系统层次架构 用户空间 (open/read/write) 虚拟文件系统 (VFS) ext4 squashfs ubifs proc/sysfs 块设备层 (Block Layer)

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 设备。
裁剪建议: 对于内存小于 64MB 的 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 移植和裁剪的基础。核心要点总结如下:

  1. arch/ 是移植主战场,ARM 代码集中在 arch/arm/ 和 arch/arm64/。
  2. drivers/ 是裁剪重点,按需保留外设驱动,注意依赖关系。
  3. fs/ 决定根文件系统类型,嵌入式推荐 squashfs 或 ubifs。
  4. include/ 头文件路径由编译系统自动管理,ARM 特有头文件在 arch/arm/include/。
  5. kernel/ 和 mm/ 提供核心机制,ARM 平台需关注调度策略和内存分配器选择。
  6. net/ 协议栈可按需裁剪,无网络功能时可大幅减小内核体积。