第三章 内核源码获取与结构:从三星官方获取内核源码、内核源码目录结构解析、Git版本管理技巧
3.1 从三星官方获取内核源码
做Exynos开发,第一步就是拿到正确的内核源码。这事儿看着简单,但坑不少。我刚开始做4412项目时,就因为在第三方网站下了个"优化版"内核,结果折腾了两周才发现是被人改过的——有些驱动被删了,有些配置被改了。从那以后,我只认官方渠道。
三星官方内核源码,主要有三个获取途径:
- 三星开源发布中心(opensource.samsung.com):这是最权威的渠道。所有Exynos芯片的内核源码,都会在这里发布。你输入芯片型号,比如Exynos4412、Exynos5422,就能找到对应的源码包。
- 三星GitHub仓库:三星在GitHub上有官方账号,会维护一些主流芯片的内核分支。不过说实话,更新速度不如开源发布中心快。
- 开发板厂商提供的BSP包:比如友善之臂、迅为这些厂商,他们会从三星拿到源码,然后加上自己的板级支持包。如果你用的是开发板,这个渠道其实更方便。
下载时要注意版本号。Exynos4412对应的内核版本通常是Linux 3.0.x或3.5.x,Exynos5422对应的是3.10.x或4.4.x。别下错了版本,否则后面驱动适配会出大问题。
3.2 内核源码目录结构解析
拿到源码后,第一件事就是解压看看目录结构。很多新手一上来就急着改代码,结果连arch目录和drivers目录都分不清。嗯,这里我带你走一遍。
Linux内核源码的顶层目录,大概有这些:
| 目录名 | 作用 | 裁剪时重点关注 |
|---|---|---|
| arch/ | 体系结构相关代码 | arch/arm/ 下的 mach-exynos/ 和 plat-samsung/ |
| drivers/ | 设备驱动 | 这是裁剪的主战场,占内核代码的70%以上 |
| fs/ | 文件系统 | 不需要的文件系统类型可以砍掉 |
| net/ | 网络协议栈 | 根据产品需求决定保留哪些协议 |
| kernel/ | 内核核心功能 | 调度器、信号、定时器等,一般不动 |
| mm/ | 内存管理 | 除非你特别懂,否则别碰 |
| include/ | 头文件 | 定义了很多宏和数据结构 |
| sound/ | 音频子系统 | 如果产品不需要音频,可以整个目录去掉 |
| crypto/ | 加密API | 嵌入式设备通常用硬件加密,这个可以精简 |
对于Exynos平台,最关键的目录是 arch/arm/mach-exynos/。这里面包含了芯片的板级初始化代码、时钟管理、电源管理、中断控制器等。我当年裁剪4412内核时,在这个目录里泡了整整一周。
再看 drivers/ 目录,这里面的子目录是按设备类型分的:
drivers/gpio/— GPIO驱动drivers/i2c/— I2C总线驱动drivers/spi/— SPI总线驱动drivers/mmc/— SD/MMC卡驱动drivers/video/— 显示驱动drivers/usb/— USB驱动drivers/input/— 输入设备驱动(触摸屏、按键等)drivers/net/— 网络设备驱动
裁剪时,你只需要保留产品实际用到的驱动。比如你的产品没有WiFi,那 drivers/net/wireless/ 整个目录都可以不编译。
3.3 Git版本管理技巧
做内核裁剪,没有Git寸步难行。你想想看,改了几百个配置项,结果编译不过,想回退都不知道从哪下手。所以,我强烈建议从一开始就用Git管理你的内核源码。
我的工作流是这样的:
- 从三星官方拉取源码后,先打一个tag:
git tag v3.0.15-exynos4412-origin。这样你随时可以回到最原始的版本。 - 创建一个裁剪分支:
git checkout -b custom/cutdown-v1。所有修改都在这个分支上进行。 - 每次修改配置后,提交一次:比如"disable WiFi driver"、"remove unused filesystem"、"enable DMA engine"。提交信息要写清楚,方便以后回溯。
- 编译通过后,再打一个tag:
git tag v3.0.15-exynos4412-cutdown-v1。这样每个可用版本都有记录。
还有一个很实用的命令——git bisect。当你裁剪后发现某个功能不正常,但又不知道是哪个配置引起的,可以用它来二分查找。我曾在一次项目中,用bisect在30分钟内找到了导致USB无法识别的罪魁祸首——一个看起来人畜无害的电源管理配置项。
另外,建议用git stash来临时保存未提交的修改。比如你正在改配置,突然需要切到另一个分支看代码,直接git stash,切回来再git stash pop,非常方便。
git add .一股脑把所有文件都加进去。内核源码编译时会生成很多中间文件(.o、.cmd、.tmp等),这些不应该被Git跟踪。一定要写好.gitignore文件,把*.o、*.cmd、*.tmp、vmlinux、System.map、modules.order这些都忽略掉。
最后,分享一个我自己的习惯:每次裁剪前,先用git diff生成一个patch文件,保存到项目文档里。这样即使以后换了电脑、换了同事,也能知道当初做了哪些修改。说白了,做嵌入式开发,文档和代码一样重要。