目录
其实给Linux提交补丁patch 代码并不是意料之内的事,虽然以前也挺羡慕有能力或者有机会给Linux内核提交代码的人,但是平时并没有在意这个事。这次事在我给自己的笔记本安装Linux的过程中发现的问题,然后才想着顺手解决一下并提交~因此写一篇博客记录一下,也把提交的流程分享跟更多的人~
构建内核 准备工作 首先当然是拉代码。如果从官方的git 直接拉比较慢的话,可以用国内的镜像,例如清华TUNA的源 安装编译依赖: sudo apt install -y build-essential libncurses-dev bison flex libssl-dev libelf-dev dwarves git bc wget gawk 配置内核编译参数:推荐用make olddefconfig这个命令从当前的linux内核拷贝配置,然后可以再通过make menuconfig去进一步定制化。
踩过的坑
在编译过程中我碰到了这个报错:
1
2
3
make[3]: *** 没有规则可制作目标“debian/canonical-certs.pem”,由“certs/x509_certificate_list” 需求。 停止。
make[2]: *** [scripts/Makefile.build:556:certs] 错误 2
make[2]: *** 正在等待未完成的任务....
其根本原因应该是linux内核的源码没有Ubuntu打包的一些证书。解决方案是在配置编译参数时把pem文件的路径清空,具体修改界面在make menuconfig的这个位置:
编译及安装 编译很简答,就是直接make。不过编译时推荐使用CCache加速,因为linux内核没有用cmake或者ninja之类的编译工具。
使用CCache
安装CCache直接apt就可以:apt install ccache。在安装完成之后可以调整ccache的一些参数,例如设置缓存路径:export CCACHE_DIR=<you_location>,设置缓存大小为2G:ccache -M 2G。
注:Linux编译在我的笔记本上CCache大概占用4G空间。
编译完成后安装使用下面这些命令:
1
2
3
4
5
6
7
8
9
10
# 编译并安装模块
sudo make modules_install -j$( nproc)
# 安装内核
sudo make install -j$( nproc)
# 更新 GRUB 并重启
sudo update-initramfs -c -k all
sudo update-grub
sudo reboot
SHELL
安装完后测试新内核是否有安装成功:uname -r
踩过的坑
在make install这个过程中我碰到amdgpu驱动编译的问题:
1
2
3
4
5
6
7
8
9
depmod...
dkms autoinstall on 6.18.0-rc6+/x86_64 succeeded for system76-io system76 system76_acpi
dkms autoinstall on 6.18.0-rc6+/x86_64 failed for amdgpu(10)
Error! One or more modules failed to install during autoinstall.
Refer to previous errors for more information.
* dkms: autoinstall for kernel 6.18.0-rc6+ [fail]
run-parts: /etc/kernel/postinst.d/dkms exited with return code 11
make[1]: *** [arch/x86/Makefile:317:install] 错误 11
make: *** [Makefile:248:__sub-make] 错误 2
让豆包老师看了下,这个错误是 DKMS 模块编译失败(主要是 amdgpu 驱动),但不影响新内核本身安装,关键是关闭 Secure Boot 并跳过 DKMS 自动编译,就能正常使用新内核。因此在这里可以直接忽略,直接跳到后面的update-initramfs和update-grab即可。
我的修改 在编译成功内核后就可以着手修改啦~我的电脑的问题是静音键的指示灯跟系统静音状态不同步,搜索了一下其实还有挺多人碰到了这个问题,最后是在archlinux论坛的一个帖子里 找到了怎么修改,实际上就是要在音频驱动里面针对机型增加一个音频相关的quirk特例修改 。(对于其他指示灯,例如闭麦指示灯,内核的实现逻辑也是类似的)
寻找修改 Linux里面的quirk是针对每个机型都有一行宏定义(内核源码在这里 ),这个定义需要一个system id和device id,需要在alsa info中寻找。运行alsa-info这个命令可以获得一个系统音频驱动的诊断信息 ,对于这次的修改来说的关键信息是:
Subsystem Id: 0x103c8bd6 Product Name: HP Pavilion Aero Laptop 13z-be200
这里的Subsystem ID拆成前四位和后四位即为内核代码中SND_PCI_QUIRK这个宏的前两个参数,因此我只需要参考别的HP Pavilion机型的quirk依葫芦画瓢即可。Subsystem ID相关的介绍还可以参考linux内核文档的音频部分 。
如果你的机型没有可参考的quirk,或者参考的quirk在你的机型上并不能用,那么你就需要参考之前提到的archlinux论坛帖子 里使用的脚本来暴力逆向工程出来怎么实现指示灯的控制了。
提交修改 修改完,验证好修复有效之后自然就是提交代码了。给linux提交代码和给普通仓库提交代码没有本质区别,最大的区别只是最后提交的时候不是git push,而是生成一个patch文件,并且通过邮件发给linux的邮件列表(需要找到对应模块的邮件列表和维护者,然后邮件发送给其中一个维护者,并且抄送邮件列表)。
生成补丁 SHELL
1
2
3
4
5
6
7
8
9
# 创建一个新分支进行开发
git checkout -b my-feature
# 修改代码后,提交更改
git add <修改的文件>
git commit -s # -s 会自动添加 Signed-off-by 信息,对于给内核提交代码来说这个是必须的
# 生成补丁
git format-patch -1 # 生成最近一次提交的补丁,假设生成0001-my-feature.patch文件
检查补丁格式 SHELL
1
2
3
4
5
# 安装内核补丁检查工具
sudo apt install -y linux-tools-common
# 检查补丁格式
./scripts/checkpatch.pl 0001-my-feature.patch
发送补丁 SHELL
1
2
3
4
5
6
7
8
# 安装依赖
sudo apt install -y git-email
# 发送补丁
git send-email --to= maintainer@example.com --cc= linux-kernel@vger.kernel.org 0001-my-feature.patch
# 以下是我实际执行的发送命令
git send-email --to= tiwai@suse.com --cc= alsa-devel@alsa-project.org --cc= linux-kernel@vger.kernel.org 0001-add-the-SND-quirk-for-HP-pavilion-aero-laptop-13z-be.patch
在发送邮件之前,你还需要提前给git设置好SMTP服务器,参考教程git文档 或者这个stackoverflow回答 。
提交之后,你的patch便会显示在linux邮件列表中,例如我的提交就在上面 。
清理内核 在测试完内核之后,如果你想用回原来的稳定内核,那可以参考下面这段操作。
豆包老师最开始的建议是:
1
2
3
# 删除新内核(替换为你的内核版本号)
sudo apt purge linux-image-6.8.0-mycustom
sudo update-grub
SHELL
但由于我make install没成功,因此只能手动删除文件了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1. 删除 /boot 目录下的新内核文件
sudo rm -f /boot/config-6.18.0-rc6+
sudo rm -f /boot/initrd.img-6.18.0-rc6+
sudo rm -f /boot/System.map-6.18.0-rc6+
sudo rm -f /boot/vmlinuz-6.18.0-rc6+
# update vmlinuz linking (optional. system boots based on grub)
sudo rm /boot/vmlinuz
sudo ln -s /boot/vmlinuz-6.16.3-76061603-generic /boot/vmlinuz
# 2. 删除 /lib/modules 下的新内核模块目录,避免残留
sudo rm -rf /lib/modules/6.18.0-rc6+
# 3. 更新 grub (不过我用的 popos 好像不用grub? 因此我实际上没有执行这最后一步)
sudo update-grub
SHELL
以上就是这次内核补丁提交的过程了,希望能帮到大家~