轻松学习yocto: 24-Kernel Patch

第14课:很好,到这里你已经学会了:
1.Layer
2.Recipe
3.Image
4.Package
5.SDK
6.BSP
7.Device Tree
8.Kernel Config(menuconfig)

下面进入 第14课:Kernel Patch 管理。

这一课是真正的 Linux BSP 工程师 每天都会做的工作。


第14课:Kernel Patch 管理
文章摘要:
本课详细讲解了在Yocto项目中如何规范管理Linux内核补丁。核心思想是不直接修改kernel-source源码,而是将所有修改制作成patch文件,通过BitBake自动应用。课程涵盖了从为什么不能直接修改tmp/work目录下的源码,到正确的patch管理流程,包括patch的生成、组织、应用顺序和管理原则。通过完整的实验步骤,演示了如何从修改内核源码、生成patch、配置bbappend文件到验证patch正确应用的完整工作流。这是所有Linux BSP厂商(NXP、TI、Intel、ST、Raspberry Pi等)都采用的标准化内核修改维护方法。

目标:
不修改 kernel-source,而是把所有修改做成 patch,让 BitBake 自动打补丁。

这是 Yocto 最推荐,也是所有 Linux BSP 厂商(NXP、TI、Intel、ST、Raspberry Pi 等)都采用的方法。


为什么不能直接改 kernel-source?
例如你以前这样做:

tmp/work-shared/raspberrypi2/kernel-source/

进入里面:

drivers/

然后

vim hello_driver.c

或者

vim bcm2709-rpi-2-b.dts

甚至

vim Makefile

虽然:

bitbake virtual/kernel

能够编译成功。
但是:
下一次

bitbake -c clean virtual/kernel

或者

bitbake -c cleansstate virtual/kernel

整个

tmp/

都会重新生成。
你的修改:
全部消失。
所以:

tmp/work 里面任何源码,都不要长期修改。


正确流程
永远应该是:

源码
    ↓
修改
    ↓
git diff
    ↓
patch
    ↓
放进 layer
    ↓
SRC_URI += file://xxx.patch
    ↓
BitBake 自动打补丁

这就是 Kernel Patch 管理。


整个目录
建议建立:

meta-myproduct
└── recipes-kernel
    └── linux
        ├── linux-raspberrypi_%.bbappend
        └── files
            ├── 0001-add-hello-driver.patch
            ├── 0002-fix-led.patch
            └── 0003-add-dts.patch

真正项目里:
几十、
几百、

甚至上千个 patch。


patch 从哪里来?
例如修改:

drivers/misc/hello_driver.c

修改以前:

printk("Hello\n");

改成:

printk("Hello Yocto\n");

然后:

git diff

得到:

diff --git a/drivers/misc/hello_driver.c b/drivers/misc/hello_driver.c

@@

-printk("Hello\n");
+printk("Hello Yocto\n");

保存:

0001-print-yocto.patch

放到:

files/

即可。


bbappend
例如:

linux-raspberrypi_%.bbappend

写:

FILESEXTRAPATHS:prepend := "${THISDIR}/files:"

SRC_URI += " \
    file://0001-print-yocto.patch \
"

编译:
bitbake virtual/kernel
BitBake:
解压源码

自动 apply patch

开始编译

整个过程完全自动。


patch 顺序
如果:

SRC_URI += "\
file://0001.patch \
file://0002.patch \
file://0003.patch \
"

就是:

0001
↓
0002
↓
0003

依次应用。
所以 patch 一般编号:

0001
0002
0003
...
0123
0456

patch 管理原则
一个 patch:
一个功能。
例如:

0001-add-driver.patch

只增加 Driver。
不要:

Driver
+
DTS
+
LED
+
I2C
+
SPI

全部混一起。

以后很难维护。


修改 DTS 怎么办?
完全一样。
修改:

arch/arm/boot/dts/broadcom/bcm2709-rpi-2-b.dts

然后:

git diff

生成:

0002-add-led-node.patch

放:

files/
bbappend:
SRC_URI += " \
file://0002-add-led-node.patch \
"

即可。


修改 Driver
例如:

drivers/i2c/
drivers/spi/
drivers/usb/
drivers/net/
drivers/gpio/

全部都是:

修改源码
↓
git diff
↓
patch
↓
bbappend

修改 Kconfig
例如:

drivers/misc/Kconfig

新增:

config HELLO_DRIVER

生成:

0003-kconfig.patch

同样放进去。


修改 Makefile
例如:

drivers/misc/Makefile

增加:

obj-$(CONFIG_HELLO_DRIVER)+=hello_driver.o

生成:

0004-makefile.patch

也是一样。


一个完整 BSP 的样子

meta-myproduct
└── recipes-kernel
    └── linux
        ├── linux-raspberrypi_%.bbappend
        └── files
            ├── 0001-add-driver.patch
            ├── 0002-kconfig.patch
            ├── 0003-makefile.patch
            ├── 0004-add-dts.patch
            ├── 0005-fix-clock.patch
            ├── 0006-fix-reset.patch
            └── ...

真正的大型 BSP 都是这样维护内核修改的。


与上一课(linux-*.bbappend)的关系
上一课你已经学会了:

FILESEXTRAPATHS:prepend := "${THISDIR}/files:"

SRC_URI += " \
    file://my-overlay.dts \
"

这一课只是把 普通文件 换成了 补丁文件:

FILESEXTRAPATHS:prepend := "${THISDIR}/files:"

SRC_URI += " \
    file://0001-add-driver.patch \
    file://0002-add-dts.patch \
"

因此,Kernel Patch 管理本质上就是利用 linux-*.bbappend 将补丁加入 SRC_URI,由 Yocto
在内核源码解压后自动应用。


本课实验(推荐)
建议不要使用一个简单的 printk 示例,而是基于你已经完成的 hello_driver 实验,完整体验一次真实的 BSP 开发流程:
1.在 tmp/work-shared/raspberrypi2/kernel-source 中修改 hello_driver.c(例如新增一条 printk)。
2.使用 Git 生成一个补丁(如 0001-update-hello-driver.patch)。
3.将补丁放到:

meta-myproduct/
└── recipes-kernel/linux/files/

4.在 linux-raspberrypi_%.bbappend 中加入:

FILESEXTRAPATHS:prepend := "${THISDIR}/files:"

SRC_URI += " \
    file://0001-update-hello-driver.patch \
"

5.删除对 kernel-source 的手工修改,重新编译:

bitbake virtual/kernel

6.启动 Raspberry Pi,确认新的 printk 已经生效。

这样你就完成了从直接改源码到用补丁维护内核修改的完整迁移,这也是实际 Yocto BSP 项目中最常见、最规范的开发方式。

第一步:确认 Kernel Source 是 Git 仓库
先进入 kernel 源码目录:

cd ~/yocto/build-rpi2/tmp/work-shared/raspberrypi2/kernel-source

执行:

pwd

应该看到类似:

/home/xxx/yocto/build-rpi2/tmp/work-shared/raspberrypi2/kernel-source

然后执行:

git status

为什么先做这一步?
因为 Yocto 的 kernel source 一般都是 Git 仓库。
如果看到类似:

On branch ...
nothing to commit

说明后面的实验都可以直接使用:

git diff

或者

git format-patch

来生成补丁。

如果不是 Git 仓库,我们会换另一种生成 patch 的方式。


先不要进行下一步。
请执行:

cd ~/yocto/build-rpi2/tmp/work-shared/raspberrypi2/kernel-source
git status

输出结果:

On branch rpi-6.6.y
nothing to commit, working tree clean

第二步:定位函数
先不要修改。
执行:

sed -n '890,930p' drivers/char/random.c

第三步:修改源码
编辑文件:

vi drivers/char/random.c

找到:

void __init random_init(void)
{
    unsigned long entropy = random_get_entropy();

修改为:

void __init random_init(void)
{
    pr_info("Kernel Patch Demo: random_init() called\n");

    unsigned long entropy = random_get_entropy();

保存退出。
为什么使用 pr_info()?
Linux 内核推荐使用:pr_info(…)
而不是:printk(KERN_INFO …)
两者都可以,但 pr_info() 更符合现代内核代码风格

第四步:确认修改成功
执行:

git diff

你应该能看到类似:

diff --git a/drivers/char/random.c b/drivers/char/random.c
index ...
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ ...
 void __init random_init(void)
 {
+    pr_info("Kernel Patch Demo: random_init() called\n");
+
     unsigned long entropy = random_get_entropy();

第五步:生成 Patch
git diff > ~/yocto/meta-myproduct/recipes-kernel/linux/files/0001-random-init-demo.patch
再确认文件已经生成:ls -l ~/yocto/meta-myproduct/recipes-kernel/linux/files

第六步:修改 linux-raspberrypi_%.bbappend
请先查看它的内容:

cat ~/yocto/meta-myproduct/recipes-kernel/linux/linux-raspberrypi_%.bbappend

第七步:确认 Yocto 能看到 Patch
这是很多教程都会省略的一步,但在实际开发中非常重要。
执行:

bitbake -e virtual/kernel | grep "^SRC_URI="

看到:

SRC_URI="...
file://my.cfg
file://0001-random-init-demo.patch

第八步:重新编译 Kernel(验证 Patch)
由于你之前直接修改了 kernel-source,我们现在要让 Yocto 重新解压源码,并通过 Patch 来恢复这次修改。

  1. 先恢复源码
    回到 kernel-source:
cd ~/yocto/build-rpi2/tmp/work-shared/raspberrypi2/kernel-source

确认还有修改:

git status

然后恢复:

git restore drivers/char/random.c

再确认:

git status

应该看到:

nothing to commit, working tree clean

为什么这么做?
因为如果源码已经包含了你的修改,BitBake 再应用 Patch 时,可能会提示:

Reversed (or previously applied) patch detected!

我们要验证的是:

不是靠手工改源码,而是靠 Patch 自动完成修改。


2. 清理 Kernel
回到 build 目录:cd ~/yocto/build-rpi2
执行:bitbake -c clean virtual/kernel
3. 重新编译

然后执行:bitbake virtual/kernel


第九步:验证 Patch 是否真正应用
编译完成后,请不要急着烧录镜像。
先执行下面两个命令:

cd ~/yocto/build-rpi2/tmp/work-shared/raspberrypi2/kernel-source/drivers/char
grep -n "Kernel Patch Demo" random.c

892: pr_info(“Kernel Patch Demo: random_init() called\n”);
就说明:

这条代码不是你手工修改的,而是 Yocto 在解压源码后,自动应用 0001-random-init-demo.patch 得到的。

这就是 Kernel Patch 管理的核心。

~/yocto/build-rpi2/tmp/work-shared/raspberrypi2/kernel-source/drivers/char/random.c
SRC_URI += “file://0001-random-init-demo.patch”
bitbake virtual/kernel 会修改 random.c

该数据集包含1,000,000条大学生的合成记录,旨在建模生活方式、心理健康、学业行为、背景因素与学业表现之间的关系。该数据集涵盖多个领域的45+特征,并提供:连续目标变量:(0–10 尺度)gpa一个类别目标变量:(低/中/高)performance_level该数据集完全合成,但统计结构类似于真实的学术环境,并具有相关的行为和认知模式。数据集规模样本:1,000,000名学生功能:45+目标:2文件格式:CSV(推荐用拼花以提高效率)功能类别学术功能学习时长出席;出勤;出席人数作业完成情况期中考试成绩期末考试成绩项目成绩积压任务以往平均绩点课堂参与度每周学习小组会议小组学习时长心理与认知因素睡眠时长压力焦虑抑郁动机专注力时间管理自律财务压力生活方式与数字行为社交媒体使用时长游戏时长观看网飞时长屏幕使用时间每天解锁手机次数体育活动垃圾食品摄入频率咖啡因摄入量(毫克)熬夜频率拖延得分课外活动时长背景与环境家庭收入父母教育水平网络质量住校生感情状况同伴学习小组兼职时长图书馆访问次数完成的在线课程数量目标变量平均绩点(回归目标)连续变量范围:0 - 10由学业努力、心理健康、自律、生活方式模式和背景因素之间的非线性相互作用生成表现等级(分类目标)由平均绩点得出:低:平均学分绩点 < 5中:5 ≤ 平均学分绩点 < 7.5高:平均学分绩点 ≥ 7.5
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值