4. 内核源码目录结构解析:arch、drivers、fs、include、kernel、mm、net 等核心目录的作用

Linux 内核源码是一个庞大且高度模块化的工程,理解其顶层目录结构是进行驱动开发的第一步。每个顶层目录都承载着特定的功能领域,驱动开发者需要快速定位关键代码所在位置。本章将逐一解析核心目录的职责、典型子目录以及驱动开发中最常打交道的文件。

4.1 顶层目录全景图

Linux 内核源码根目录下通常包含以下核心目录(以 6.x 版本为例):

核心目录速查表 — 驱动开发最常访问的目录依次为:drivers、include、arch、kernel、Documentation。
目录名 全称 / 含义 驱动开发关联度 典型子目录举例
arch Architecture(体系结构) ⭐⭐⭐⭐⭐ arm、arm64、x86、riscv、mips
drivers Device Drivers(设备驱动) ⭐⭐⭐⭐⭐ i2c、spi、gpio、usb、pci、dma、mmc
fs File Systems(文件系统) ⭐⭐⭐ ext4、proc、sysfs、debugfs、tmpfs
include Header Files(头文件) ⭐⭐⭐⭐⭐ linux、uapi、asm-generic、dt-bindings
kernel Core Kernel(内核核心) ⭐⭐⭐⭐ sched、irq、time、power、printk
mm Memory Management(内存管理) ⭐⭐⭐ slab、page_alloc、vmalloc、memblock
net Networking(网络协议栈) ⭐⭐⭐ ipv4、ipv6、wireless、core、ethernet
Documentation 内核文档 ⭐⭐⭐⭐ devicetree、driver-api、filesystems
scripts 编译与辅助脚本 ⭐⭐⭐ kconfig、dtc、checkpatch.pl
Linux 内核源码顶层目录结构图 Linux 内核源码根目录 arch drivers fs include kernel mm net Documentation scripts 💡 驱动开发核心路径 drivers/ → 编写设备驱动代码 | include/ → 引用内核 API 头文件 | arch/ → 处理平台相关配置 每个顶层目录下还有多层子目录,驱动开发者应重点掌握 drivers、include、arch 三个目录。

4.2 arch/ — 体系结构相关代码

arch/ 目录存放与 CPU 体系结构紧密相关的代码,是内核移植和板级支持包(BSP)的核心区域。每个支持的 CPU 架构在该目录下都有一个独立子目录。

4.2.1 常见架构子目录

  • arch/arm/ — 32 位 ARM 架构,嵌入式设备中最常见。
  • arch/arm64/ — 64 位 ARMv8 架构,现代 SoC 主流选择。
  • arch/x86/ — x86 架构,主要用于 PC 和服务器。
  • arch/riscv/ — RISC-V 开源架构,新兴嵌入式平台。
  • arch/mips/ — MIPS 架构,部分老旧嵌入式设备仍在使用。

4.2.2 驱动开发者关注点

子路径 作用 驱动开发场景
arch/arm/boot/dts/ 设备树源文件(.dts / .dtsi) 定义硬件拓扑、寄存器地址、中断号
arch/arm/mach-xxx/ 板级初始化代码(旧内核) 平台设备注册、时钟配置
arch/arm/include/asm/ 架构相关头文件 IO 操作宏、内存屏障、原子操作
arch/arm64/kernel/ 内核启动与异常处理 中断向量、系统调用入口
实战提示: 编写 ARM 平台驱动时,设备树文件位于 arch/arm/boot/dts/ 或 arch/arm64/boot/dts/。修改设备树后需要重新编译 DTB 并更新引导加载程序。
arch 目录内部结构示例 arch/ arm/ arm64/ x86/ riscv/ mips/ boot/ kernel/ mm/ 驱动开发重点:arm/boot/dts/ 设备树文件 + arm/include/asm/ 架构头文件 每个架构子目录内部结构相似,包含 boot、kernel、mm、include 等子目录

4.3 drivers/ — 设备驱动代码主战场

drivers/ 是内核中最大的目录,包含几乎所有外设的驱动实现。驱动开发者的大部分工作都在这个目录下完成。

4.3.1 驱动子系统分类

子系统目录 包含驱动类型 典型文件
drivers/gpio/ GPIO 控制器驱动 gpio-omap.c, gpio-rockchip.c
drivers/i2c/ I2C 总线控制器 + 从设备驱动 i2c-imx.c, busses/, algos/
drivers/spi/ SPI 控制器 + 从设备驱动 spi-imx.c, spi-rockchip.c
drivers/mtd/ 存储设备驱动(NAND、SPI NOR) nand/, spi-nor/
drivers/net/ 网络接口控制器驱动 ethernet/, wireless/, phy/
drivers/usb/ USB 主机/设备/OTG 驱动 host/, gadget/, core/
drivers/mmc/ SD/MMC/eMMC 控制器驱动 host/, core/, card/
drivers/dma/ DMA 控制器驱动 dmaengine/ 子目录
drivers/clk/ 时钟控制器驱动 clk-imx.c, clk-rockchip.c
drivers/pinctrl/ 引脚复用与配置驱动 pinctrl-imx.c
避坑提醒: 不要直接在 drivers/ 根目录下添加新驱动。应按照外设类型放入对应的子系统子目录。如果找不到合适的子系统,考虑使用 drivers/misc/(杂项设备)或 drivers/staging/(暂存区)。

4.3.2 驱动文件命名惯例

# 典型 SPI 控制器驱动命名
drivers/spi/spi-imx.c        # NXP i.MX 系列 SPI 控制器
drivers/spi/spi-rockchip.c   # Rockchip SPI 控制器
drivers/spi/spi-bcm2835.c    # Broadcom BCM2835 SPI 控制器

# 典型 I2C 控制器驱动命名
drivers/i2c/busses/i2c-imx.c
drivers/i2c/busses/i2c-tegra.c

# 典型 GPIO 控制器驱动命名
drivers/gpio/gpio-omap.c
drivers/gpio/gpio-rockchip.c

4.4 include/ — 内核 API 头文件仓库

include/ 目录是内核提供给驱动开发者的“API 手册”。驱动代码通过包含这些头文件来使用内核提供的函数、宏和数据结构。

4.4.1 头文件分类

子目录 内容 驱动常用头文件
include/linux/ 通用内核 API 头文件 module.h, platform_device.h, gpio.h, i2c.h, spi.h
include/uapi/ 用户空间 API 头文件 ioctl.h, types.h, stat.h
include/asm-generic/ 体系结构无关的通用头文件 io.h, atomic.h, bitops.h
include/dt-bindings/ 设备树绑定头文件 gpio.h, clock.h, interrupt.h
include/soc/ SoC 特定头文件 imx8m.h, rockchip.h
驱动开发黄金法则: 编写驱动时,优先查阅 include/linux/ 下的头文件。例如 #include <linux/module.h> 是所有内核模块必须包含的头文件。

4.5 fs/ — 文件系统与驱动接口

fs/ 目录实现各种文件系统,驱动开发者主要关注其中与设备模型交互的部分:

  • procfs (fs/proc/) — 通过 /proc 接口暴露内核信息,驱动可用 proc_create() 创建条目。
  • sysfs (fs/sysfs/) — 通过 /sys 接口暴露设备属性,驱动通过 device_create_file() 添加。
  • debugfs (fs/debugfs/) — 调试文件系统,驱动开发阶段常用 debugfs_create_dir() 和 debugfs_create_file()。
  • tmpfs (fs/tmpfs/) — 临时文件系统,用于内存文件存储。
// 驱动中使用 debugfs 的典型代码片段
#include <linux/debugfs.h>

static struct dentry *debugfs_dir;

static int __init my_driver_init(void)
{
    debugfs_dir = debugfs_create_dir("my_driver", NULL);
    if (IS_ERR(debugfs_dir))
        return PTR_ERR(debugfs_dir);
    
    debugfs_create_u32("reg_value", 0644, debugfs_dir, &my_reg_value);
    return 0;
}

static void __exit my_driver_exit(void)
{
    debugfs_remove_recursive(debugfs_dir);
}

4.6 kernel/ — 内核核心机制

kernel/ 目录包含内核的核心子系统,驱动开发中会频繁调用其中的函数:

子目录 / 文件 功能 驱动常用接口
kernel/sched/ 进程调度 schedule(), wake_up_process()
kernel/irq/ 中断子系统 request_irq(), free_irq(), tasklet
kernel/time/ 时间与定时器 timer_list, hrtimer, jiffies
kernel/printk.c 内核日志 printk(), pr_info(), dev_err()
kernel/workqueue.c 工作队列 schedule_work(), queue_work()

4.7 mm/ — 内存管理

mm/ 目录实现虚拟内存、页分配、slab 分配器等。驱动开发者主要使用以下接口:

  • kmalloc / kfree — 内核内存分配,基于 slab 分配器。
  • vmalloc / vfree — 虚拟地址连续但物理地址不连续的内存分配。
  • dma_alloc_coherent — DMA 一致性内存分配,位于 drivers/base/dma-coherent.c。
  • ioremap / iounmap — IO 内存映射,将物理地址映射到内核虚拟地址空间。
// 驱动中常见的内存操作模式
void __iomem *base_addr;

// 1. 映射物理地址到内核虚拟空间
base_addr = ioremap(0x1C00000, SZ_4K);
if (!base_addr) {
    pr_err("ioremap failed\n");
    return -ENOMEM;
}

// 2. 读写寄存器
u32 val = readl(base_addr + 0x10);
writel(val | BIT(0), base_addr + 0x10);

// 3. 解除映射
iounmap(base_addr);

4.8 net/ — 网络协议栈

net/ 目录实现完整的网络协议栈。网络设备驱动开发者需要关注:

  • net/core/ — 网络核心层,包括 net_device 结构体操作、sk_buff 管理。
  • net/ethernet/ — 以太网协议相关代码。
  • net/wireless/ — 无线网络子系统(cfg80211、mac80211)。
  • net/ipv4/ 和 net/ipv6/ — TCP/IP 协议栈实现。
学习路径建议: 网络驱动开发入门可以从 drivers/net/ethernet/ 下的简单以太网驱动开始阅读,配合 include/linux/netdevice.h 理解 net_device_ops 结构体。

4.9 其他重要目录

目录 作用 驱动开发用途
Documentation/ 内核文档 查阅驱动 API 说明、设备树绑定文档
scripts/ 编译与配置脚本 checkpatch.pl 检查代码风格、dtc 编译设备树
tools/ 用户空间工具 perf、objtool、testing 等调试工具
samples/ 内核编程示例 参考驱动编写范例
init/ 内核初始化代码 main.c 是内核入口,了解启动流程
lib/ 内核库函数 kobject、klist、rbtree 等通用数据结构
驱动开发代码路径 选择驱动类型 字符设备驱动 平台设备驱动 ← 上一章 📖 返回目录 下一章 →