9.4 贡献自己的第一个patch
9.4.1 提交代码
从哪里入手找到提交代码的机会呢?如果你没有遇到一个切实的bug,那么可用考虑以下几个方面
- 消除编译警告
- 整改编码格式,例如对齐不规范、代码格式不符合社区要求。
- 修正或增加必要的注释,例如单词拼写错误
- 认领社区邮件列表中的bug
找到一个问题之后,必须在当前最新的开发分支上验证此问题是否存在,否则你可能做的是无用功。例如针对https://source.denx.de/Xenomai/xenomai,应该使用next分支来验证此问题。
修复问题时,需要注意编码规范。Xenomai遵照Linux内核的编码规则,这是中文版本的链接:https://www.kernel.org/doc/html/latest/translations/zh_CN/process/coding-style.html
修改代码后,最终会使用git commit来提交代码到本地分支,通常要使用-s、-m 和 -e选项。
bash
git commit -s -m "子系统: 一句话总结提交信息" -e
1. -s 参数
在提交信息的末尾自动添加一行 Signed-off-by: Your Name <your.email@example.com>,其中 Your Name 和 your.email@example.com 是你的 Git 配置中的用户名和邮箱(通过 git config user.name 和 git config user.email 设置)。
2. -m 参数
-m后面必须跟随一个描述信息,简明扼要的总结patch的更改以及为什么需要patch。这个描述信息将会作为patch的标题。通常推荐的写法是:"子系统: 一句话总结提交信息",例如"lib/cobalt: Fix a deadlock when release_buffer() attempts to re-acquire buffer_lock"
3. -e 参数
-e 会打开默认的文本编辑器(当前已经配置为Vim),进一步编写patch的主体说明信息。此处可以详细的展开补丁处理的故障症状(内核日志消息、oops消息等),问题发生的原理,修复问题的思路。可以通过阅读Xenomai邮件列表,来学习具体的写法。编写完成后,在vim中输入:wq即可保存并退出,完成代码的提交。
最后,如果发现在-m和-e中已经编写的描述信息有误,可以使用git commit --amend来重新修改并提交。
9.4.2 生成patch文件
当你走到这一步的时候,说明你已经成功解决了一个问题!一般来说,应该确保一次代码提交仅解决一个问题,避免尝试解决多个问题。除非遇到复杂问题,可能需要按步骤或按模块拆分成多次代码提交。对于初学者来说,这种复杂情况暂时应该不会遇到。
假定你找到了一个问题,并仅提交了一次代码,就把问题完美解决了。在这种情况下,你仅需要一个简单的命令即可生成patch文件。
bash
git format-patch -1
git format-patch -1 是 Git 中用于生成补丁文件的命令,表示基于最近的一次提交(即最新的 1 次提交)创建一个补丁文件。补丁文件包含了本次提交相对于其父提交的更改内容,包括代码差异、提交信息等。补丁文件默认存放在当前目录,文件名中包含提交信息的主题,例如生成 0001-commit-message.patch 补丁文件。
即使你还没有自己提交代码,也可以在本地Xenomai代码仓库中,根据已有的代码提交记录生成一个示例补丁文件。例如git checkout next切换到next分支,执行git format-patch -1,会生成0001-cobalt-dovetail-Fill-fault-statistics-counters.patch补丁文件。
vim
From 5fd9dfd746c922bf9e90d17be40e4dd39d34a42e Mon Sep 17 00:00:00 2001
From: Richard Weinberger <richard@nod.at>
Date: Fri, 4 Apr 2025 21:08:57 +0200
Subject: [PATCH] cobalt/dovetail: Fill fault statistics counters
/proc/xenomai/faults reports always zeros on dovetail.
Looks like filling these counters was forgotten
for the dovetail case.
Signed-off-by: Richard Weinberger <richard@nod.at>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
kernel/cobalt/dovetail/kevents.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/kernel/cobalt/dovetail/kevents.c b/kernel/cobalt/dovetail/kevents.c
index 0f70dbc27..9fa75faa1 100644
--- a/kernel/cobalt/dovetail/kevents.c
+++ b/kernel/cobalt/dovetail/kevents.c
@@ -43,6 +43,8 @@ void handle_oob_trap_entry(unsigned int trapnr, struct pt_regs *regs)
*/
trace_cobalt_thread_fault(xnarch_fault_pc(regs), trapnr);
+ raw_cpu_ptr(&cobalt_machine_cpudata)->faults[trapnr]++;
+
if (xnthread_test_state(thread, XNROOT))
return;
--
2.34.1
1. 补丁头部信息
plaintext
From 5fd9dfd746c922bf9e90d17be40e4dd39d34a42e Mon Sep 17 00:00:00 2001
From: Richard Weinberger <richard@nod.at>
Date: Fri, 4 Apr 2025 21:08:57 +0200
Subject: [PATCH] cobalt/dovetail: Fill fault statistics counters
- From: 提交的哈希值(唯一标识该提交)。
- From: 提交作者的名字和邮箱地址。
- Date: 提交的时间戳。
- Subject: 提交的主题,简要描述了这次更改的目的。一般都会自动加上[PATCH]前缀。Maintainer的邮箱每天可能会收到数百封邮件,[PATCH]前缀可以用来快速辨别辨别是否是一个包含补丁的邮件。
2. 提交信息正文
plaintext
/proc/xenomai/faults reports always zeros on dovetail.
Looks like filling these counters was forgotten
for the dovetail case.
Signed-off-by: Richard Weinberger <richard@nod.at>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
- 提交的详细说明 :
- 描述了问题:
/proc/xenomai/faults在dovetail上总是报告为零,因为统计计数器未被正确填充。 - 提供了解决方案:修复了这个问题。
- 描述了问题:
- Signed-off-by: 表示提交者和审核者的签名,通常用于确认代码符合项目的贡献协议。
3. 更改摘要
plaintext
---
kernel/cobalt/dovetail/kevents.c | 2 ++
1 file changed, 2 insertions(+)
---后面跟随的内容,总结了更改的影响:---代表了此部分的内容并不会最终进入提交的记录。假设你有一些信息需要在patch文件中补充,但是这些信息并不需要进入最终的提交记录,那么可以用vim编辑patch文件,在---后面补充信息。- 这个patch修改了一个文件
kernel/cobalt/dovetail/kevents.c,增加了两行代码。
4. 代码差异部分
diff
diff --git a/kernel/cobalt/dovetail/kevents.c b/kernel/cobalt/dovetail/kevents.c
index 0f70dbc27..9fa75faa1 100644
--- a/kernel/cobalt/dovetail/kevents.c
+++ b/kernel/cobalt/dovetail/kevents.c
@@ -43,6 +43,8 @@ void handle_oob_trap_entry(unsigned int trapnr, struct pt_regs *regs)
*/
trace_cobalt_thread_fault(xnarch_fault_pc(regs), trapnr);
+ raw_cpu_ptr(&cobalt_machine_cpudata)->faults[trapnr]++;
+
if (xnthread_test_state(thread, XNROOT))
return;
- diff --git: 指明了被修改的文件路径。
- index : 显示文件的 Git 对象哈希值以及文件权限(
100644表示普通文件)。 - --- a/... 和 +++ b/...: 分别表示旧版本和新版本的文件。
- @@ ... @@: 指定了修改的代码范围(行号)。
- + 行: 新增的代码行。
- - 行: 删除的代码行。
9.4.3 发送patch
Patch文件已经准备好了,万事俱备,只差东风。现在只需要一行命令,就可以把patch发送出去!
现在你可能踌躇满志,但是要提醒你的是,做为新手,还有两件事情必须做。
第一,使用Linux内核源码scripts目录提供的checkpatch.pl来检查patch文件。
checkpatch.pl会检查编码风格,例如缩进、每行不超过 80 个字符、if等控制结构的括号格式是否正确等。它还会检查命名规范、代码逻辑问题、补丁格式问题等等,最终会给出修改建议。
假设你下载了Dovetail的源码到linux-dovetail目录,你可以执行如下命令,完成检查。当然,在当前的例子中并没有发现任何需要更改的地方。
bash
# ~/linux-dovetail/scripts/checkpatch.pl ./0001-cobalt-dovetail-Fill-fault-statistics-counters.patch
total: 0 errors, 0 warnings, 8 lines checked
./0001-cobalt-dovetail-Fill-fault-statistics-counters.patch has no obvious style problems and is ready for submission.
第二,一定要首先发送到自己的邮箱,检查收到的邮件是否符合预期。
通过git send-email来发送patch文件。注意以下仅仅是一个例子,不要真正发送。你需要把邮箱和patch文件换成你自己的。
bash
git send-email --to julizi2025@163.com 0001-cobalt-dovetail-Fill-fault-statistics-counters.patch
发送到自己的邮箱后,往往能发现一些初级错误。这样既可以提高patch被review通过的几率,同时也避免给Maintainer留下不堪的第一印象。
最后,终于可以放心的把patch发送出去了,发送给谁呢?
bash
git send-email \
--to rpm@xenomai.org,jan.kiszka@siemens.com,florian.bezdeka@siemens.com \
--cc xenomai@lists.linux.dev \
0001-cobalt-dovetail-Fill-fault-statistics-counters.patch
- 发送给Xenomai的Maintainer
- Jan Kiszka jan.kiszka@siemens.com
- Philippe Gerum rpm@xenomai.org
- Florian Bezdeka florian.bezdeka@siemens.com
- 抄送Xenomai社区邮件列表
- xenomai@lists.linux.dev
发送成功后,在https://lore.kernel.org/xenomai/社区邮件列表中,很快就能看到你发送的patch邮件了。
9.4.4 修正patch并重新发送
当你走到这一步时,也许你会非常沮丧,因为你的patch被Maintainer拒绝了。拒绝的原因可能有很多种,例如虽然你已经很小心了,但是仍然有语法或格式的问题;或者你的修改思路并不符合一些最佳实践例如锁的使用原则等等;或者是需要你补充更多的错误现象信息,等等。
不过,你应该庆幸自己已经成功迈出了第一步,并且开始和Maintainer世界一流的大师进行交流。收到反馈总比patch邮件石沉大海要好的多!
你需要仔细思考并推敲Maintainer的想法和意图,通过回复邮件讨论并确定修改方向,然后开始准备第二版patch。
准备patch的步骤和之前是一样的,当你生成第二版patch后,你需要做两个比较小的改动。
第一,把标题中的[PATCH]前缀改为[PATCH v2]
用vim打开patch文件后,找到Subject:,修改前缀为[PATCH v2]。
bash
Subject: [PATCH v2] cobalt/dovetail: Fill fault statistics counters
第二,在---后增加修改记录Changelog
不要指望Maintainer能够记住你的第一版patch甚至他当时回复的意见。可以通过增加简短的修改记录来唤醒Maintainer的记忆,避免重新思考,重新讨论,避免问题进一步发散。
这部分并没有固定的格式要求,举两个常见的例子:
- 在
---后面描述历史修改记录
bash
---
Patch v2:
- Use the pthread_setcancelstate() function to set the thread state
to PTHREAD_CANCEL_DISABLE.
Patch v3:
- Add backtrace output in gdb.
- 在
---后直接放上之前讨论的链接
bash
---
Changes in v2:
- fold in https://lore.kernel.org/xenomai/78dbe3b5-55d5-440e-9b62-45db1f2add5c@siemens.com/T/#u
确保你已经准备好了第二版甚至第三版patch文件,按照之前提到的检查方法检查后,可以使用git send-email发送出去了。
9.4.5 进阶:生成patch set补丁集合
通过前面的章节,你可能已经非常熟练的与Xenomai社区沟通协作了!也许你会发现一个大的功能变化或重大bug,涉及多个模块或文件的改动,必须多次提交代码,最终生成多个patch。
1. 生成多个补丁及 Cover Letter
Git 提供了 git format-patch 命令来生成补丁文件,并支持通过 --cover-letter 参数生成一个封面信。
bash
git format-patch -<n> --cover-letter --thread=shallow --subject-prefix="PATCH v1" origin/main
-<n>: 指定要生成的最近几次提交的补丁。例如-3表示生成最近的 3 次提交。--cover-letter: 生成一个封面信模板文件。--thread=shallow: 为补丁系列启用浅层线程模式,使邮件客户端能够正确组织补丁。--subject-prefix="PATCH v1": 自定义补丁主题前缀(默认是PATCH,可以改为PATCH v1等)。origin/main: 指定基准分支(通常是上游分支),表示基于此分支生成补丁。
2. 生成的文件结构
执行上述命令后,会生成以下文件:
- Cover Letter 文件 :
- 文件名类似于:
0000-cover-letter.patch - 这是一个模板文件,你需要手动编辑它以添加详细说明。
- 文件名类似于:
- 补丁文件 :
- 文件名类似于:
0001-commit-message.patch,0002-commit-message.patch, ... - 每个补丁文件对应一次提交。
- 文件名类似于:
3. 编辑 Cover Letter
生成的 0000-cover-letter.patch 文件包含以下内容:
plaintext
From: Your Name <your.email@example.com>
Subject: [PATCH 0/X] Subject of the patch series
This is the cover letter for the patch series.
It should provide an overview of the changes, why they are needed,
and any other relevant information.
Signed-off-by: Your Name <your.email@example.com>
---
- 填写内容 :
- 在
Subject中简要描述整个补丁系列的主题。 - 在正文中详细说明:
- 补丁系列的目的。
- 各个补丁之间的关系。
- 测试结果或已知问题。
- 在
4. 发送补丁
使用 git send-email 发送补丁文件,包括封面信和所有补丁文件。
bash
git send-email \
--to rpm@xenomai.org,jan.kiszka@siemens.com,florian.bezdeka@siemens.com \
--cc xenomai@lists.linux.dev \
*.patch
*.patch: 包括封面信和所有补丁文件。--to和--cc: 指定收件人和抄送人。
当你把patch集合发送出去之后,你在Xenomai社区邮件列表中,会观察到类似这样的情况:

在发送出第一个邮件即Cover Letter后,补丁系列后续的每封邮件都直接回复到封面信(Cover Letter)。
这是因为在git format-patch命令中使用了--thread=shallow浅线程模式。浅线程模式的核心,是让邮件头中的In-Reply-To和References字段,指向Cover Letter中Message-Id,将所有补丁邮件直接关联到Cover Letter,形成了一个扁平化的线程结构。
bash
Cover Letter
├── Patch 1
├── Patch 2
└── Patch 3
在发送出第一个邮件即Cover Letter后,补丁系列后续的每封邮件都直接回复到封面信(Cover Letter)。
这是因为在git format-patch命令中使用了--thread=shallow浅线程模式。浅线程模式的核心,是让邮件头中的In-Reply-To和References字段,指向Cover Letter中Message-Id,将所有补丁邮件直接关联到Cover Letter,形成了一个扁平化的线程结构。
bash
Cover Letter
├── Patch 1
├── Patch 2
└── Patch 3