图片无法显示,请右键点击新窗口打开图片


https://kernel.org/

参与 Linux 社区的主要途径是向 Linux 主线提交补丁(Patch), 本节用最简短的文字描述如何向 Linux 社区提交一个补丁. BiscuitOS 已经提供了一套补丁实践环境,可以基于该环境进行补丁提交,开发者可以参考如下命令进行部署(《BiscuitOS 用户手册》):

# 1. 切换到 BiscuitOS 项目所在的目录
cd /BiscuitOS
# 2. 根据架构选择分支,这里以 X86_64 架构为例
#    ARM32: linux-next-arm32_defconfig
#    ARM64: linux-next-arm64_defconfig
#    i386:  linux-next-i386_defconfig
#    X86:   linux-next-x86_64_defconfig 
make linux-next-x86_64_defconfig
# 3. 进入 Docker 模式
make docker
# 4. 部署环境
make

部署成功之后,可以参考 “/BiscuitOS/output/linux-next-x86_64/README.md” 介绍的部署进行部署,部署成功之后,开发者可以直接在 BiscuitOS 调试和实践补丁. 这里不对 README 的内容进行介绍,开发者自行部署, 接下来的内容认为开发者已经成功部署 Linux 补丁环境,接下来切换到 Linux NEXT 分支:

# 1. 配置 GIT 邮箱和用户名
git config --global user.name "BiscuitOS"
git config --global user.email "BiscuitOS@biscuitos.cn"
# 2. 进入到 NEXT 分支
cd /BiscuitOS/output/linux-next-x86_64/linux/linux
# 3. 获得最新 Commit
git pull

当更新最新的 Linux NEXT 分支时,如何出现黄色字体提示的异常,表明你当前的分支与远程分支有分歧(divergent branches),Git 不知道如何合并它们, 你需要明确告诉 Git 如何处理这种分歧, 这里提供了三种解决办法:

  • 使用 merge 策略: 将远程分支的更改合并到本地分支,并创建一个合并提交:
    • git config pull.rebase false
    • git pull
  • 使用 rebase 策略: 将本地提交变基到远程分支的最新提交之后:
    • git config pull.rebase true
    • git pull
  • 使用 fast-forward only 策略: 仅允许快进合并(如果无法快进,则会失败)
    • git config pull.ff only
    • git pull

如果开发者希望保持提交历史的线性,推荐使用 rebase 策略, 如果开发者不介意合并提交,可以使用 merge,如果你希望确保分支是快进更新的,可以使用 fast-forward only. 这里使用 rebase 策略,并将其作为全局默认配置:

# 1. 全局设置为 rebase 模式
git config --global pull.rebase true
# 2. 再次更新 Linux NEXT 分支
git pull

拉取最新的 Linux NEXT 分支成功之后,接下来就是开发补丁环节,开发者可以参考该过程进行开发调试. 案例在 mm/BiscuitOS.c 开发一个内核态分配器,其源码如下:

上图新增一个内核态分配器,其向外导出 BiscuitOS_tmapBiscuitOS_tunmap 函数,并在内核启动过程中会调用 BiscuitOS_init 函数. 其核心逻辑是从线性映射空间找出预留的物理内存对应的虚拟内存,将这些虚拟内存作为空闲的虚拟内存进行管理,然后提供给需要内核临时访问的时候使用,这在内核虚拟内存紧缺的场景下有用. 这里指的开发者注意的是,每开发一个新的功能,都需要一个明确且能说服其他开发者的理由,这样更容易被社区接受.

接下来在 mm 目录下的 Makefile 和 Kconfig 文件添加对 BiscuitOS.c KBUILD 逻辑. 开发者可以利用 BiscuitOS 实践环境直接验证新添加的功能是否符合需求,已经解决编译和运行时的 BUG. 待所有的问题解决之后,接下来开始制作补丁, 补丁包括两部分内容:

  • 封面补丁: 封面补丁用于描述整个补丁系列的背景和目的,让其他开发者更好更快了解你的补丁,因此在补丁合集里提供封面补丁是一种友好的行为, 建议各位开发者都提供封面补丁.
  • 代码补丁: 代码补丁就是实际的代码补丁,里面包含了基于 Linux 最新 NEXT 分支的修改,社区可以 REVIEW 补丁内容来评判补丁是否可以合入.

开发者在准备好代码之后,接下来就是生成补丁的过程,开发者参考如下命令进行生成:

# 1. 查看修改文件信息
git status
# 2. 添加补丁对应的源码
git add mm/BiscuitOS.c mm/Makefile mm/Kconfig
# 3. 添加 COMMIT 描述
git commit -s -v

确认添加补丁涉及的文件之后,使用 “git commit” 命令生成 COMMIT Information,其中 “-s” 选项可以在 Commit 信息下加上类似 “Signed-off-by: BiscuitOS <BiscuitOS@biscuitos.cn>“,”-v” 参数会在 Commit 信息下方显示修改代码信息,确保所有改动都包含进来. 执行该命令之后会进入 vim 编辑模式,那么开发者根据修改的代码的内容进行描述:

Commit 信息有严格的限制,开发者需要严格准守,每部分的要求如下:

  • 第一部分: “short description”, 以子系统名打头,比如案例修改的是内存管理子系统,因此使用 mm 打头,然后 mm 后面使用分号,分号后面紧跟一个空格.
  • 第二部分: “the body of your patch”, 这部分要详细的解释为何要做这样的修改,以及怎么做,注意时态用现在时,语态用主动形式。英文不好的开发者用 DeepSeek 进行辅助.
  • 第三部分: 第三部分是 “-s” 参数自动加上的,另外还有 “-v” 参数自动加入的补丁内容.

需要注意的是,这三部分之间都用一个空行隔开. 如果 Commit 之后还想修改 Commit 信息,可以使用 “git commit –amend -v -s”. Commit 制作完毕之后,接下来生成补丁,首先制作封面补丁,使用如下命令:

# 1. 生成补丁系列(基于 master 分支)
git format-patch -o /path/to/patches/ -v1 --subject-prefix='RFC' --cover-letter HEAD~1
# OR. 生成补丁系列(基于非 master 分支)
git format-patch -o /path/to/patches/ -v1 --subject-prefix='RFC' --cover-letter master
  • -o /path/to/patches/: 用于指定生成封面补丁的位置,如果没有该选项,则默认在当前目录生成封面补丁.
  • -v1: 指定补丁系列的版本号(例如 v1)
  • –subject-prefix: 邮件标题添加前缀,不同的前缀让内核开发者更好的讨论, 其可以设置为以下几种类型
    • PATCH: 常规且正式的补丁
    • RFC: 非正式补丁,希望内核其他开发者一起讨论该补丁,用来说明方向看看社区的意见
    • RESEND: 邮件发过好几周都没有人鸟,可能被遗忘重新发送
  • –cover-letter: 表示生成封面补丁文件
  • HEAD~1: 如果补丁直接在 master 分支上生成,则 “HEAD~n” 表示从最新 Commit 到第 n 个 Commit 补丁作为补丁集.
  • master: 如果补丁在其他分支上生成,然后补丁集合则是相对于 master 分支新增的补丁.

命令执行完毕之后,会在 “/path/to/patches” 目录下生成 0000-cover-letter.patch 封面补丁文件, 以及代码补丁文件. 接下来编辑封面补丁文件, 生成的 “0000-cover-letter.patch” 文件是一个模板,开发者需要编辑它以提供补丁系列的详细信息.

上图就是自动生成的封面补丁模板,开发者基于这个模板对补丁系列的背景和目的进行说明,其中 *** SUBJECT HERE *** 为补丁合集的简要描述, *** BLURB HERE *** 为补丁合集的背景以及目的描述,尽可能描述情况,让其他内核开发者更好的了解补丁要解决问题的目的.

上图是案例对应的封面补丁,补丁了介绍了分配器要解决的问题背景,以及分配器的基础使用,开发者尽可能的将封面补丁描述情况,这样其他内核开发者才能更好理解你的意图,这样才能更好的合入 Linux 主线. 封面补丁和代码补丁准备好之后,接下来检查 patch 格式,使用如下命令:

# 1. 使用内核提供的检查工具
./scripts/checkpatch.pl  v1-0001-mm-BiscuitOS-Memory-Allocator.patch

当执行补丁检查工具之后,此时会将异常的地方检测出来,接下来开发者根据建议重新修改源码,源码修改完毕之后使用如下命令:

# 1. 检查修改的文件
git status
# 2. 将修改的文件添加到补丁
git add mm/BiscuitOS.c mm/Kconfig
# 3. Commit 追加修改, 修改完毕之后保存退出
git commit --amend -s -v
# 4. 重新生成代码补丁
git format-patch -o /path/to/patches/ -v1 --subject-prefix='RFC' HEAD~1
# 5. 重新检查补丁
./scripts/checkpatch.pl  v1-0001-mm-BiscuitOS-Memory-Allocator.patch

检查补丁有问题是很常见的问题,开发者可以根据上面的步骤不断重新生成补丁,直到 checkpatch.pl 没有检查出 ERROR 为止. 开发者注意不要向社区发送还存在 ERROR 的 patch,不然会被喷的很惨. 接下来就是发送补丁,再发送之前请确认 git send-email 是否已经配置好,如果没有请参考如下:

# 1. 安装 git send-email
sudo apt update
sudo apt install -y git-email
# 2. 检查 git send-email 已经安装成功
git send-email --help
# 3. 配置邮件服务器
vi ~/.gitconfig

smtpServer 替换成开发者使用邮箱的 SMTP 服务器,例如开发者使用 gmail 邮箱,那么 SMTP 服务器邮箱就是: “smtp.gmail.com”. smtpUser 替换成开发者的邮箱,接下来测试能否正常发送, 使用如下命令:

# 1. 向自己的邮箱发送补丁测试看看
git send-email --to biscuitos@biscuitos.cn --cc biscuitos@biscuitos.cn v1-0001-mm-BiscuitOS-Memory-Allocator.patch

当发送成功之后,会在指定的邮箱中收到补丁文件的内容,那么说明邮件可以正常发送. 当开发者准备好补丁文件,那么补丁发给谁呢? 当然发给社区和 Maintainer,接下来获得 Maintainer 的邮箱,使用如下命令:

# 1. 根据 Patch 找出 maintainer
./scripts/get_maintainer.pl v1-0001-mm-BiscuitOS-Memory-Allocator.patch

“get_maintainer.pl” 脚本会找出补丁涉及的 maintainer,然后根据获得列表作为收邮件的对象,开发者也可以根据自己的需求提供抄送的对象. 一切准备好了,接下来就是正式向社区发送补丁,使用下面命令:

git send-email --to akpm@linux-foundation.org --to linux-kernel@vger.kernel.org --to linux-mm@kvack.org --cc maintainers@lists.example.com /path/to/patches/\*.patch

当成功提交补丁之后,可以在 《Project ListL - Patchwork》 查看对应的子系统,就可以看到刚刚提交的补丁. 也可以在订阅内核邮件列表邮箱里收到刚刚发送的邮件. 接下来的日子就是等待内核开发者对该邮件的回复. 但收到内核开发者回复之后,可以和他一同讨论该补丁,如果需要对补丁进行修改,可以参考如下命令:

# 1. 参考建议,修改源码

# 2. 检查修改的文件
git status
# 3. 将修改的文件添加到补丁
git add mm/BiscuitOS.c mm/Kconfig
# 4. Commit 追加修改, 修改完毕之后保存退出
git commit --amend -s -v
# 5. 重新生成代码补丁
git format-patch -o /path/to/patches/ -v2 --subject-prefix='RFC' HEAD~1
# 6. 重新检查补丁
./scripts/checkpatch.pl  v2-0001-mm-BiscuitOS-Memory-Allocator.patch

这里值得注意的是,开发者在使用 “git format-patch” 生成 patch 的时候,启用一个新的版本号,例如这次使用 v2,那么社区开发者就会 REVIEW 最新的 V2 版本,而不是 V1 版本,V1 版本自动失效. 做完上面的操作之后,再次发送邮件. 往复上面的动作,直到 Patch 被社区接收为止,这是一个漫长的过程,也是一个学习的过程,望各位坚持到最后,以上便是向社区提交 Patch 的全过程.


获得 Linux 主线最新信息首选 《Github: Torvalds/Linux》, 开发者可以使用克隆该仓库到本地,然后查看主线最新合入的 Patch.

LWN.net 是获得 Linux 最新内容不错的网站,特别带封面补丁的内容都会被收录进来,可以在 Articles 专栏 查看文章描述. 另外 LWN Kernel Index 专栏 将文章按子系统进行归类整理.

Linux-Kernel Archive 网站的特点是可以按时间将补丁进行分类进行查看,例如在某段时间内按作者提交的补丁进行查看,有利于读者从头到位的完整查看补丁的发展历史.


开发者在学习某个子系统时,想了解该子系统的发展历史,那么如何更好的获得某个子系统的历史称为了棘手问题,目前有很多方法可以获得,这里介绍一个最简单的办法。首先基于 BiscuitOS 部署最新的的内核代码,参考如下命令:(《BiscuitOS 用户手册》):

# 1. 切换到 BiscuitOS 项目所在的目录
cd /BiscuitOS
# 2. 根据架构选择分支,这里以 X86_64 架构为例
#    ARM32: linux-newest-arm32_defconfig
#    ARM64: linux-newest-arm64_defconfig
#    i386:  linux-newest-i386_defconfig
#    X86:   linux-newest-x86_64_defconfig 
make linux-newest-x86_64_defconfig
# 3. 进入 Docker 模式
make docker
# 4. 部署环境
make
# 5. 部署完毕进入最新 Linux 源码
cd /BiscuitOS/output/linux-newest-x86_64/linux/linux

开发者安装 VSCODE,然后为最新 Linux 源码建立项目,建立完毕之后可以使用 VSCODE 查看源码.

安装 Git History 插件

插件安装完毕之后,像看哪一行代码的历史,可以选中代码之后,单击右键选择 Git: View Line History

如果想看整个文件的历史,可以点击右键选择 Git: View File History.


首先登录 《Vger.kernel.org》 选择喜欢的子系统,例如选择 linux-kernel(The Linux Kernel Mailing List).

登录个人邮箱,然后写一封邮件,邮件收件人为 majordomo@vger.kernel.org, 邮件的主题和内容都是 subscribe linux-kernel, 发送完毕之后就可以收到内核邮件了,这里需要注意每天邮件数量最大,可能会把邮箱挤爆.