1. 嵌入式Linux内核概述:内核版本演进、源码结构与配置系统
各位同学,咱们今天正式开讲。嵌入式Linux内核,说白了就是一套专门跑在资源受限硬件上的操作系统内核。我做了十几年嵌入式,见过太多人一上来就make menuconfig瞎点一通,最后编译出来的内核要么跑不起来,要么大得离谱。嗯,这章咱们先把地基打牢。
1.1 内核版本演进:从Linus的玩具到工业级系统
Linux内核从1991年诞生到现在,版本号一直在变。我个人习惯把版本演进分成三个阶段:
| 阶段 | 版本范围 | 特点 |
|---|---|---|
| 早期 | 0.01 ~ 2.6 | 单内核、不支持抢占、驱动少 |
| 成熟期 | 2.6 ~ 4.x | 可抢占内核、设备模型、DTB引入 |
| 现代 | 5.x ~ 6.x | 实时补丁、Rust支持、BPF大爆发 |
为什么我要提这个?因为你在选内核版本时,不是越新越好。我在一个ARM Cortex-A7的项目上,曾经固执地用了当时最新的5.10,结果发现某个网卡驱动在4.19上稳定得很,5.10上反而有bug。后来我学乖了——嵌入式项目选内核,优先选LTS版本,比如4.19、5.10、6.1这些。
1.2 内核源码结构:别被目录吓到
第一次解压Linux内核源码,看到几十个目录,很多人头皮发麻。其实核心目录就那么几个,我列个清单:
- arch/ —— 体系结构相关代码。ARM、x86、RISC-V都在这里。嵌入式开发最常逛的地方。
- drivers/ —— 驱动代码。占了源码一半以上的体积。你想想看,一个内核支持几千种设备,驱动能不多吗?
- kernel/ —— 核心调度、进程管理、信号处理。这部分一般不动。
- mm/ —— 内存管理。页分配、slab、vmalloc都在这里。
- fs/ —— 文件系统。ext4、fat、nfs、procfs……
- net/ —— 网络协议栈。TCP/IP、socket、netfilter。
- include/ —— 头文件。你写驱动时
#include的东西大多来自这里。 - scripts/ —— 编译脚本、配置工具。Kconfig解析器就在这里。
我记得刚入行时,导师跟我说了一句话,至今受用:"你不需要看懂所有代码,但要知道去哪找代码。" 比如你想改某个ARM开发板的启动流程,直接进arch/arm/mach-xxx/;想调网卡驱动,去drivers/net/ethernet/。
1.3 内核配置系统:Kconfig与Makefile的配合
内核配置系统,说白了就是一套"开关管理"机制。Kconfig定义"有什么开关",Makefile决定"开关怎么用"。我画了一张图,帮你理清关系:
1.3.1 Kconfig语法速览
Kconfig文件里,最常用的就是config、menuconfig、choice、menu这几个关键字。我写个例子:
menu "My Custom Drivers"
config MY_DRIVER
tristate "My custom driver support"
depends on ARM
help
This is a custom driver for my embedded project.
config MY_DRIVER_DEBUG
bool "Enable debug output"
depends on MY_DRIVER
default n
endmenu
这里tristate表示三种状态:编译进内核(y)、编译为模块(m)、不编译(n)。bool只有y/n两种。depends on就是依赖关系——你选了MY_DRIVER,才能看到MY_DRIVER_DEBUG。
ARCH=XXX,结果我忘了选架构,在menuconfig里找了半天没找到那个选项。后来查Kconfig才发现,depends on条件不满足时,选项根本不会显示。
1.3.2 Makefile中的条件编译
Kconfig定义完开关,Makefile里怎么用?很简单:
obj-$(CONFIG_MY_DRIVER) += my_driver.o
obj-$(CONFIG_MY_DRIVER_DEBUG) += my_driver_debug.o
如果CONFIG_MY_DRIVER=y,那么obj-y就会把my_driver.o编译进内核。如果是m,就编译成模块。如果是n,这行等于没写。
嗯,这里有个小技巧:调试驱动时,先用=m编译成模块,这样出了问题不用重新烧写整个内核,insmod/rmmod就能快速迭代。等稳定了再改成=y编进内核。
1.4 本章小结
这一章我们聊了三件事:内核版本怎么选、源码目录怎么看、配置系统怎么玩。说白了,就是让你拿到一个内核源码包后,知道从哪下手。下一章咱们会动手编译第一个内核,到时候这些概念都会用上。
make ARCH=arm help,看看支持哪些开发板。这是你第一次和内核源码"握手"。