ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

yocto: 24-Kernel Patch

yocto: 24-Kernel Patch 第14课很好到这里你已经学会了1.Layer2.Recipe3.Image4.Package5.SDK6.BSP7.Device Tree8.Kernel Configmenuconfig下面进入 第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/然后vimhello_driver.c或者vimbcm2709-rpi-2-b.dts甚至vimMakefile虽然bitbake virtual/kernel能够编译成功。但是下一次bitbake-cclean virtual/kernel或者bitbake-ccleansstate virtual/kernel整个tmp/都会重新生成。你的修改全部消失。所以tmp/work 里面任何源码都不要长期修改。正确流程永远应该是源码 ↓ 修改 ↓gitdiff↓ patch ↓ 放进 layer ↓ SRC_URIfile://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);然后gitdiff得到diff--gita/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/kernelBitBake解压源码↓自动 apply patch↓开始编译整个过程完全自动。patch 顺序如果SRC_URI\ file://0001.patch \ file://0002.patch \ file://0003.patch \ 就是0001 ↓ 0002 ↓ 0003依次应用。所以 patch 一般编号0001 0002 0003... 0123 0456patch 管理原则一个 patch一个功能。例如0001-add-driver.patch只增加 Driver。不要Driver DTS LED I2C SPI全部混一起。以后很难维护。修改 DTS 怎么办完全一样。修改arch/arm/boot/dts/broadcom/bcm2709-rpi-2-b.dts然后gitdiff生成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/全部都是修改源码 ↓gitdiff↓ 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/kernel6.启动 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然后执行gitstatus为什么先做这一步因为 Yocto 的 kernel source 一般都是 Git 仓库。如果看到类似On branch... nothing to commit说明后面的实验都可以直接使用gitdiff或者gitformat-patch来生成补丁。如果不是 Git 仓库我们会换另一种生成 patch 的方式。先不要进行下一步。请执行cd~/yocto/build-rpi2/tmp/work-shared/raspberrypi2/kernel-sourcegitstatus输出结果On branch rpi-6.6.y nothing to commit, working tree clean第二步定位函数先不要修改。执行sed-n890,930pdrivers/char/random.c第三步修改源码编辑文件vidrivers/char/random.c找到void __init random_init(void){unsigned long entropyrandom_get_entropy();修改为void __init random_init(void){pr_info(Kernel Patch Demo: random_init() called\n);unsigned long entropyrandom_get_entropy();保存退出。为什么使用 pr_info()Linux 内核推荐使用pr_info(…)而不是printk(KERN_INFO …)两者都可以但 pr_info() 更符合现代内核代码风格第四步确认修改成功执行gitdiff你应该能看到类似diff--gita/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 entropyrandom_get_entropy();第五步生成 Patchgit 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-evirtual/kernel|grep^SRC_URI看到SRC_URI... file://my.cfg file://0001-random-init-demo.patch第八步重新编译 Kernel验证 Patch由于你之前直接修改了 kernel-source我们现在要让 Yocto 重新解压源码并通过 Patch 来恢复这次修改。先恢复源码回到 kernel-sourcecd~/yocto/build-rpi2/tmp/work-shared/raspberrypi2/kernel-source确认还有修改gitstatus然后恢复gitrestore drivers/char/random.c再确认gitstatus应该看到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/kernel3. 重新编译然后执行bitbake virtual/kernel第九步验证 Patch 是否真正应用编译完成后请不要急着烧录镜像。先执行下面两个命令cd~/yocto/build-rpi2/tmp/work-shared/raspberrypi2/kernel-source/drivers/chargrep-nKernel Patch Demorandom.c892: 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.cSRC_URI “file://0001-random-init-demo.patch”bitbake virtual/kernel 会修改 random.c
返回列表