第二百零二章:编码规范
飞升期涉及内核源码:
一
补丁殿的深处,有一座被无数代码环绕的密室。林小源推门而入,发现四面墙壁上刻满了代码片段,每一行都闪烁着淡淡的光芒。
密室中央站着一位身材笔挺的中年人,穿着一丝不苟的长袍,衣襟上的褶皱都像是用尺子量过的。他的目光锐利如刀,扫过林小源全身。
"你写的代码,"中年人开口,声音冷峻,"我看过了。"
林小源心头一紧。中年人从墙上取下一块玉简,玉简上浮现出林小源之前提交的一段代码。
"缩进用了空格,"中年人指着代码,语气中带着明显的不满,"内核用 Tab,八字符宽。你的变量名叫 ,这个 是什么?临时变量也要有意义的名字。你的函数有两百行——两百行!"
林小源脸上发烫。
中年人将玉简扔回墙上,转身面对林小源:"内核的编码规范不是建议,是铁律。十万开发者在同一份代码上工作,没有统一的风格,代码就会变成一团乱麻。"
/*
* 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;
}#include <stdio.h>
/*
* 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 — 检查编码规范
规范重要性:
- 可读性 — 统一风格
- 可维护性 — 容易理解
- 社区协作 — 减少争论
编码规范是语言——让代码说话清晰。
编码规范之试
编码规范一章强调:好注释不重复代码动作,而要解释代码背后的什么理由?