3. Linux内核源码结构

Linux 内核源码是一个庞大而高度模块化的工程,理解其目录树结构是进行内核裁剪与编译的第一步。本章将深入解析内核源码的顶层目录布局,并详细阐述进程调度、内存管理、文件系统与网络协议栈这四大核心子系统的职责与内部架构。

3.1 内核源码顶层目录树解析

Linux 内核源码根目录下包含数十个一级子目录,每个目录都承载着特定的功能模块。下表列出了嵌入式开发中最为关键的目录及其作用:

目录名 核心功能 嵌入式裁剪关注点
arch/ 体系结构相关代码(ARM、x86、RISC-V 等) 必须保留目标 CPU 架构子目录,其余可移除
kernel/ 核心调度、进程管理、中断处理 可裁剪调度器类型(CFS、RT)与内核锁机制
mm/ 内存管理(页分配、SLAB、VMA) 可关闭交换、大页内存、内存压缩等特性
fs/ 文件系统实现(ext4、FAT、NFS、proc、sysfs) 只保留目标存储介质所需的文件系统
net/ 网络协议栈(TCP/IP、IPv6、Netfilter) 按需裁剪协议族与防火墙模块
drivers/ 设备驱动(GPIO、I2C、SPI、UART、MMC) 嵌入式裁剪的核心区域,按硬件外设保留驱动
include/ 内核头文件(API 定义、数据结构) 通常全量保留,但可裁剪架构相关头文件
init/ 内核初始化入口(main.c) 可裁剪启动参数解析与初始化流程
scripts/ 编译脚本、配置工具、DT 编译工具 编译阶段使用,不进入最终镜像
裁剪提示: 在嵌入式项目中,arch/ 和 drivers/ 是体积优化的主战场。通过 make menuconfig 将不需要的驱动编译为 m(模块)或直接 n(禁用),可显著减少内核镜像体积。

下图展示了内核源码顶层目录之间的依赖关系与数据流向:

Linux 内核源码顶层目录依赖关系图 kernel/ (核心调度) mm/ (内存管理) fs/ (文件系统) net/ (网络协议栈) arch/ (体系结构相关) drivers/ (设备驱动) include/ (头文件) + init/ (初始化) 调度依赖 VFS 调用 网络调度 CPU 架构 驱动注册 提供 API 说明:箭头表示依赖或调用关系;arch/ 和 drivers/ 是硬件相关层,kernel/ 是核心调度中枢。

3.2 进程调度子系统

进程调度是内核的核心职责,负责决定哪个进程在何时获得 CPU 使用权。Linux 内核实现了完全公平调度器(CFS)和实时调度器(RT)。

  • CFS(完全公平调度器): 基于红黑树实现,以 vruntime 为键值,选择虚拟运行时间最小的进程运行,保证公平性。
  • RT(实时调度器): 支持 FIFO 和 Round-Robin 策略,优先级范围 0~99,优先级高的进程抢占低优先级进程。
  • 调度类(sched_class): 内核通过调度类接口统一管理 CFS、RT 和空闲调度器,形成可扩展的调度框架。
嵌入式裁剪要点: 在实时嵌入式系统中,可关闭 CFS 并仅保留 RT 调度器,减少调度器代码体积约 30KB。通过 CONFIG_PREEMPT_RT 可启用完全抢占内核,提升实时性。

下图展示了进程调度子系统的核心组件与调度流程:

进程调度子系统架构图 schedule() 入口 CFS 调度类 RT 调度类 Idle 调度类 红黑树 (vruntime) 优先级队列 (prio_array) 空闲进程 (swapper) 说明:schedule() 遍历调度类链表,选择优先级最高的调度类中的最优进程执行。 CFS 使用红黑树保证公平,RT 使用优先级队列保证实时性。

3.3 内存管理子系统

内存管理负责物理内存与虚拟内存的分配、回收与映射。嵌入式系统中,内存资源受限,理解内存管理机制对裁剪至关重要。

组件 功能描述 嵌入式裁剪选项
页分配器 基于伙伴算法管理物理页框,支持 4KB 基本页 可关闭大页(HugeTLB)减少 TLB 开销
SLAB/SLUB 分配器 管理小对象内存分配,减少碎片 SLUB 是默认分配器,体积更小,推荐嵌入式使用
VMA(虚拟内存区域) 管理进程地址空间,支持 mmap、brk 可关闭交换(swap)减少代码体积
页回收 kswapd 内核线程回收不活跃页面 可调整回收阈值或关闭交换
注意: 在无 MMU 的嵌入式 MCU(如 Cortex-M 系列)上,需要启用 CONFIG_MMU=n,此时内核使用平坦内存模型,所有进程共享同一地址空间,VMA 和页表机制将被裁剪。

下图展示了内存管理子系统的核心组件与数据流:

内存管理子系统核心组件图 内存管理核心 (mm/) 页分配器 (buddy) SLUB 分配器 VMA 管理 物理页框管理 kmalloc/kfree 缺页异常处理 说明:页分配器管理物理内存,SLUB 分配器管理小对象,VMA 管理进程虚拟地址空间。 嵌入式裁剪时,可关闭交换(CONFIG_SWAP)和大页(CONFIG_HUGETLB_PAGE)以减小体积。 无 MMU 系统需设置 CONFIG_MMU=n,此时 VMA 和页表机制被完全裁剪。

3.4 文件系统子系统

文件系统子系统通过虚拟文件系统(VFS)层统一管理多种具体文件系统实现。VFS 提供通用的系统调用接口(open、read、write),底层由具体文件系统驱动完成存储操作。

  • VFS 层: 定义超级块(super_block)、索引节点(inode)、目录项(dentry)和文件对象(file)四大核心数据结构。
  • 具体文件系统: ext4(日志型)、FAT(兼容性)、NFS(网络)、proc/sysfs(虚拟文件系统)等。
  • 块 I/O 层: 负责文件系统与块设备驱动之间的数据交换,支持 I/O 调度器(CFQ、Deadline、NOOP)。
嵌入式文件系统选择: 对于 Flash 存储,推荐使用 UBIFS(UBI 文件系统)或 JFFS2,它们支持磨损均衡和掉电恢复。对于 RAM 盘,可使用 tmpfs。裁剪时只保留目标文件系统,可大幅减小内核体积。

下图展示了文件系统子系统的分层架构:

文件系统子系统分层架构图 系统调用接口 (sys_open/sys_read) 虚拟文件系统 (VFS) ext4 FAT UBIFS proc/sysfs 块 I/O 层 (I/O 调度器) 说明:VFS 层屏蔽底层文件系统差异,提供统一接口。嵌入式裁剪时只保留目标文件系统驱动。

3.5 网络协议栈子系统

Linux 网络协议栈实现了完整的 TCP/IP 协议族,支持从链路层到应用层的全栈功能。嵌入式系统中,网络协议栈的裁剪空间很大。

协议层 核心组件 嵌入式裁剪建议
套接字层 BSD socket API、inet_sock 保留 AF_INET,可裁剪 AF_UNIX、AF_NETLINK
传输层 TCP、UDP、SCTP 仅保留 TCP/UDP,裁剪 SCTP、DCCP
网络层 IPv4、IPv6、ICMP、IGMP 仅保留 IPv4,裁剪 IPv6 可节省约 200KB
链路层 以太网、WiFi、PPP、Bridge 按硬件接口保留对应驱动
防火墙 Netfilter、iptables、nftables 可完全裁剪 Netfilter 以减小体积
裁剪案例: 一个仅需 TCP/IPv4 通信的嵌入式设备,可设置 CONFIG_IPV6=n、CONFIG_NETFILTER=n、CONFIG_IP_SCTP=n,网络协议栈体积可从 500KB 降至约 150KB。

下图展示了网络协议栈的分层结构与数据包处理流程:

网络协议栈分层结构与数据包处理流程 应用层 (socket) TCP 协议 UDP 协议 IPv4 协议 (路由、ICMP) 以太网驱动 / 设备层 ← 上一章 📖 返回目录 下一章 →