Skip to content

第二百零二章:编码规范

飞升期

涉及内核源码:

补丁殿的深处,有一座被无数代码环绕的密室。林小源推门而入,发现四面墙壁上刻满了代码片段,每一行都闪烁着淡淡的光芒。

密室中央站着一位身材笔挺的中年人,穿着一丝不苟的长袍,衣襟上的褶皱都像是用尺子量过的。他的目光锐利如刀,扫过林小源全身。

"你写的代码,"中年人开口,声音冷峻,"我看过了。"

林小源心头一紧。中年人从墙上取下一块玉简,玉简上浮现出林小源之前提交的一段代码。

"缩进用了空格,"中年人指着代码,语气中带着明显的不满,"内核用 Tab,八字符宽。你的变量名叫 ,这个 是什么?临时变量也要有意义的名字。你的函数有两百行——两百行!"

林小源脸上发烫。

中年人将玉简扔回墙上,转身面对林小源:"内核的编码规范不是建议,是铁律。十万开发者在同一份代码上工作,没有统一的风格,代码就会变成一团乱麻。"

c
/*
 * Linux 内核编码规范:
 *
 * 1. 缩进
 *    使用 Tab (8 字符)
 *    不使用空格
 *
 * 2. 大括号
 *    函数: 大括号单独一行
 *    语句: 大括号在行尾
 *
 * 3. 命名
 *    变量: 小写加下划线
 *    类型: 小写加下划线
 *    宏: 大写加下划线
 *
 * 4. 函数
 *    短小精悍
 *    只做一件事
 *    局部变量不超过 10 行
 *
 * 5. 注释
 *    不要解释"是什么"
 *    要解释"为什么"
 *
 * 6. 头文件
 *    #ifndef 保护
 *    只包含必要的头文件
 */

/* 好的命名 */
int calculate_sum(int a, int b)
{
	return a + b;
}

/* 坏的命名 */
int calc(int a, int b)
{
	return a + b;
}

/* 好的函数: 短小精悍 */
static int validate_input(int value)
{
	if (value < 0)
		return -1;
	if (value > 100)
		return -1;
	return 0;
}

/* 好的注释: 解释为什么 */
/*
 * We need to lock here because the data structure
 * is accessed from multiple CPUs.
 */
void process_data(void)
{
	/* Lock the data */
}

int main()
{
	printf("=== 编码规范 — 内核的风格 ===\n\n");

	printf("内核编码规范:\n\n");

	printf("--- 缩进 ---\n");
	printf("使用 Tab (8 字符)\n");
	printf("不使用空格\n\n");

	printf("--- 大括号 ---\n");
	printf("函数:\n");
	printf("  大括号单独一行\n\n");
	printf("语句:\n");
	printf("  大括号在行尾\n\n");

	printf("--- 命名 ---\n");
	printf("变量: my_variable\n");
	printf("类型: my_type_t\n");
	printf("宏: MY_MACRO\n\n");

	printf("--- 函数 ---\n");
	printf("短小精悍\n");
	printf("只做一件事\n");
	printf("局部变量不超过 10 行\n\n");

	printf("--- 注释 ---\n");
	printf("不要解释\"是什么\"\n");
	printf("要解释\"为什么\"\n\n");

	printf("--- 检查工具 ---\n");
	printf("checkpatch.pl:\n");
	printf("  检查编码规范\n");
	printf("  scripts/checkpatch.pl patch.patch\n\n");

	printf("--- 为什么规范重要 ---\n");
	printf("1. 可读性\n");
	printf("   统一风格,容易阅读\n\n");
	printf("2. 可维护性\n");
	printf("   容易理解,容易修改\n\n");
	printf("3. 社区协作\n");
	printf("   统一规范,减少争论\n");

	return 0;
}

中年人从墙上取下另一块玉简,上面是一段冗长的函数,嵌套了七八层 if-else,局部变量声明占了整整一屏。

"你看这个函数,"中年人将玉简递给林小源,"它在做什么?"

林小源盯着看了半天,眉头越皱越紧:"它……先验证输入,然后分配内存,然后初始化设备,然后注册中断,然后……"

"然后你就迷失了,"中年人打断他,"一个函数做了七八件事,它就什么都做不好。内核的函数要短小精悍,只做一件事。如果一个函数超过五十行,你就要问问自己——它是不是做了太多事?"

中年人在空中划出几道光弧,将那段冗长代码拆分成五个独立的函数,每个函数只有十几行,职责清晰。

"拆分之后,"中年人指着新的代码,"每个函数都能独立测试,独立审查,独立复用。这才是内核代码该有的样子。"

林小源看着那五个简洁的函数,心中豁然开朗。短小不是目的,清晰才是。

中年人走到密室最深处,那里有一面特殊的墙壁,上面刻着两种注释——左边是"是什么"的注释,右边是"为什么"的注释。

左边写着:/* 将 count 加 1 */,右边写着:/* 需要加锁,因为多个 CPU 会同时访问这个数据结构 */

"你告诉我,"中年人转身面对林小源,"哪个注释有价值?"

林小源毫不犹豫地指向右边。

"左边的注释是废话,"中年人的语气中带着一丝嘲讽,"代码本身就在说'把 count 加 1',你再写一遍有什么用?但右边的注释说出了代码无法表达的东西——为什么需要加锁。这是代码之外的知识,是设计决策,是上下文。"

中年人从袖中取出一枚玉简,递给林小源:"好代码应该自解释。注释不是用来解释代码在做什么,而是用来解释代码为什么这样做。如果你写不出'为什么'的注释,要么代码本身足够清晰,要么你自己还没想清楚。"

林小源接过玉简,上面刻着一句铭文:注释是意图的说明,不是行为的复述。


道藏笔记

内核启示

内核有严格的编码规范。

规范要点:

  • 缩进 — Tab (8 字符)
  • 大括号 — 函数单独一行,语句行尾
  • 命名 — 小写加下划线
  • 函数 — 短小精悍
  • 注释 — 解释"为什么"

检查工具:

  • checkpatch.pl — 检查编码规范

规范重要性:

  • 可读性 — 统一风格
  • 可维护性 — 容易理解
  • 社区协作 — 减少争论

编码规范是语言——让代码说话清晰。


破关试炼

编码规范之试

编码规范一章强调:好注释不重复代码动作,而要解释代码背后的什么理由?

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

以修仙之名,悟内核之道