驱动编译成模块和*区别
一、最核心
*(=y)是“焊死在内核里”
M(=m)是“可插拔的外设模块”
二、编译层面的本质区别(非常重要)
1️⃣ =y(*) —— 内核的一部分
CONFIG_FOO=y
意味着:
源码被编译进:
vmlinux
Image / zImage
和内核一起 同时存在、同时启动
不能卸载
不依赖 userspace
📌 编译结果:
vmlinux 内有 foo_driver.o
2️⃣ =m(M) —— 可加载模块
CONFIG_FOO=m
意味着:
驱动编译成一个 .ko 文件
放在:
/lib/modules/$(uname -r)/foo.ko
需要 modprobe / insmod 才会生效
可以卸载
📌 编译结果:
foo.ko
三、启动阶段的决定性差异(嵌入式最关键)
❌ 模块在内核早期是“不可用的”
凡是和启动相关的驱动,必须 =y
包括:
MMC / eMMC / NAND
EXT4 / UBIFS
I2C / SPI(如果 rootfs 在上面)
LCD / 串口(调试)
四、真实工程中的选型原则(非常实用)
✅ 必须 =y 的驱动
| 类型 | 原因 |
|---|---|
| RootFS 所在设备 | 启动前必须可用 |
| 控制台串口 | 否则你啥都看不到 |
| pinctrl / clock | SoC 基础设施 |
| Device Tree 支持 | ARM 必须 |
✅ 适合 =m 的驱动
| 类型 | 原因 |
|---|---|
| USB 设备 | 插拔式 |
| 摄像头 | 可选 |
| 声卡 | 可替换 |
| WiFi / BT | 固件加载慢 |
五、M 和 Y 在 Kconfig 里的隐藏规则(很重要)
1️⃣ 模块不能依赖内置的反向关系
A = m
B depends on A
→ B 不能是 y,最多 m
所以有规则:
依赖链中,最“弱”的那个决定上限
2️⃣ select 会强制拉成 y(危险)
config A
select B
即使你没开 B
也会被强行设为 y

浙公网安备 33010602011771号