4. 内核配置与编译基础:Kconfig与Makefile结构、defconfig使用、menuconfig配置、内核编译流程
在全志T113平台上进行外设驱动移植,内核的配置与编译是贯穿始终的基础技能。不同内核版本(如Linux 4.9、5.4、5.10、6.1等)在Kconfig语法、Makefile组织以及编译流程上虽有共性,但也存在细微差异。本章将系统梳理这些核心概念,帮助你在面对不同内核版本时,能够快速定位配置选项、理解编译依赖,并高效完成内核镜像的构建。
4.1 Kconfig 内核配置系统
Kconfig是Linux内核的配置系统,它定义了所有可配置的选项及其依赖关系。每个内核版本都包含一个庞大的Kconfig树,驱动开发者通过修改或新增Kconfig条目,使自己的外设驱动能够被用户选择。
4.1.1 Kconfig 语法核心
一个典型的Kconfig条目包含类型、提示、依赖和选择逻辑。以下是在全志T113上常见的驱动配置示例:
config SUNXI_GPIO
tristate "Allwinner Sunxi GPIO support"
depends on ARCH_SUNXI
default y
help
Say Y here to support GPIO on Allwinner Sunxi SoCs.
This driver is required for GPIO control on T113.
| 关键字 | 含义 | 常见取值 |
|---|---|---|
tristate |
三态选项(编译进内核/编译为模块/不编译) | tristate, bool, int, string |
depends on |
依赖条件,条件不满足时选项不可见 | ARCH_SUNXI, OF, GPIO |
select |
反向选择,选中当前项时自动选中另一项 | select GPIOLIB |
default |
默认值 | y, n, m |
help |
帮助文本,在menuconfig中显示 | 描述驱动功能 |
imply关键字,它比select更温和,允许被依赖项仍可被用户手动关闭。全志T113在移植较新内核时,建议优先使用imply代替部分select,以减少配置冲突。
4.1.2 Kconfig 层级结构
内核源码树中的Kconfig文件按目录层级组织,顶层Kconfig通过source语句包含子目录的Kconfig。全志T113的驱动通常位于drivers/下的子目录中。
4.2 Makefile 驱动编译框架
内核的Makefile系统负责将Kconfig中配置的选项编译成目标文件。驱动开发者需要理解obj-$(CONFIG_*)机制,才能正确地将自己的驱动加入编译。
4.2.1 驱动Makefile基本模式
在驱动目录(如drivers/gpio/)下的Makefile中,通常采用以下模式:
# 单文件驱动
obj-$(CONFIG_GPIO_SUNXI) += gpio-sunxi.o
# 多文件驱动
obj-$(CONFIG_SUNXI_PINCTRL) += sunxi-pinctrl.o
sunxi-pinctrl-objs := pinctrl-sunxi.o pinctrl-sunxi-t113.o
| Makefile 变量 | 含义 | 示例 |
|---|---|---|
obj-y |
无条件编译进内核 | obj-y += core.o |
obj-m |
编译为可加载模块 | obj-m += mydrv.o |
obj-$(CONFIG_XXX) |
根据配置决定编译方式 | obj-$(CONFIG_SUNXI_GPIO) += gpio-sunxi.o |
xxx-objs |
多文件驱动时指定目标文件列表 | sunxi-pinctrl-objs := a.o b.o |
ccflags-y |
附加编译标志 | ccflags-y += -DDEBUG |
obj-$(CONFIG_ARCH_SUNXI)作为条件。从5.4开始,推荐使用更细粒度的CONFIG_SUNXI_XXX。移植驱动时,务必检查目标内核的Makefile风格,避免条件变量不匹配导致驱动未被编译。
4.3 defconfig 默认配置文件
defconfig是芯片厂商或开发板厂商提供的默认内核配置,它包含了使能特定SoC和板级外设所需的最小配置集。全志T113的defconfig文件位于内核源码的arch/arm/configs/或arch/arm64/configs/目录下。
4.3.1 全志T113常见defconfig
| 配置文件名称 | 适用场景 | 内核版本示例 |
|---|---|---|
sunxi_defconfig |
全志通用32位平台 | Linux 4.9 / 5.4 |
t113_defconfig |
T113专用配置(部分厂商提供) | Linux 5.10 / 6.1 |
sunxi_arm64_defconfig |
全志64位平台(T113使用) | Linux 5.10+ |
4.3.2 defconfig 使用流程
- 加载默认配置:
make ARCH=arm sunxi_defconfig - 基于默认配置调整:
make ARCH=arm menuconfig - 保存新配置:
make ARCH=arm savedefconfig(生成精简版defconfig) - 备份配置: 将生成的
defconfig文件复制到arch/arm/configs/my_t113_defconfig
menuconfig增量添加所需驱动配置。不要手动编辑.config文件,以免引入依赖不一致问题。
4.4 menuconfig 图形化配置
menuconfig是基于ncurses的终端图形化配置工具,是内核配置最常用的交互方式。它直观地展示了Kconfig定义的选项树,并自动处理依赖关系。
4.4.1 menuconfig 操作指南
| 按键 | 功能 |
|---|---|
↑ ↓ |
上下移动光标 |
Enter |
进入子菜单 / 确认选择 |
Space |
切换选项状态(Y / N / M) |
/ |
搜索配置项(支持通配符) |
Z |
显示所有选项(包括被依赖隐藏的) |
? |
查看选项的帮助信息 |
4.4.2 在全志T113上快速定位驱动
在menuconfig界面中,按/键进入搜索模式,输入驱动名称或关键词即可快速定位。例如搜索SUNXI_GPIO:
Symbol: SUNXI_GPIO [=y]
Type : tristate
Defined at drivers/gpio/Kconfig:123
Prompt: Allwinner Sunxi GPIO support
Depends on: ARCH_SUNXI [=y] && GPIOLIB [=y]
Location:
-> Device Drivers
-> GPIO Support (GPIOLIB [=y])
-> Memory mapped GPIO drivers
4.5 内核编译完整流程
从源码到可启动的内核镜像,全志T113的编译流程遵循标准Linux内核构建步骤,但需注意架构和工具链的指定。
4.5.1 编译步骤详解
# 1. 设置环境变量(交叉编译工具链)
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
# 2. 清理旧配置和编译产物
make distclean
# 3. 加载默认配置
make sunxi_defconfig
# 4. 自定义配置(可选)
make menuconfig
# 5. 编译内核镜像和设备树
make -j$(nproc) zImage dtbs
# 6. 编译内核模块(如果有)
make -j$(nproc) modules
# 7. 安装模块到目标根文件系统
make INSTALL_MOD_PATH=/path/to/rootfs modules_install
4.5.2 编译产物说明
| 产物文件 | 路径 | 说明 |
|---|---|---|
zImage |
arch/arm/boot/zImage |
压缩后的内核镜像,T113常用格式 |
*.dtb |
arch/arm/boot/dts/ |
编译后的设备树二进制文件 |
vmlinux |
源码根目录 | 未压缩的ELF格式内核,用于调试 |
System.map |
源码根目录 | 内核符号表,用于地址解析 |
.config |
源码根目录 | 当前使用的内核配置 |
4.5.3 编译流程可视化
4.6 不同内核版本的配置差异
在全志T113驱动移植过程中,不同内核版本在配置和编译方面存在以下关键差异:
| 对比项 | Linux 4.9 | Linux 5.10 | Linux 6.1 |
|---|---|---|---|
| 设备树目录 | arch/arm/boot/dts/ |
arch/arm/boot/dts/ |
arch/arm/boot/dts/allwinner/ |
| Kconfig依赖检查 | 较宽松 | 引入imply关键字 |
更严格的depends on检查 |
| 编译输出 | 默认zImage |
支持Image.gz(ARM64) |
默认Image(ARM64) |
| 模块签名 | 可选 | 默认关闭 | 部分架构默认开启 |
| GCC版本要求 | GCC 5.x+ | GCC 7.x+ | GCC 10.x+ |
arch/arm/boot/dts/下是否包含sunxi-t113.dtsi,以及Makefile中是否注册了对应的.dtb目标。