Skip to content

第二百零六章:文档之道

飞升期

涉及内核源码:

林小源离开试炼场,踏入一片寂静的书海。无数书卷悬浮在半空中,每一卷都散发着柔和的光芒。书卷的封面上标注着不同的路径——Documentation/process/Documentation/driver-api/Documentation/admin-guide/

一位年轻的书童坐在书海中央的石凳上,手中捧着一卷泛黄的古籍。他的眼睛因为长年阅读而微微眯起,但目光中透着温和与耐心。

"你是来学写文档的?"书童放下古籍,微笑着看向林小源。

林小源点头。他环顾四周,书卷的数量多得令人眩晕:"这些文档……都是内核的?"

"每一卷都是,"书童站起身,从空中取下一卷书,"Documentation/ 是内核的文档主目录。开发流程、API 说明、用户指南、驱动文档——全部在这里。"

书童翻开手中的书卷,露出其中的 RST 格式。"内核文档用 RST 格式编写,用 Sphinx 生成 HTML 和 PDF。你写好 RST 文件,放进 Documentation/ 目录,更新索引,然后 make htmldocs 就能生成可阅读的文档。"

林小源接过书卷,感受到纸页上文字的重量。每一个字都是前人留下的路标。

c
/*
 * 内核文档:
 *
 * 文档位置:
 *   Documentation/ — 主文档目录
 *   Documentation/process/ — 开发流程
 *   Documentation/dev-tools/ — 开发工具
 *   Documentation/driver-api/ — 驱动 API
 *
 * 文档格式:
 *   RST (reStructuredText) — 格式
 *   Sphinx — 文档生成工具
 *
 * 文档类型:
 *   1. 开发流程文档
 *      提交补丁、编码规范
 *
 *   2. API 文档
 *      内核 API 说明
 *
 *   3. 用户文档
 *      内核配置、启动参数
 *
 *   4. 驱动文档
 *      设备驱动说明
 *
 * 编写文档:
 *   内核注释
 *   Documentation/ 目录
 *   RST 格式
 *
 * 生成文档:
 *   make htmldocs
 *   make pdfdocs
 */

/* 模拟文档条目 */
struct doc_entry {
    char path[128];
    char description[256];
};

struct doc_entry docs[] = {
    {"Documentation/process/submitting-patches.rst", "补丁提交流程"},
    {"Documentation/process/coding-style.rst", "编码规范"},
    {"Documentation/process/code-of-conduct.rst", "行为准则"},
    {"Documentation/driver-api/driver-model.rst", "设备模型"},
    {"Documentation/admin-guide/kernel-parameters.rst", "内核参数"},
};

printf("=== 文档之道 — 内核的说明书 ===\n\n");

printf("文档是内核的说明书:\n\n");

printf("--- 文档位置 ---\n");
int n = sizeof(docs) / sizeof(docs[0]);
for (int i = 0; i < n; i++) {
    printf("%s\n", docs[i].path);
    printf("  %s\n", docs[i].description);
}

printf("\n--- 文档格式 ---\n");
printf("RST (reStructuredText):\n");
printf("  标记语言\n");
printf("  类似 Markdown\n\n");
printf("Sphinx:\n");
printf("  文档生成工具\n");
printf("  生成 HTML、PDF\n\n");

printf("--- 文档类型 ---\n");
printf("1. 开发流程文档:\n");
printf("   提交补丁、编码规范\n\n");
printf("2. API 文档:\n");
printf("   内核 API 说明\n\n");
printf("3. 用户文档:\n");
printf("   内核配置、启动参数\n\n");
printf("4. 驱动文档:\n");
printf("   设备驱动说明\n\n");

printf("--- 编写文档 ---\n");
printf("内核注释:\n");
printf("   在代码中添加注释\n");
printf("   解释\"为什么\"\n\n");
printf("Documentation/ 目录:\n");
printf("   添加 RST 文件\n");
printf("   更新索引\n\n");

printf("--- 生成文档 ---\n");
printf("make htmldocs:\n");
printf("   生成 HTML 文档\n\n");
printf("make pdfdocs:\n");
printf("   生成 PDF 文档\n\n");

printf("--- 文档重要性 ---\n");
printf("1. 可理解性:\n");
printf("   帮助新人理解代码\n\n");
printf("2. 可维护性:\n");
printf("   记录设计决策\n\n");
printf("3. 可用性:\n");
printf("   帮助用户使用\n\n");

printf("--- 文档原则 ---\n");
printf("1. 清晰:\n");
printf("   语言简洁明了\n\n");
printf("2. 完整:\n");
printf("   覆盖所有功能\n\n");
printf("3. 更新:\n");
printf("   代码改了文档也要改\n");

书童从空中取下另一卷书,翻开递给林小源。页面上是两种格式的对比——左边是 Markdown,右边是 RST。

"你可能会问,为什么不用 Markdown?"书童似乎看穿了林小源的心思,"Markdown 简单,但能力有限。RST 支持交叉引用——你可以从一个文档链接到另一个文档的特定章节。RST 支持代码块的语法高亮、表格、数学公式。Sphinx 从 RST 可以生成 HTML、PDF、epub,甚至 man page。"

林小源仔细对比着两种格式。RST 确实更强大,但也更复杂。书童指着页面上的一个交叉引用标记:"你看,这里引用了 submitting-patches.rst 中的某个章节。点击链接,读者就能直接跳转过去。Markdown 做不到这一点。"

"内核有数万份文档,"书童合上书卷,"如果没有交叉引用,读者就会在文档的海洋中迷失。RST 和 Sphinx 是内核文档的基石。"

书童带林小源走到书海的边缘,那里有一位年轻的修士正在苦苦翻阅源代码,眉头紧锁。

"他是一位新人,"书童低声说,"他想理解内核的设备模型,但没有文档。他只能读源码。"

林小源看着那位新人,看到他在 drivers/ 目录下迷失方向,看到他在 include/linux/ 中找不到自己需要的头文件,看到他因为不理解某个函数的调用约定而写出了一段有 bug 的代码。

"这就是文档的价值,"书童的声音变得沉重,"没有文档的代码,新人需要花几周甚至几个月才能理解。有了文档,几天就够了。文档不是可有可无的装饰,它是代码和理解之间的桥梁。"

书童转身面对林小源,目光认真:"你学到了内核的很多知识,但如果你不把它们写下来,下一个林小源就要重新走一遍你走过的路。写文档,就是为后来者铺路。"

林小源望着那片浩瀚的书海,心中涌起一股使命感。代码会过时,但文档会传承。


道藏笔记

内核启示

文档是内核的说明书。

文档位置:

  • Documentation/ — 主文档目录
  • Documentation/process/ — 开发流程
  • Documentation/dev-tools/ — 开发工具

文档格式:

  • RST — 标记语言
  • Sphinx — 文档生成工具

文档类型:

  • 开发流程 — 提交补丁、编码规范
  • API 文档 — 内核 API
  • 用户文档 — 配置、参数
  • 驱动文档 — 设备驱动

生成文档:

  • make htmldocs — HTML
  • make pdfdocs — PDF

文档是桥梁——连接代码和理解。


破关试炼

文档之试

文档之道中,内核文档主要存放在哪个顶层目录下?

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

以修仙之名,悟内核之道