迈出为Linux贡献的第一步

本文以GPL-2.0协议授权。

Licensed under GPL-2.0.

忘了从什么时候开始,我喜欢将自己的用户名叫和Kernel相关的,就像我的GitHub用户名一样(KernelErr)。突然有一天我突发奇想,既然我叫Kernel,能不能给Linux这个大家都知道的Kernel做些贡献?于是我开始搜索相关的入门教程,阅读Linux相关书籍。

目前我已有一个驱动的cleanup和多个中文文档翻译的PATCH被采用,用中文写这篇博文的目的也在于呼吁大家有空也可以加入到内核开发的行列中来。从我的视角来看,Linux社区非常友好,如果你犯了错,大家通常会友好地指出来,不必有心理负担。同时Linux也是一个非常有名的开源项目,你的贡献总有一天可以被他人看到。

My first patch

相信你可以

前段时间从Inside Rust博客中看到了这么一篇文章:Imposter Syndrome。文章介绍了“冒名顶替”综合征这一软件社区中的问题,我们每个人知道的事物实际上是不同的,所以不必过度认为自己“不够格”或者“一无所知”。我们每个人都不是完美的,都犯过错。

Image from Inside Rust Blog licensed under Apache-2.0

从哪儿开始

内核文档中有这么一部分:Getting started with Kernel development - How the development process works,介绍了如何上手内核开发。这里我引用时奎亮 Alex Shi的中文翻译

“可以理解的是,单个开发人员往往对起步感到茫然。从一个大型项目开始可能会很吓人;人们往往想先用一些较小的东西来试试水。由此,一些开发人员开始创建修补拼写错误或轻微编码风格问题的补丁。不幸的是,这样的补丁会产生一定程度的噪音, 这会分散整个开发社区的注意力,因此,它们越来越被人不看重。希望向社区介绍自己的新开发人员将无法通过这些方式获得他们期待的反响。

在没有明显问题需要解决的情况下,通常建议开发人员查看当前的回归和开放缺陷列表。从来都不缺少需要解决的问题;通过解决这些问题,开发人员将从该过程获得经验,同时与开发社区的其他成员建立相互尊重。”

很遗憾,我的水平有限,所以我的第一个PATCH选择了做cleanup(清除不必要的大括号),从那以后我开始翻译Linux文档,个人认为文档也是一个好的贡献的点。如果你实在觉得无从下手,可以先关注一下Linux邮件列表,你可以从Majordomo lists at VGER.KERNEL.ORG中选择一个或者多个自己感兴趣的邮件列表订阅,订阅的方法就是点击subscribe,会发从一封邮件到majordomo@vger.kernel.org,其正文是订阅邮件列表的命令。注意,发送邮件时需要保证邮件的Content-Type为纯文本,许多在线邮件客户端是带有样式的,需要手动指定为纯文本。过几分钟你会收到来自服务器的确认邮件,之后你就可以收到任何发到订阅的邮件列表的邮件。

直接订阅linux-kernel列表需要三思,你的邮箱很可能一天收到几百封邮件!

订阅邮件列表的好处是你可以第一时间知道内核相关方向的动态,知道最新的PATCH,也可以参与其中。

第一个PATCH

在邮件列表中观望许久的你终于决定修改一些代码/文档,并提交第一个PATCH,这里我们以文档为例。

正确的git仓库

Linux有许多仓库,在发版的时候Linus会从各个仓库merge到他的仓库。假如我想给内核文档做贡献,我需要先知道我该clone下来哪个仓库,你可以在Linux源码树的根目录下找到MAINTAINERS文件,其中写明了源码树不同区域的维护者和仓库信息,就像这样:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
DOCUMENTATION
M:	Jonathan Corbet <corbet@lwn.net>
L:	linux-doc@vger.kernel.org
S:	Maintained
P:	Documentation/doc-guide/maintainer-profile.rst
T:	git git://git.lwn.net/linux.git docs-next
F:	Documentation/
F:	scripts/documentation-file-ref-check
F:	scripts/kernel-doc
F:	scripts/sphinx-pre-install
X:	Documentation/ABI/
X:	Documentation/admin-guide/media/
X:	Documentation/devicetree/
X:	Documentation/driver-api/media/
X:	Documentation/firmware-guide/acpi/
X:	Documentation/i2c/
X:	Documentation/power/
X:	Documentation/spi/
X:	Documentation/userspace-api/media/

那么你就可以从git://git.lwn.net/linux.git仓库的docs-next中找到最新的文档源码,并在此基础上做修改。

检查更改

Linux提供了一个脚本来检查代码、PATCH中常见的错误,其位于scripts/checkpatch.pl。作出修改后请务必先使用该脚本看看文件有没有问题:

1
./scripts/checkpatch.pl -f --terse --show-types FILE_NAME

checkpatch script

没有任何输出说明没有问题,如果有WARNING或者ERROR就需要非常注意了。脚本的具体用法可以查看文档。

commit message

当你做出你的修改并测试无误,准备好提交后,这时候需要git commit:

1
2
git add files_you_edited
git commit -s -v

你需要使用-s来添加你的签名(What is the Sign Off feature in Git for?)。之后你需要编写一个言简意赅的title和详细说明更改的body:

commit message example

需要注意的是Linux强调“one commit do one thing”,这方便维护者来审阅你的更改。所以如果你做了多个不同方向的更改,请给每个更改一个commit,而不是合成一个大commit提交。多个commit叫做“PATCH SET”。

打包 commit

git commit后,你需要打包commit并生成PATCH文件,如果你只有一个commit,可以执行下面的命令:

1
git format-patch -o /tmp/ HEAD^

如果你有多个commit需要打包成一个PATCH SET,可以执行下面的命令,需要替换FIRST COMMIT ID为包含的第一个commit id,LAST COMMIT ID为最后一个commit id:

1
git format-patch -o /tmp/ --cover-letter -n --thread=shallow [FIRST COMMIT ID]^..[LAST COMMIT ID]

发送PATCH

终于,我们准备好提交PATCH,但是等等!在哪儿提交pull request(误)?

Linux不同于GitHub上面的开源项目,你需要通过邮件发送PATCH,而不是提交pull request/merge requst。这颇有一种美好的年代感🙂。

邮件服务器的要求

首先请不要使用email relay service来发送邮件,实测表明这类服务并不能很好处理一些邮件头部信息,也不能正确处理好邮件的Message-Id

邮件客户端可以通过Message-IdIn-Reply-To来正确折叠邮件成topic的样子,而不是平行显示邮件。

其次你的邮箱服务器需要支持SMTP协议发信,非常不推荐直接通过网页邮箱来发送PATCH,这非常可能导致你的PATCH不是纯文本的!

你的邮箱服务器最好正确配置了SPF和DKIM,SPF记录可以确定邮件发自正确的邮件服务器,DKIM可以进一步确保邮件发件人地址不是伪造的。如果你的邮件服务器存在问题,这会给维护者使用b4工具审阅PATCH时造成困难。

DKIM passed

邮件客户端的要求

推荐阅读:Linux邮件客户端配置信息。目前我正在使用Thunderbird,还没遇到问题,使用推荐的邮件客户端的好处是在回复邮件时,可以以正确的格式引用原文,而不是以类似outlook的方式折叠原文。

1
2
3
4
5
Rui Li <me@lirui.org> writes:

> 嘟嘟嘟~

啦啦啦~

原文需要用>来折叠,Thunderbird等客户端会自动帮你处理好。

发送给谁

如果你不确定PATCH格式方面有没有问题,可以在发送PATCH前先发到我的邮箱 me@lirui.org ,我看到后会帮你检查格式。

Linux提供了一个脚本告诉你文件的维护者信息,运行下面的命令可以获取文件的维护者:

1
perl scripts/get_maintainer.pl --separator , --nokeywords --nogit --nogit-fallback --norolestats -f FILE_NAME

通常来说邮件的To应该是直接维护者,CC应该是邮件列表等。中文文档翻译你可以To Alex和Yanteng,CC给其他邮件地址。

发送邮件

这里我们使用git send-email来发送邮件,如果你是Debian系系统,可以安装git-emailgit send-email可以自动帮你处理好邮件的ID等细节,非常方便。如何配置还请参阅Git - git-send-email Documentation,里面有以gmail为例子的配置文件。

1
git send-email --to "..." --cc "..." PATCH_FILES

to和cc对应上面的邮件地址,PATCH_FILES可以是之前format-patch生成的一个文件,或者对应PATCH SET的多个文件。你可以先发给我试试😊:

1
git send-email --to "Rui Li <me@lirui.org>" PATCH_FILES

收到审阅

当你提交PATCH后可能有两种情况:

  • 收到Reviewed-by签名,这说明你的PATCH已经被审阅,之后请耐心等待PATCH被采用。
  • 审阅者提出了修改意见。

如果提交后几天都没有消息,还请耐心等待,大家都很忙。对于收到了修改意见的情况,还请回复修改意见邮件,表示你的态度,是否作出修改,这对其他人也有参考意义。

发送修改后的PATCH

做出修改后,需要重新写git commit message,发送更新后的PATCH。这时候除了原来的message,你还需要在签名后添加一个change log,用三个短横线分割:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
docs/zh_CN: Add userspace-api/seccomp_filter Chinese translation

Translate the following documents into Chinese:

- userspace-api/seccomp_filter.rst

Also adjust index order according to the original index file.

Signed-off-by: Rui Li <me@lirui.org>
---
Changes since v3:
- Improve translation.

Changes since v2:
- Fix some typo.

Changes since v1:
- Add a note for Seccomp.
- Fix some typo.

重新发送PATCH的方式大体上没有区别,但你需要在PATCH后添加版本号:

1
git format-patch --subject-prefix="PATCH v2" -o /tmp/ HEAD^

通过--subject-prefix可以修改前缀,添加版本号,通常第二个版本就是v2,需要添加v1的change log,告诉审阅者你做了什么修改。

遗漏的部分

如果本文遗漏了什么内容,或者你有什么疑问,欢迎通过邮件联系我,工作时间大概率秒回~(如果求职邮件可以被秒回就好了🥹)

有用的链接

写在最后

路漫漫其修远兮,吾将上下而求索。万事开头难。