2. 内核裁剪基础与调试符号:内核编译选项、Kconfig与Makefile基础、开启调试相关配置

内核裁剪并非简单的“删除代码”,而是通过精细的编译选项控制,在功能、性能与调试能力之间取得平衡。本章将深入剖析内核编译系统的核心——Kconfig与Makefile,并重点讲解如何开启调试相关的关键配置(DEBUG_INFO、FTRACE、PERF_EVENTS),为后续的故障排查工具链打下坚实基础。

2.1 内核编译选项体系:Kconfig 与 Makefile 基础

Linux 内核的构建系统由两层核心机制组成:Kconfig 负责定义和选择编译选项,Kbuild (Makefile) 负责根据选项执行编译。理解这两者的协作关系,是进行内核裁剪和调试配置的前提。

核心概念: Kconfig 定义“做什么”(哪些功能模块被编译),Makefile 定义“怎么做”(如何编译这些模块)。

2.1.1 Kconfig 语法与选项类型

Kconfig 文件定义了内核的配置菜单。每个配置选项通常以 config 关键字开头,后跟选项名(如 CONFIG_FTRACE)。以下是常见的选项类型:

类型 关键字 说明 示例
布尔型 bool 编译进内核(y)或不编译(n) config DEBUG_INFO
bool "Debug info"
三态型 tristate 编译进内核(y)、编译为模块(m)或不编译(n) config FTRACE
tristate "Tracers"
整型 int 输入一个整数值 config LOG_BUF_SHIFT
int "Kernel log buffer size"
字符串 string 输入一个字符串 config CROSS_COMPILE
string "Cross-compiler tool prefix"

Kconfig 还支持 依赖关系(depends on)和 反向依赖(select),用于构建复杂的选项逻辑树。

# 示例:FTRACE 依赖于 DEBUG_KERNEL
config FTRACE
    bool "Tracers"
    depends on DEBUG_KERNEL
    select RING_BUFFER
    help
      Enable tracing of kernel events...

2.1.2 Makefile 与 Kbuild 的编译控制

当 Kconfig 生成了 .config 文件后,Makefile 通过 obj-y、obj-m 和 obj-n 变量来决定哪些文件被编译:

  • obj-y:无条件编译进内核。
  • obj-$(CONFIG_XXX):根据 CONFIG_XXX 的值(y/m/n)决定编译方式。
  • obj-m:编译为可加载模块。
# 内核源码树根目录 Makefile 示例片段
# 根据 CONFIG_FTRACE 的值决定是否编译 trace 目录
obj-$(CONFIG_FTRACE)        += trace/

# 在 kernel/trace/Makefile 中
obj-$(CONFIG_FTRACE)        += trace.o
obj-$(CONFIG_FUNCTION_TRACER) += trace_functions.o
裁剪技巧: 在嵌入式系统中,通过将不需要的功能对应的 CONFIG_XXX 设为 n,可以显著减小内核体积。但调试选项(如 FTRACE)通常建议保留为 y,以便在开发阶段进行问题定位。

2.2 内核裁剪流程与 .config 文件结构

内核裁剪的典型流程如下:

  1. 加载默认配置: make defconfig 或 make ARCH=arm multi_v7_defconfig
  2. 交互式调整: make menuconfig、make nconfig 或 make xconfig
  3. 保存配置: 生成 .config 文件
  4. 编译: make -j$(nproc)

.config 文件是内核编译的“蓝图”,每一行对应一个配置选项:

# .config 文件片段
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_INFO=y
CONFIG_FTRACE=y
CONFIG_FUNCTION_TRACER=y
CONFIG_PERF_EVENTS=y
# CONFIG_DEBUG_FS is not set
注意: 直接手动编辑 .config 文件可能导致依赖关系不一致。推荐使用 make olddefconfig 自动处理未定义的选项,或使用 make menuconfig 进行可视化调整。
内核裁剪与编译流程 内核裁剪与编译流程 Linux 源码树 Kconfig 系统 make menuconfig .config 文件 Makefile / Kbuild vmlinux / .ko 说明:Kconfig 定义选项,menuconfig 生成 .config,Makefile 根据 .config 决定编译对象。

2.3 开启调试相关配置:DEBUG_INFO、FTRACE、PERF_EVENTS

在嵌入式调试场景中,以下三个配置选项是故障排查的“三驾马车”。它们分别提供符号信息、内核跟踪能力和性能事件采样能力。

2.3.1 CONFIG_DEBUG_INFO:调试符号与行号信息

该选项控制是否在生成的内核镜像和模块中包含 DWARF 调试信息(如变量名、函数原型、源码行号)。

  • 开启效果: vmlinux 体积增大 2-5 倍,但 objdump、gdb、addr2line 等工具可以准确地将地址映射到源码位置。
  • 子选项:
    • CONFIG_DEBUG_INFO_REDUCED:仅保留部分调试信息,减小体积。
    • CONFIG_DEBUG_INFO_SPLIT:将调试信息分离到独立的 .dwo 文件中。
# 开启完整调试信息
CONFIG_DEBUG_INFO=y
# 可选:开启分离调试信息以减小内核镜像体积
CONFIG_DEBUG_INFO_SPLIT=y
实战建议: 在开发阶段始终开启 CONFIG_DEBUG_INFO。在发布阶段,可以保留 vmlinux 的调试版本,而将部署的内核镜像使用 strip 去除符号,以平衡体积与可调试性。

2.3.2 CONFIG_FTRACE:内核函数跟踪框架

Ftrace 是内核内置的跟踪器,用于记录函数调用、中断上下文、调度事件等。其核心配置如下:

配置项 类型 说明
CONFIG_FTRACE bool 主开关,开启跟踪框架
CONFIG_FUNCTION_TRACER bool 启用函数级跟踪(function 和 function_graph 跟踪器)
CONFIG_DYNAMIC_FTRACE bool 动态插桩,允许运行时启用/禁用特定函数的跟踪,减少性能开销
CONFIG_FTRACE_SYSCALLS bool 跟踪系统调用入口和返回
CONFIG_STACK_TRACER bool 跟踪内核栈使用情况,用于检测栈溢出
# 最小化 Ftrace 配置(推荐)
CONFIG_FTRACE=y
CONFIG_FUNCTION_TRACER=y
CONFIG_DYNAMIC_FTRACE=y
CONFIG_FTRACE_SYSCALLS=y

2.3.3 CONFIG_PERF_EVENTS:性能事件子系统

Perf 子系统提供硬件性能计数器(如 CPU 周期、缓存未命中)和软件事件(如上下文切换、页面错误)的采样与计数能力。

  • 核心配置: CONFIG_PERF_EVENTS=y
  • 硬件支持: 需要开启 CONFIG_HW_PERF_EVENTS(通常自动依赖)。
  • 用户空间接口: 通过 perf_event_open() 系统调用与 perf 命令行工具交互。
# Perf 事件配置
CONFIG_PERF_EVENTS=y
# 可选:开启跟踪点事件支持,与 Ftrace 协同工作
CONFIG_EVENT_TRACING=y
协同工作: CONFIG_PERF_EVENTS 与 CONFIG_FTRACE 并非互斥。Perf 可以调用 Ftrace 的跟踪点(tracepoint)作为事件源,实现“perf record -e sched:sched_switch”这样的混合采样。
调试配置依赖关系 调试配置依赖关系 CONFIG_DEBUG_KERNEL CONFIG_DEBUG_INFO CONFIG_FTRACE CONFIG_PERF_EVENTS DEBUG_INFO_REDUCED FUNCTION_TRACER HW_PERF_EVENTS

2.4 配置验证与常见问题

完成配置后,可以通过以下方式验证调试选项是否生效:

# 检查 .config 中相关选项
grep -E "DEBUG_INFO|FTRACE|PERF_EVENTS" .config

# 编译后检查内核是否包含调试符号
file vmlinux | grep -i "debug"

# 检查 Ftrace 是否可用
mount -t tracefs tracefs /sys/kernel/tracing
ls /sys/kernel/tracing/trace
常见问题 原因 解决方案
编译后内核体积过大 DEBUG_INFO 开启导致 使用 DEBUG_INFO_REDUCED 或 DEBUG_INFO_SPLIT
Ftrace 跟踪点不可见 未开启 CONFIG_EVENT_TRACING 在 menuconfig 中搜索并开启
perf 命令报错“No permission” 内核未开启 CONFIG_PERF_EVENTS 检查 .config,重新编译内核
动态插桩不生效 未开启 CONFIG_DYNAMIC_FTRACE 开启后重新编译,并确保内核命令行包含 ftrace=function
性能影响提示: 开启 FTRACE 和 PERF_EVENTS 会引入少量运行时开销(约 1-3%)。在生产环境中,建议通过 CONFIG_DYNAMIC_FTRACE 实现按需启用,避免持续的性能损失。