Skip to content

第二百零三章:邮件列表

飞升期

涉及内核源码:

林小源离开补丁殿,来到一片浩瀚的信息之海。海面上漂浮着无数发光的信笺,每一封都在缓缓飘向远方。海的中央竖着一块巨大的石碑,上书"LKML"三个大字。

一位穿着灰色长袍的信使从海面上踏浪而来,手中握着一沓邮件。他的脸上带着风尘仆仆的疲惫,但眼神依然锐利。

"你要往内核提交补丁,"信使开口,声音沙哑,"就必须学会用邮件列表。"

林小源环顾四周,看着满天飞舞的信笺:"这些邮件……都是补丁?"

"不只是补丁,"信使摇头,"邮件列表是内核开发的全部通信。补丁、讨论、审查、争论——一切都在邮件中进行。没有聊天室,没有即时消息,只有邮件。"

信使将手中的邮件递给林小源。第一封来自 列表,是一段网络驱动的修改;第二封来自 linux-fsdevel,是文件系统的讨论;第三封来自 linux-mm,是内存管理的审查意见。

"子系统有自己的邮件列表,"信使解释道,"补丁要发到正确的列表。发错了,维护者可能看不到。"

他又抖开一张羊皮纸,上面写着

"先找人,再发信。"信使说,"看 里的维护者、列表和树,再用 辅助确认。默认可以抄送 linux-kernel,但不要把不相关的人和列表拖进来。若改了用户空间接口,还要让 linux-api 和手册维护者知道;若是严重安全问题,不能先发公开列表,要走安全报告路径。"

林小源望着邮件之海,忽然意识到:发补丁不是把信扔进大海,而是把一封需要被正确的人读到的信,送到正确的渡口。

c
/*
 * 邮件列表:
 *
 * LKML (Linux Kernel Mailing List):
 *   linux-kernel@vger.kernel.org
 *   内核主要邮件列表
 *
 * 子系统邮件列表:
 *   netdev — 网络子系统
 *   linux-fsdevel — 文件系统
 *   linux-mm — 内存管理
 *
 * 邮件礼仪:
 *   1. 纯文本邮件
 *   2. 不要 HTML
 *   3. 不要附件 (补丁用内联)
 *   4. 引用适当
 *   5. 不要顶部回复
 *
 * 补丁邮件:
 *   Subject: [PATCH 0/3] 子系统: 系列描述
 *   Subject: [PATCH 1/3] 子系统: 第一个补丁
 *   Subject: [PATCH 2/3] 子系统: 第二个补丁
 *   Subject: [PATCH 3/3] 子系统: 第三个补丁
 *
 * 工具:
 *   git send-email — 发送补丁
 *   mutt — 邮件客户端
 *   Thunderbird — 邮件客户端
 */

/* 模拟邮件 */
struct email {
    char from[64];
    char to[64];
    char subject[128];
    char body[512];
};

void print_email(struct email *e) {
    printf("From: %s\n", e->from);
    printf("To: %s\n", e->to);
    printf("Subject: %s\n\n", e->subject);
    printf("%s\n", e->body);
}

printf("=== 邮件列表 — 内核的通信 ===\n\n");

printf("内核开发通过邮件列表协作:\n\n");

/* 示例邮件 */
struct email patch_email = {
    .from = "林小源 <linxiaoyuan@kernel.org>",
    .to = "linux-kernel@vger.kernel.org",
    .subject = "[PATCH] ext4: fix memory leak in ext4_fill_super",
    .body = "Fix a memory leak in ext4_fill_super() where\n"
            "the super block buffer head was not released\n"
            "on error path.\n\n"
            "Signed-off-by: 林小源 <linxiaoyuan@kernel.org>\n"
            "---\n"
            " fs/ext4/super.c | 5 +++--\n"
            " 1 file changed, 3 insertions(+), 2 deletions(-)"
};

printf("--- 补丁邮件示例 ---\n");
print_email(&patch_email);

printf("\n--- 邮件列表 ---\n");
printf("LKML:\n");
printf("  linux-kernel@vger.kernel.org\n");
printf("  内核主要邮件列表\n\n");
printf("子系统邮件列表:\n");
printf("  netdev — 网络子系统\n");
printf("  linux-fsdevel — 文件系统\n");
printf("  linux-mm — 内存管理\n\n");

printf("--- 邮件礼仪 ---\n");
printf("1. 纯文本邮件\n");
printf("   不要 HTML\n\n");
printf("2. 不要附件\n");
printf("   补丁用内联\n\n");
printf("3. 引用适当\n");
printf("   只引用相关部分\n\n");
printf("4. 不要顶部回复\n");
printf("   在引用下方回复\n\n");

printf("5. 找对收件人\n");
printf("   MAINTAINERS + scripts/get_maintainer.pl\n");
printf("   抄送相关维护者和列表\n\n");

printf("--- 补丁系列 ---\n");
printf("[PATCH 0/3] 系列描述\n");
printf("[PATCH 1/3] 第一个补丁\n");
printf("[PATCH 2/3] 第二个补丁\n");
printf("[PATCH 3/3] 第三个补丁\n\n");

printf("--- 工具 ---\n");
printf("git send-email:\n");
printf("  发送补丁\n");
printf("  配置 SMTP\n\n");
printf("mutt:\n");
printf("  终端邮件客户端\n\n");
printf("Thunderbird:\n");
printf("  图形邮件客户端\n");
printf("  需要配置纯文本\n");
破关试炼

收件之试

发送补丁前,查找相关维护者和邮件列表的核心文件名是什么?

答对后才能继续滑动和进入下一章。

信使从海面上捞起一封邮件,邮件的正文被各种花哨的格式包围——彩色字体、嵌入图片、HTML 标签。

"你看这封邮件,"信使皱着眉头,"用 Thunderbird 发的 HTML 邮件。在我的终端里,全是乱码。在 Greg 的终端里,也全是乱码。在 Linus 的终端里——"他顿了顿,"Linus 根本不会打开这种邮件。"

林小源接过那封邮件,果然看到一堆毫无意义的标签和转义字符。

"内核开发者用终端读邮件,"信使将那封邮件扔回海里,"纯文本,没有例外。你的邮件在所有客户端都必须能正确显示,这就是纯文本的意义——兼容。"

信使又从怀中取出一封简洁的纯文本邮件,递给林小源。这封邮件只有干净的文字,没有多余的格式,每一行都清晰可读。

"这才是内核社区的邮件该有的样子。"

信使又伸手一抓,抓出一封被折断的补丁。它原本是纯文本,却被邮件客户端自动换行,diff 里的空格被吞掉,行首的制表符变成了空格。

"这封更危险,"信使说,"它看起来像补丁,却无法应用。审查者不能在破碎的 diff 上逐行评论,维护者也不会替你修邮件客户端。发给别人之前,先发给自己,确认 git am 能吃下去。最稳妥的办法,是用 git send-email。"

破关试炼

纯文之试

为了避免补丁被 HTML、附件或自动换行破坏,内核社区强烈推荐用哪个 git 工具发送补丁?

答对后才能继续滑动和进入下一章。

林小源注意到海面上有一组特殊的信笺,它们被一根金色的丝线串联在一起,依次排列。

"补丁系列,"信使指着那组信笺,"当你的修改涉及多个补丁时,就要用补丁系列来组织。"

林小源数了数,一共四封邮件。第一封标着 [PATCH 0/3],后面三封分别标着 [PATCH 1/3][PATCH 2/3][PATCH 3/3]

"第零封是封面信,"信使解释道,"它描述整个系列的目的、背景、测试结果。它不包含代码修改,只包含说明。后面三封才是真正的补丁。"

信使轻轻一拉金色丝线,四封邮件同时展开,形成了一个完整的画面。"编号让审查者知道总共有几个补丁,每个补丁在系列中的位置。如果审查者说'第二个补丁有问题',你就知道是 [PATCH 2/3]。"

林小源默默记下:补丁系列是组织复杂修改的方式,编号是沟通的语言。

"版本也是语言。"信使继续说。他把那组信笺翻到背面,那里写着 v1 -> v2v2 -> v3

"当你根据审查意见重发,不要让审查者去旧邮件里翻记忆。封面信或补丁分隔线 --- 之后,要写清楚这一版改了什么:删了哪个 helper,补了哪项测试,为什么保留某个选择。版本说明不会进入永久 changelog,却能让审查者快速重新进入上下文。"

林小源看着那些版本记录,心里忽然一松。被打回不等于失败。每一个 v2、v3,都是补丁在审查中被锻打后的新形态。

破关试炼

版本之试

补丁重发时,用来说明 v1 到 v2、v2 到 v3 改动的说明通常放在分隔线之后;这条分隔线由哪三个字符组成?

答对后才能继续滑动和进入下一章。

道藏笔记

内核启示

内核开发通过邮件列表协作。

邮件列表:

  • LKML — 内核主要邮件列表
  • netdev — 网络子系统
  • linux-fsdevel — 文件系统
  • linux-mm — 内存管理

邮件礼仪:

  • 纯文本邮件
  • 不要 HTML
  • 不要附件
  • 引用适当
  • 不要顶部回复
  • 保留相关 Cc
  • 先确认邮件客户端不会破坏补丁

补丁系列:

  • [PATCH 0/n] 封面信
  • [PATCH 1/n] 补丁 1
  • [PATCH 2/n] 补丁 2
  • v2/v3 重发时说明版本差异
  • --- 之后的版本记录不进入永久 changelog

邮件列表是桥梁——连接全球的开发者。


破关试炼

道藏复核

补丁系列中用于描述整个系列背景、测试结果和版本变化的第零封邮件通常标成什么编号?

答对后才能继续滑动和进入下一章。

以修仙之名,悟内核之道