xref: /OK3568_Linux_fs/kernel/Documentation/translations/zh_CN/process/coding-style.rst (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun.. include:: ../disclaimer-zh_CN.rst
2*4882a593Smuzhiyun
3*4882a593Smuzhiyun:Original: :ref:`Documentation/process/coding-style.rst <codingstyle>`
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun.. _cn_codingstyle:
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun译者::
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun  中文版维护者: 张乐 Zhang Le <r0bertz@gentoo.org>
10*4882a593Smuzhiyun  中文版翻译者: 张乐 Zhang Le <r0bertz@gentoo.org>
11*4882a593Smuzhiyun  中文版校译者: 王聪 Wang Cong <xiyou.wangcong@gmail.com>
12*4882a593Smuzhiyun                 wheelz <kernel.zeng@gmail.com>
13*4882a593Smuzhiyun                 管旭东 Xudong Guan <xudong.guan@gmail.com>
14*4882a593Smuzhiyun                 Li Zefan <lizf@cn.fujitsu.com>
15*4882a593Smuzhiyun                 Wang Chen <wangchen@cn.fujitsu.com>
16*4882a593Smuzhiyun
17*4882a593SmuzhiyunLinux 内核代码风格
18*4882a593Smuzhiyun=========================
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun这是一个简短的文档,描述了 linux 内核的首选代码风格。代码风格是因人而异的,
21*4882a593Smuzhiyun而且我不愿意把自己的观点强加给任何人,但这就像我去做任何事情都必须遵循的原则
22*4882a593Smuzhiyun那样,我也希望在绝大多数事上保持这种的态度。请 (在写代码时) 至少考虑一下这里
23*4882a593Smuzhiyun的代码风格。
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun首先,我建议你打印一份 GNU 代码规范,然后不要读。烧了它,这是一个具有重大象征
26*4882a593Smuzhiyun性意义的动作。
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun不管怎样,现在我们开始:
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun1) 缩进
32*4882a593Smuzhiyun--------------
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun制表符是 8 个字符,所以缩进也是 8 个字符。有些异端运动试图将缩进变为 4 (甚至
35*4882a593Smuzhiyun2!) 字符深,这几乎相当于尝试将圆周率的值定义为 3。
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun理由:缩进的全部意义就在于清楚的定义一个控制块起止于何处。尤其是当你盯着你的
38*4882a593Smuzhiyun屏幕连续看了 20 小时之后,你将会发现大一点的缩进会使你更容易分辨缩进。
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun现在,有些人会抱怨 8 个字符的缩进会使代码向右边移动的太远,在 80 个字符的终端
41*4882a593Smuzhiyun屏幕上就很难读这样的代码。这个问题的答案是,如果你需要 3 级以上的缩进,不管用
42*4882a593Smuzhiyun何种方式你的代码已经有问题了,应该修正你的程序。
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun简而言之,8 个字符的缩进可以让代码更容易阅读,还有一个好处是当你的函数嵌套太
45*4882a593Smuzhiyun深的时候可以给你警告。留心这个警告。
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun在 switch 语句中消除多级缩进的首选的方式是让 ``switch`` 和从属于它的 ``case``
48*4882a593Smuzhiyun标签对齐于同一列,而不要 ``两次缩进`` ``case`` 标签。比如:
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun.. code-block:: c
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun	switch (suffix) {
53*4882a593Smuzhiyun	case 'G':
54*4882a593Smuzhiyun	case 'g':
55*4882a593Smuzhiyun		mem <<= 30;
56*4882a593Smuzhiyun		break;
57*4882a593Smuzhiyun	case 'M':
58*4882a593Smuzhiyun	case 'm':
59*4882a593Smuzhiyun		mem <<= 20;
60*4882a593Smuzhiyun		break;
61*4882a593Smuzhiyun	case 'K':
62*4882a593Smuzhiyun	case 'k':
63*4882a593Smuzhiyun		mem <<= 10;
64*4882a593Smuzhiyun		/* fall through */
65*4882a593Smuzhiyun	default:
66*4882a593Smuzhiyun		break;
67*4882a593Smuzhiyun	}
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun不要把多个语句放在一行里,除非你有什么东西要隐藏:
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun.. code-block:: c
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun	if (condition) do_this;
74*4882a593Smuzhiyun	  do_something_everytime;
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun也不要在一行里放多个赋值语句。内核代码风格超级简单。就是避免可能导致别人误读
77*4882a593Smuzhiyun的表达式。
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun除了注释、文档和 Kconfig 之外,不要使用空格来缩进,前面的例子是例外,是有意为
80*4882a593Smuzhiyun之。
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun选用一个好的编辑器,不要在行尾留空格。
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun2) 把长的行和字符串打散
86*4882a593Smuzhiyun------------------------------
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun代码风格的意义就在于使用平常使用的工具来维持代码的可读性和可维护性。
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun每一行的长度的限制是 80 列,我们强烈建议您遵守这个惯例。
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun长于 80 列的语句要打散成有意义的片段。除非超过 80 列能显著增加可读性,并且不
93*4882a593Smuzhiyun会隐藏信息。子片段要明显短于母片段,并明显靠右。这同样适用于有着很长参数列表
94*4882a593Smuzhiyun的函数头。然而,绝对不要打散对用户可见的字符串,例如 printk 信息,因为这样就
95*4882a593Smuzhiyun很难对它们 grep。
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun3) 大括号和空格的放置
99*4882a593Smuzhiyun------------------------------
100*4882a593Smuzhiyun
101*4882a593SmuzhiyunC 语言风格中另外一个常见问题是大括号的放置。和缩进大小不同,选择或弃用某种放
102*4882a593Smuzhiyun置策略并没有多少技术上的原因,不过首选的方式,就像 Kernighan 和 Ritchie 展示
103*4882a593Smuzhiyun给我们的,是把起始大括号放在行尾,而把结束大括号放在行首,所以:
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun.. code-block:: c
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun	if (x is true) {
108*4882a593Smuzhiyun		we do y
109*4882a593Smuzhiyun	}
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun这适用于所有的非函数语句块 (if, switch, for, while, do)。比如:
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun.. code-block:: c
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun	switch (action) {
116*4882a593Smuzhiyun	case KOBJ_ADD:
117*4882a593Smuzhiyun		return "add";
118*4882a593Smuzhiyun	case KOBJ_REMOVE:
119*4882a593Smuzhiyun		return "remove";
120*4882a593Smuzhiyun	case KOBJ_CHANGE:
121*4882a593Smuzhiyun		return "change";
122*4882a593Smuzhiyun	default:
123*4882a593Smuzhiyun		return NULL;
124*4882a593Smuzhiyun	}
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun不过,有一个例外,那就是函数:函数的起始大括号放置于下一行的开头,所以:
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun.. code-block:: c
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun	int function(int x)
131*4882a593Smuzhiyun	{
132*4882a593Smuzhiyun		body of function
133*4882a593Smuzhiyun	}
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun全世界的异端可能会抱怨这个不一致性是... 呃... 不一致的,不过所有思维健全的人
136*4882a593Smuzhiyun都知道 (a) K&R 是 **正确的** 并且 (b) K&R 是正确的。此外,不管怎样函数都是特
137*4882a593Smuzhiyun殊的 (C 函数是不能嵌套的)。
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun注意结束大括号独自占据一行,除非它后面跟着同一个语句的剩余部分,也就是 do 语
140*4882a593Smuzhiyun句中的 "while" 或者 if 语句中的 "else",像这样:
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun.. code-block:: c
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun	do {
145*4882a593Smuzhiyun		body of do-loop
146*4882a593Smuzhiyun	} while (condition);
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun149*4882a593Smuzhiyun
150*4882a593Smuzhiyun.. code-block:: c
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun	if (x == y) {
153*4882a593Smuzhiyun		..
154*4882a593Smuzhiyun	} else if (x > y) {
155*4882a593Smuzhiyun		...
156*4882a593Smuzhiyun	} else {
157*4882a593Smuzhiyun		....
158*4882a593Smuzhiyun	}
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun理由:K&R。
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun也请注意这种大括号的放置方式也能使空 (或者差不多空的) 行的数量最小化,同时不
163*4882a593Smuzhiyun失可读性。因此,由于你的屏幕上的新行是不可再生资源 (想想 25 行的终端屏幕),你
164*4882a593Smuzhiyun将会有更多的空行来放置注释。
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun当只有一个单独的语句的时候,不用加不必要的大括号。
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun.. code-block:: c
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun	if (condition)
171*4882a593Smuzhiyun		action();
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun174*4882a593Smuzhiyun
175*4882a593Smuzhiyun.. code-block:: c
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun	if (condition)
178*4882a593Smuzhiyun		do_this();
179*4882a593Smuzhiyun	else
180*4882a593Smuzhiyun		do_that();
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun这并不适用于只有一个条件分支是单语句的情况;这时所有分支都要使用大括号:
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun.. code-block:: c
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun	if (condition) {
187*4882a593Smuzhiyun		do_this();
188*4882a593Smuzhiyun		do_that();
189*4882a593Smuzhiyun	} else {
190*4882a593Smuzhiyun		otherwise();
191*4882a593Smuzhiyun	}
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun3.1) 空格
194*4882a593Smuzhiyun********************
195*4882a593Smuzhiyun
196*4882a593SmuzhiyunLinux 内核的空格使用方式 (主要) 取决于它是用于函数还是关键字。(大多数) 关键字
197*4882a593Smuzhiyun后要加一个空格。值得注意的例外是 sizeof, typeof, alignof 和 __attribute__,这
198*4882a593Smuzhiyun些关键字某些程度上看起来更像函数 (它们在 Linux 里也常常伴随小括号而使用,尽管
199*4882a593Smuzhiyun在 C 里这样的小括号不是必需的,就像 ``struct fileinfo info;`` 声明过后的
200*4882a593Smuzhiyun``sizeof info``)。
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun所以在这些关键字之后放一个空格::
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun	if, switch, case, for, do, while
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun但是不要在 sizeof, typeof, alignof 或者 __attribute__ 这些关键字之后放空格。
207*4882a593Smuzhiyun例如,
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun.. code-block:: c
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun	s = sizeof(struct file);
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun不要在小括号里的表达式两侧加空格。这是一个 **反例** :
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun.. code-block:: c
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun	s = sizeof( struct file );
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun当声明指针类型或者返回指针类型的函数时, ``*`` 的首选使用方式是使之靠近变量名
220*4882a593Smuzhiyun或者函数名,而不是靠近类型名。例子:
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun.. code-block:: c
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun	char *linux_banner;
225*4882a593Smuzhiyun	unsigned long long memparse(char *ptr, char **retptr);
226*4882a593Smuzhiyun	char *match_strdup(substring_t *s);
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun在大多数二元和三元操作符两侧使用一个空格,例如下面所有这些操作符::
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun	=  +  -  <  >  *  /  %  |  &  ^  <=  >=  ==  !=  ?  :
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun但是一元操作符后不要加空格::
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun	&  *  +  -  ~  !  sizeof  typeof  alignof  __attribute__  defined
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun后缀自加和自减一元操作符前不加空格::
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun	++  --
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun前缀自加和自减一元操作符后不加空格::
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun	++  --
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun``.`` 和 ``->`` 结构体成员操作符前后不加空格。
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun不要在行尾留空白。有些可以自动缩进的编辑器会在新行的行首加入适量的空白,然后
247*4882a593Smuzhiyun你就可以直接在那一行输入代码。不过假如你最后没有在那一行输入代码,有些编辑器
248*4882a593Smuzhiyun就不会移除已经加入的空白,就像你故意留下一个只有空白的行。包含行尾空白的行就
249*4882a593Smuzhiyun这样产生了。
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun当 git 发现补丁包含了行尾空白的时候会警告你,并且可以应你的要求去掉行尾空白;
252*4882a593Smuzhiyun不过如果你是正在打一系列补丁,这样做会导致后面的补丁失败,因为你改变了补丁的
253*4882a593Smuzhiyun上下文。
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun4) 命名
257*4882a593Smuzhiyun------------------------------
258*4882a593Smuzhiyun
259*4882a593SmuzhiyunC 是一个简朴的语言,你的命名也应该这样。和 Modula-2 和 Pascal 程序员不同,
260*4882a593SmuzhiyunC 程序员不使用类似 ThisVariableIsATemporaryCounter 这样华丽的名字。C 程序员会
261*4882a593Smuzhiyun称那个变量为 ``tmp`` ,这样写起来会更容易,而且至少不会令其难于理解。
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun不过,虽然混用大小写的名字是不提倡使用的,但是全局变量还是需要一个具描述性的
264*4882a593Smuzhiyun名字。称一个全局函数为 ``foo`` 是一个难以饶恕的错误。
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun全局变量 (只有当你 **真正** 需要它们的时候再用它) 需要有一个具描述性的名字,就
267*4882a593Smuzhiyun像全局函数。如果你有一个可以计算活动用户数量的函数,你应该叫它
268*4882a593Smuzhiyun``count_active_users()`` 或者类似的名字,你不应该叫它 ``cntuser()`` 。
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun在函数名中包含函数类型 (所谓的匈牙利命名法) 是脑子出了问题——编译器知道那些类
271*4882a593Smuzhiyun型而且能够检查那些类型,这样做只能把程序员弄糊涂了。难怪微软总是制造出有问题
272*4882a593Smuzhiyun的程序。
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun本地变量名应该简短,而且能够表达相关的含义。如果你有一些随机的整数型的循环计
275*4882a593Smuzhiyun数器,它应该被称为 ``i`` 。叫它 ``loop_counter`` 并无益处,如果它没有被误解的
276*4882a593Smuzhiyun可能的话。类似的, ``tmp`` 可以用来称呼任意类型的临时变量。
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun如果你怕混淆了你的本地变量名,你就遇到另一个问题了,叫做函数增长荷尔蒙失衡综
279*4882a593Smuzhiyun合症。请看第六章 (函数)。
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun5) Typedef
283*4882a593Smuzhiyun-----------
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun不要使用类似 ``vps_t`` 之类的东西。
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun对结构体和指针使用 typedef 是一个 **错误** 。当你在代码里看到:
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun.. code-block:: c
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun	vps_t a;
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun这代表什么意思呢?
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun相反,如果是这样
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun.. code-block:: c
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun	struct virtual_container *a;
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun你就知道 ``a`` 是什么了。
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun很多人认为 typedef ``能提高可读性`` 。实际不是这样的。它们只在下列情况下有用:
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun (a) 完全不透明的对象 (这种情况下要主动使用 typedef 来 **隐藏** 这个对象实际上
306*4882a593Smuzhiyun     是什么)。
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun     例如: ``pte_t`` 等不透明对象,你只能用合适的访问函数来访问它们。
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun     .. note::
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun       不透明性和 "访问函数" 本身是不好的。我们使用 pte_t 等类型的原因在于真
313*4882a593Smuzhiyun       的是完全没有任何共用的可访问信息。
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun (b) 清楚的整数类型,如此,这层抽象就可以 **帮助** 消除到底是 ``int`` 还是
316*4882a593Smuzhiyun     ``long`` 的混淆。
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun     u8/u16/u32 是完全没有问题的 typedef,不过它们更符合类别 (d) 而不是这里。
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun     .. note::
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun       要这样做,必须事出有因。如果某个变量是 ``unsigned long`` ,那么没有必要
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun	typedef unsigned long myflags_t;
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun     不过如果有一个明确的原因,比如它在某种情况下可能会是一个 ``unsigned int``
327*4882a593Smuzhiyun     而在其他情况下可能为 ``unsigned long`` ,那么就不要犹豫,请务必使用
328*4882a593Smuzhiyun     typedef。
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun (c) 当你使用 sparse 按字面的创建一个 **新** 类型来做类型检查的时候。
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun (d) 和标准 C99 类型相同的类型,在某些例外的情况下。
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun     虽然让眼睛和脑筋来适应新的标准类型比如 ``uint32_t`` 不需要花很多时间,可
335*4882a593Smuzhiyun     是有些人仍然拒绝使用它们。
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun     因此,Linux 特有的等同于标准类型的 ``u8/u16/u32/u64`` 类型和它们的有符号
338*4882a593Smuzhiyun     类型是被允许的——尽管在你自己的新代码中,它们不是强制要求要使用的。
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun     当编辑已经使用了某个类型集的已有代码时,你应该遵循那些代码中已经做出的选
341*4882a593Smuzhiyun     择。
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun (e) 可以在用户空间安全使用的类型。
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun     在某些用户空间可见的结构体里,我们不能要求 C99 类型而且不能用上面提到的
346*4882a593Smuzhiyun     ``u32`` 类型。因此,我们在与用户空间共享的所有结构体中使用 __u32 和类似
347*4882a593Smuzhiyun     的类型。
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun可能还有其他的情况,不过基本的规则是 **永远不要** 使用 typedef,除非你可以明
350*4882a593Smuzhiyun确的应用上述某个规则中的一个。
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun总的来说,如果一个指针或者一个结构体里的元素可以合理的被直接访问到,那么它们
353*4882a593Smuzhiyun就不应该是一个 typedef。
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun6) 函数
357*4882a593Smuzhiyun------------------------------
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun函数应该简短而漂亮,并且只完成一件事情。函数应该可以一屏或者两屏显示完 (我们
360*4882a593Smuzhiyun都知道 ISO/ANSI 屏幕大小是 80x24),只做一件事情,而且把它做好。
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun一个函数的最大长度是和该函数的复杂度和缩进级数成反比的。所以,如果你有一个理
363*4882a593Smuzhiyun论上很简单的只有一个很长 (但是简单) 的 case 语句的函数,而且你需要在每个 case
364*4882a593Smuzhiyun里做很多很小的事情,这样的函数尽管很长,但也是可以的。
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun不过,如果你有一个复杂的函数,而且你怀疑一个天分不是很高的高中一年级学生可能
367*4882a593Smuzhiyun甚至搞不清楚这个函数的目的,你应该严格遵守前面提到的长度限制。使用辅助函数,
368*4882a593Smuzhiyun并为之取个具描述性的名字 (如果你觉得它们的性能很重要的话,可以让编译器内联它
369*4882a593Smuzhiyun们,这样的效果往往会比你写一个复杂函数的效果要好。)
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun函数的另外一个衡量标准是本地变量的数量。此数量不应超过 5-10 个,否则你的函数
372*4882a593Smuzhiyun就有问题了。重新考虑一下你的函数,把它分拆成更小的函数。人的大脑一般可以轻松
373*4882a593Smuzhiyun的同时跟踪 7 个不同的事物,如果再增多的话,就会糊涂了。即便你聪颖过人,你也可
374*4882a593Smuzhiyun能会记不清你 2 个星期前做过的事情。
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun在源文件里,使用空行隔开不同的函数。如果该函数需要被导出,它的 **EXPORT** 宏
377*4882a593Smuzhiyun应该紧贴在它的结束大括号之下。比如:
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun.. code-block:: c
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun	int system_is_up(void)
382*4882a593Smuzhiyun	{
383*4882a593Smuzhiyun		return system_state == SYSTEM_RUNNING;
384*4882a593Smuzhiyun	}
385*4882a593Smuzhiyun	EXPORT_SYMBOL(system_is_up);
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun在函数原型中,包含函数名和它们的数据类型。虽然 C 语言里没有这样的要求,在
388*4882a593SmuzhiyunLinux 里这是提倡的做法,因为这样可以很简单的给读者提供更多的有价值的信息。
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun7) 集中的函数退出途径
392*4882a593Smuzhiyun------------------------------
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun虽然被某些人声称已经过时,但是 goto 语句的等价物还是经常被编译器所使用,具体
395*4882a593Smuzhiyun形式是无条件跳转指令。
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun当一个函数从多个位置退出,并且需要做一些类似清理的常见操作时,goto 语句就很方
398*4882a593Smuzhiyun便了。如果并不需要清理操作,那么直接 return 即可。
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun选择一个能够说明 goto 行为或它为何存在的标签名。如果 goto 要释放 ``buffer``,
401*4882a593Smuzhiyun一个不错的名字可以是 ``out_free_buffer:`` 。别去使用像 ``err1:`` 和 ``err2:``
402*4882a593Smuzhiyun这样的GW_BASIC 名称,因为一旦你添加或删除了 (函数的) 退出路径,你就必须对它们
403*4882a593Smuzhiyun重新编号,这样会难以去检验正确性。
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun使用 goto 的理由是:
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun- 无条件语句容易理解和跟踪
408*4882a593Smuzhiyun- 嵌套程度减小
409*4882a593Smuzhiyun- 可以避免由于修改时忘记更新个别的退出点而导致错误
410*4882a593Smuzhiyun- 让编译器省去删除冗余代码的工作 ;)
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun.. code-block:: c
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun	int fun(int a)
415*4882a593Smuzhiyun	{
416*4882a593Smuzhiyun		int result = 0;
417*4882a593Smuzhiyun		char *buffer;
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun		buffer = kmalloc(SIZE, GFP_KERNEL);
420*4882a593Smuzhiyun		if (!buffer)
421*4882a593Smuzhiyun			return -ENOMEM;
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun		if (condition1) {
424*4882a593Smuzhiyun			while (loop1) {
425*4882a593Smuzhiyun				...
426*4882a593Smuzhiyun			}
427*4882a593Smuzhiyun			result = 1;
428*4882a593Smuzhiyun			goto out_free_buffer;
429*4882a593Smuzhiyun		}
430*4882a593Smuzhiyun		...
431*4882a593Smuzhiyun	out_free_buffer:
432*4882a593Smuzhiyun		kfree(buffer);
433*4882a593Smuzhiyun		return result;
434*4882a593Smuzhiyun	}
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun一个需要注意的常见错误是 ``一个 err 错误`` ,就像这样:
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun.. code-block:: c
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun	err:
441*4882a593Smuzhiyun		kfree(foo->bar);
442*4882a593Smuzhiyun		kfree(foo);
443*4882a593Smuzhiyun		return ret;
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun这段代码的错误是,在某些退出路径上 ``foo`` 是 NULL。通常情况下,通过把它分离
446*4882a593Smuzhiyun成两个错误标签 ``err_free_bar:`` 和 ``err_free_foo:`` 来修复这个错误:
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun.. code-block:: c
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun	 err_free_bar:
451*4882a593Smuzhiyun		kfree(foo->bar);
452*4882a593Smuzhiyun	 err_free_foo:
453*4882a593Smuzhiyun		kfree(foo);
454*4882a593Smuzhiyun		return ret;
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun理想情况下,你应该模拟错误来测试所有退出路径。
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun8) 注释
460*4882a593Smuzhiyun------------------------------
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun注释是好的,不过有过度注释的危险。永远不要在注释里解释你的代码是如何运作的:
463*4882a593Smuzhiyun更好的做法是让别人一看你的代码就可以明白,解释写的很差的代码是浪费时间。
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun一般的,你想要你的注释告诉别人你的代码做了什么,而不是怎么做的。也请你不要把
466*4882a593Smuzhiyun注释放在一个函数体内部:如果函数复杂到你需要独立的注释其中的一部分,你很可能
467*4882a593Smuzhiyun需要回到第六章看一看。你可以做一些小注释来注明或警告某些很聪明 (或者槽糕) 的
468*4882a593Smuzhiyun做法,但不要加太多。你应该做的,是把注释放在函数的头部,告诉人们它做了什么,
469*4882a593Smuzhiyun也可以加上它做这些事情的原因。
470*4882a593Smuzhiyun
471*4882a593Smuzhiyun当注释内核 API 函数时,请使用 kernel-doc 格式。请看
472*4882a593SmuzhiyunDocumentation/doc-guide/ 和 scripts/kernel-doc 以获得详细信息。
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun长 (多行) 注释的首选风格是:
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun.. code-block:: c
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun	/*
479*4882a593Smuzhiyun	 * This is the preferred style for multi-line
480*4882a593Smuzhiyun	 * comments in the Linux kernel source code.
481*4882a593Smuzhiyun	 * Please use it consistently.
482*4882a593Smuzhiyun	 *
483*4882a593Smuzhiyun	 * Description:  A column of asterisks on the left side,
484*4882a593Smuzhiyun	 * with beginning and ending almost-blank lines.
485*4882a593Smuzhiyun	 */
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun对于在 net/ 和 drivers/net/ 的文件,首选的长 (多行) 注释风格有些不同。
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun.. code-block:: c
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun	/* The preferred comment style for files in net/ and drivers/net
492*4882a593Smuzhiyun	 * looks like this.
493*4882a593Smuzhiyun	 *
494*4882a593Smuzhiyun	 * It is nearly the same as the generally preferred comment style,
495*4882a593Smuzhiyun	 * but there is no initial almost-blank line.
496*4882a593Smuzhiyun	 */
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun注释数据也是很重要的,不管是基本类型还是衍生类型。为了方便实现这一点,每一行
499*4882a593Smuzhiyun应只声明一个数据 (不要使用逗号来一次声明多个数据)。这样你就有空间来为每个数据
500*4882a593Smuzhiyun写一段小注释来解释它们的用途了。
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun9) 你已经把事情弄糟了
504*4882a593Smuzhiyun------------------------------
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun这没什么,我们都是这样。可能你的使用了很长时间 Unix 的朋友已经告诉你
507*4882a593Smuzhiyun``GNU emacs`` 能自动帮你格式化 C 源代码,而且你也注意到了,确实是这样,不过它
508*4882a593Smuzhiyun所使用的默认值和我们想要的相去甚远 (实际上,甚至比随机打的还要差——无数个猴子
509*4882a593Smuzhiyun在 GNU emacs 里打字永远不会创造出一个好程序) (译注:Infinite Monkey Theorem)
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun所以你要么放弃 GNU emacs,要么改变它让它使用更合理的设定。要采用后一个方案,
512*4882a593Smuzhiyun你可以把下面这段粘贴到你的 .emacs 文件里。
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun.. code-block:: none
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun  (defun c-lineup-arglist-tabs-only (ignored)
517*4882a593Smuzhiyun    "Line up argument lists by tabs, not spaces"
518*4882a593Smuzhiyun    (let* ((anchor (c-langelem-pos c-syntactic-element))
519*4882a593Smuzhiyun           (column (c-langelem-2nd-pos c-syntactic-element))
520*4882a593Smuzhiyun           (offset (- (1+ column) anchor))
521*4882a593Smuzhiyun           (steps (floor offset c-basic-offset)))
522*4882a593Smuzhiyun      (* (max steps 1)
523*4882a593Smuzhiyun         c-basic-offset)))
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun  (dir-locals-set-class-variables
526*4882a593Smuzhiyun   'linux-kernel
527*4882a593Smuzhiyun   '((c-mode . (
528*4882a593Smuzhiyun          (c-basic-offset . 8)
529*4882a593Smuzhiyun          (c-label-minimum-indentation . 0)
530*4882a593Smuzhiyun          (c-offsets-alist . (
531*4882a593Smuzhiyun                  (arglist-close         . c-lineup-arglist-tabs-only)
532*4882a593Smuzhiyun                  (arglist-cont-nonempty .
533*4882a593Smuzhiyun		      (c-lineup-gcc-asm-reg c-lineup-arglist-tabs-only))
534*4882a593Smuzhiyun                  (arglist-intro         . +)
535*4882a593Smuzhiyun                  (brace-list-intro      . +)
536*4882a593Smuzhiyun                  (c                     . c-lineup-C-comments)
537*4882a593Smuzhiyun                  (case-label            . 0)
538*4882a593Smuzhiyun                  (comment-intro         . c-lineup-comment)
539*4882a593Smuzhiyun                  (cpp-define-intro      . +)
540*4882a593Smuzhiyun                  (cpp-macro             . -1000)
541*4882a593Smuzhiyun                  (cpp-macro-cont        . +)
542*4882a593Smuzhiyun                  (defun-block-intro     . +)
543*4882a593Smuzhiyun                  (else-clause           . 0)
544*4882a593Smuzhiyun                  (func-decl-cont        . +)
545*4882a593Smuzhiyun                  (inclass               . +)
546*4882a593Smuzhiyun                  (inher-cont            . c-lineup-multi-inher)
547*4882a593Smuzhiyun                  (knr-argdecl-intro     . 0)
548*4882a593Smuzhiyun                  (label                 . -1000)
549*4882a593Smuzhiyun                  (statement             . 0)
550*4882a593Smuzhiyun                  (statement-block-intro . +)
551*4882a593Smuzhiyun                  (statement-case-intro  . +)
552*4882a593Smuzhiyun                  (statement-cont        . +)
553*4882a593Smuzhiyun                  (substatement          . +)
554*4882a593Smuzhiyun                  ))
555*4882a593Smuzhiyun          (indent-tabs-mode . t)
556*4882a593Smuzhiyun          (show-trailing-whitespace . t)
557*4882a593Smuzhiyun          ))))
558*4882a593Smuzhiyun
559*4882a593Smuzhiyun  (dir-locals-set-directory-class
560*4882a593Smuzhiyun   (expand-file-name "~/src/linux-trees")
561*4882a593Smuzhiyun   'linux-kernel)
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun这会让 emacs 在 ``~/src/linux-trees`` 下的 C 源文件获得更好的内核代码风格。
564*4882a593Smuzhiyun
565*4882a593Smuzhiyun不过就算你尝试让 emacs 正确的格式化代码失败了,也并不意味着你失去了一切:还可
566*4882a593Smuzhiyun以用 ``indent`` 。
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun不过,GNU indent 也有和 GNU emacs 一样有问题的设定,所以你需要给它一些命令选
569*4882a593Smuzhiyun项。不过,这还不算太糟糕,因为就算是 GNU indent 的作者也认同 K&R 的权威性
570*4882a593Smuzhiyun(GNU 的人并不是坏人,他们只是在这个问题上被严重的误导了),所以你只要给 indent
571*4882a593Smuzhiyun指定选项 ``-kr -i8`` (代表 ``K&R,8 字符缩进``),或使用 ``scripts/Lindent``
572*4882a593Smuzhiyun这样就可以以最时髦的方式缩进源代码。
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun``indent`` 有很多选项,特别是重新格式化注释的时候,你可能需要看一下它的手册。
575*4882a593Smuzhiyun不过记住: ``indent`` 不能修正坏的编程习惯。
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun10) Kconfig 配置文件
579*4882a593Smuzhiyun------------------------------
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun对于遍布源码树的所有 Kconfig* 配置文件来说,它们缩进方式有所不同。紧挨着
582*4882a593Smuzhiyun``config`` 定义的行,用一个制表符缩进,然而 help 信息的缩进则额外增加 2 个空
583*4882a593Smuzhiyun格。举个例子::
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun  config AUDIT
586*4882a593Smuzhiyun	bool "Auditing support"
587*4882a593Smuzhiyun	depends on NET
588*4882a593Smuzhiyun	help
589*4882a593Smuzhiyun	  Enable auditing infrastructure that can be used with another
590*4882a593Smuzhiyun	  kernel subsystem, such as SELinux (which requires this for
591*4882a593Smuzhiyun	  logging of avc messages output).  Does not do system-call
592*4882a593Smuzhiyun	  auditing without CONFIG_AUDITSYSCALL.
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun而那些危险的功能 (比如某些文件系统的写支持) 应该在它们的提示字符串里显著的声
595*4882a593Smuzhiyun明这一点::
596*4882a593Smuzhiyun
597*4882a593Smuzhiyun  config ADFS_FS_RW
598*4882a593Smuzhiyun	bool "ADFS write support (DANGEROUS)"
599*4882a593Smuzhiyun	depends on ADFS_FS
600*4882a593Smuzhiyun	...
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun要查看配置文件的完整文档,请看 Documentation/kbuild/kconfig-language.rst603*4882a593Smuzhiyun
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun11) 数据结构
606*4882a593Smuzhiyun------------------------------
607*4882a593Smuzhiyun
608*4882a593Smuzhiyun如果一个数据结构,在创建和销毁它的单线执行环境之外可见,那么它必须要有一个引
609*4882a593Smuzhiyun用计数器。内核里没有垃圾收集 (并且内核之外的垃圾收集慢且效率低下),这意味着你
610*4882a593Smuzhiyun绝对需要记录你对这种数据结构的使用情况。
611*4882a593Smuzhiyun
612*4882a593Smuzhiyun引用计数意味着你能够避免上锁,并且允许多个用户并行访问这个数据结构——而不需要
613*4882a593Smuzhiyun担心这个数据结构仅仅因为暂时不被使用就消失了,那些用户可能不过是沉睡了一阵或
614*4882a593Smuzhiyun者做了一些其他事情而已。
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun注意上锁 **不能** 取代引用计数。上锁是为了保持数据结构的一致性,而引用计数是一
617*4882a593Smuzhiyun个内存管理技巧。通常二者都需要,不要把两个搞混了。
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun很多数据结构实际上有 2 级引用计数,它们通常有不同 ``类`` 的用户。子类计数器统
620*4882a593Smuzhiyun计子类用户的数量,每当子类计数器减至零时,全局计数器减一。
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun这种 ``多级引用计数`` 的例子可以在内存管理 (``struct mm_struct``: mm_users 和
623*4882a593Smuzhiyunmm_count),和文件系统 (``struct super_block``: s_count 和 s_active) 中找到。
624*4882a593Smuzhiyun
625*4882a593Smuzhiyun记住:如果另一个执行线索可以找到你的数据结构,但这个数据结构没有引用计数器,
626*4882a593Smuzhiyun这里几乎肯定是一个 bug。
627*4882a593Smuzhiyun
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun12) 宏,枚举和RTL
630*4882a593Smuzhiyun------------------------------
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun用于定义常量的宏的名字及枚举里的标签需要大写。
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun.. code-block:: c
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun	#define CONSTANT 0x12345
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun在定义几个相关的常量时,最好用枚举。
639*4882a593Smuzhiyun
640*4882a593Smuzhiyun宏的名字请用大写字母,不过形如函数的宏的名字可以用小写字母。
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun一般的,如果能写成内联函数就不要写成像函数的宏。
643*4882a593Smuzhiyun
644*4882a593Smuzhiyun含有多个语句的宏应该被包含在一个 do-while 代码块里:
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun.. code-block:: c
647*4882a593Smuzhiyun
648*4882a593Smuzhiyun	#define macrofun(a, b, c)			\
649*4882a593Smuzhiyun		do {					\
650*4882a593Smuzhiyun			if (a == 5)			\
651*4882a593Smuzhiyun				do_this(b, c);		\
652*4882a593Smuzhiyun		} while (0)
653*4882a593Smuzhiyun
654*4882a593Smuzhiyun使用宏的时候应避免的事情:
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun1) 影响控制流程的宏:
657*4882a593Smuzhiyun
658*4882a593Smuzhiyun.. code-block:: c
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun	#define FOO(x)					\
661*4882a593Smuzhiyun		do {					\
662*4882a593Smuzhiyun			if (blah(x) < 0)		\
663*4882a593Smuzhiyun				return -EBUGGERED;	\
664*4882a593Smuzhiyun		} while (0)
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun**非常** 不好。它看起来像一个函数,不过却能导致 ``调用`` 它的函数退出;不要打
667*4882a593Smuzhiyun乱读者大脑里的语法分析器。
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun2) 依赖于一个固定名字的本地变量的宏:
670*4882a593Smuzhiyun
671*4882a593Smuzhiyun.. code-block:: c
672*4882a593Smuzhiyun
673*4882a593Smuzhiyun	#define FOO(val) bar(index, val)
674*4882a593Smuzhiyun
675*4882a593Smuzhiyun可能看起来像是个不错的东西,不过它非常容易把读代码的人搞糊涂,而且容易导致看起
676*4882a593Smuzhiyun来不相关的改动带来错误。
677*4882a593Smuzhiyun
678*4882a593Smuzhiyun3) 作为左值的带参数的宏: FOO(x) = y;如果有人把 FOO 变成一个内联函数的话,这
679*4882a593Smuzhiyun   种用法就会出错了。
680*4882a593Smuzhiyun
681*4882a593Smuzhiyun4) 忘记了优先级:使用表达式定义常量的宏必须将表达式置于一对小括号之内。带参数
682*4882a593Smuzhiyun   的宏也要注意此类问题。
683*4882a593Smuzhiyun
684*4882a593Smuzhiyun.. code-block:: c
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun	#define CONSTANT 0x4000
687*4882a593Smuzhiyun	#define CONSTEXP (CONSTANT | 3)
688*4882a593Smuzhiyun
689*4882a593Smuzhiyun5) 在宏里定义类似函数的本地变量时命名冲突:
690*4882a593Smuzhiyun
691*4882a593Smuzhiyun.. code-block:: c
692*4882a593Smuzhiyun
693*4882a593Smuzhiyun	#define FOO(x)				\
694*4882a593Smuzhiyun	({					\
695*4882a593Smuzhiyun		typeof(x) ret;			\
696*4882a593Smuzhiyun		ret = calc_ret(x);		\
697*4882a593Smuzhiyun		(ret);				\
698*4882a593Smuzhiyun	})
699*4882a593Smuzhiyun
700*4882a593Smuzhiyunret 是本地变量的通用名字 - __foo_ret 更不容易与一个已存在的变量冲突。
701*4882a593Smuzhiyun
702*4882a593Smuzhiyuncpp 手册对宏的讲解很详细。gcc internals 手册也详细讲解了 RTL,内核里的汇编语
703*4882a593Smuzhiyun言经常用到它。
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun
706*4882a593Smuzhiyun13) 打印内核消息
707*4882a593Smuzhiyun------------------------------
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun内核开发者应该是受过良好教育的。请一定注意内核信息的拼写,以给人以好的印象。
710*4882a593Smuzhiyun不要用不规范的单词比如 ``dont``,而要用 ``do not`` 或者 ``don't`` 。保证这些信
711*4882a593Smuzhiyun息简单明了,无歧义。
712*4882a593Smuzhiyun
713*4882a593Smuzhiyun内核信息不必以英文句号结束。
714*4882a593Smuzhiyun
715*4882a593Smuzhiyun在小括号里打印数字 (%d) 没有任何价值,应该避免这样做。
716*4882a593Smuzhiyun
717*4882a593Smuzhiyun<linux/device.h> 里有一些驱动模型诊断宏,你应该使用它们,以确保信息对应于正确
718*4882a593Smuzhiyun的设备和驱动,并且被标记了正确的消息级别。这些宏有:dev_err(), dev_warn(),
719*4882a593Smuzhiyundev_info() 等等。对于那些不和某个特定设备相关连的信息,<linux/printk.h> 定义
720*4882a593Smuzhiyun了 pr_notice(), pr_info(), pr_warn(), pr_err() 和其他。
721*4882a593Smuzhiyun
722*4882a593Smuzhiyun写出好的调试信息可以是一个很大的挑战;一旦你写出后,这些信息在远程除错时能提
723*4882a593Smuzhiyun供极大的帮助。然而打印调试信息的处理方式同打印非调试信息不同。其他 pr_XXX()
724*4882a593Smuzhiyun函数能无条件地打印,pr_debug() 却不;默认情况下它不会被编译,除非定义了 DEBUG
725*4882a593Smuzhiyun或设定了 CONFIG_DYNAMIC_DEBUG。实际这同样是为了 dev_dbg(),一个相关约定是在一
726*4882a593Smuzhiyun个已经开启了 DEBUG 时,使用 VERBOSE_DEBUG 来添加 dev_vdbg()。
727*4882a593Smuzhiyun
728*4882a593Smuzhiyun许多子系统拥有 Kconfig 调试选项来开启 -DDEBUG 在对应的 Makefile 里面;在其他
729*4882a593Smuzhiyun情况下,特殊文件使用 #define DEBUG。当一条调试信息需要被无条件打印时,例如,
730*4882a593Smuzhiyun如果已经包含一个调试相关的 #ifdef 条件,printk(KERN_DEBUG ...) 就可被使用。
731*4882a593Smuzhiyun
732*4882a593Smuzhiyun
733*4882a593Smuzhiyun14) 分配内存
734*4882a593Smuzhiyun------------------------------
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun内核提供了下面的一般用途的内存分配函数:
737*4882a593Smuzhiyunkmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc() 和 vzalloc()。
738*4882a593Smuzhiyun请参考 API 文档以获取有关它们的详细信息。
739*4882a593Smuzhiyun
740*4882a593Smuzhiyun传递结构体大小的首选形式是这样的:
741*4882a593Smuzhiyun
742*4882a593Smuzhiyun.. code-block:: c
743*4882a593Smuzhiyun
744*4882a593Smuzhiyun	p = kmalloc(sizeof(*p), ...);
745*4882a593Smuzhiyun
746*4882a593Smuzhiyun另外一种传递方式中,sizeof 的操作数是结构体的名字,这样会降低可读性,并且可能
747*4882a593Smuzhiyun会引入 bug。有可能指针变量类型被改变时,而对应的传递给内存分配函数的 sizeof
748*4882a593Smuzhiyun的结果不变。
749*4882a593Smuzhiyun
750*4882a593Smuzhiyun强制转换一个 void 指针返回值是多余的。C 语言本身保证了从 void 指针到其他任何
751*4882a593Smuzhiyun指针类型的转换是没有问题的。
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun分配一个数组的首选形式是这样的:
754*4882a593Smuzhiyun
755*4882a593Smuzhiyun.. code-block:: c
756*4882a593Smuzhiyun
757*4882a593Smuzhiyun	p = kmalloc_array(n, sizeof(...), ...);
758*4882a593Smuzhiyun
759*4882a593Smuzhiyun分配一个零长数组的首选形式是这样的:
760*4882a593Smuzhiyun
761*4882a593Smuzhiyun.. code-block:: c
762*4882a593Smuzhiyun
763*4882a593Smuzhiyun	p = kcalloc(n, sizeof(...), ...);
764*4882a593Smuzhiyun
765*4882a593Smuzhiyun两种形式检查分配大小 n * sizeof(...) 的溢出,如果溢出返回 NULL。
766*4882a593Smuzhiyun
767*4882a593Smuzhiyun
768*4882a593Smuzhiyun15) 内联弊病
769*4882a593Smuzhiyun------------------------------
770*4882a593Smuzhiyun
771*4882a593Smuzhiyun有一个常见的误解是 ``内联`` 是 gcc 提供的可以让代码运行更快的一个选项。虽然使
772*4882a593Smuzhiyun用内联函数有时候是恰当的 (比如作为一种替代宏的方式,请看第十二章),不过很多情
773*4882a593Smuzhiyun况下不是这样。inline 的过度使用会使内核变大,从而使整个系统运行速度变慢。
774*4882a593Smuzhiyun因为体积大内核会占用更多的指令高速缓存,而且会导致 pagecache 的可用内存减少。
775*4882a593Smuzhiyun想象一下,一次 pagecache 未命中就会导致一次磁盘寻址,将耗时 5 毫秒。5 毫秒的
776*4882a593Smuzhiyun时间内 CPU 能执行很多很多指令。
777*4882a593Smuzhiyun
778*4882a593Smuzhiyun一个基本的原则是如果一个函数有 3 行以上,就不要把它变成内联函数。这个原则的一
779*4882a593Smuzhiyun个例外是,如果你知道某个参数是一个编译时常量,而且因为这个常量你确定编译器在
780*4882a593Smuzhiyun编译时能优化掉你的函数的大部分代码,那仍然可以给它加上 inline 关键字。
781*4882a593Smuzhiyunkmalloc() 内联函数就是一个很好的例子。
782*4882a593Smuzhiyun
783*4882a593Smuzhiyun人们经常主张给 static 的而且只用了一次的函数加上 inline,如此不会有任何损失,
784*4882a593Smuzhiyun因为没有什么好权衡的。虽然从技术上说这是正确的,但是实际上这种情况下即使不加
785*4882a593Smuzhiyuninline gcc 也可以自动使其内联。而且其他用户可能会要求移除 inline,由此而来的
786*4882a593Smuzhiyun争论会抵消 inline 自身的潜在价值,得不偿失。
787*4882a593Smuzhiyun
788*4882a593Smuzhiyun
789*4882a593Smuzhiyun16) 函数返回值及命名
790*4882a593Smuzhiyun------------------------------
791*4882a593Smuzhiyun
792*4882a593Smuzhiyun函数可以返回多种不同类型的值,最常见的一种是表明函数执行成功或者失败的值。这样
793*4882a593Smuzhiyun的一个值可以表示为一个错误代码整数 (-Exxx=失败,0=成功) 或者一个 ``成功``
794*4882a593Smuzhiyun布尔值 (0=失败,非0=成功)。
795*4882a593Smuzhiyun
796*4882a593Smuzhiyun混合使用这两种表达方式是难于发现的 bug 的来源。如果 C 语言本身严格区分整形和
797*4882a593Smuzhiyun布尔型变量,那么编译器就能够帮我们发现这些错误... 不过 C 语言不区分。为了避免
798*4882a593Smuzhiyun产生这种 bug,请遵循下面的惯例::
799*4882a593Smuzhiyun
800*4882a593Smuzhiyun	如果函数的名字是一个动作或者强制性的命令,那么这个函数应该返回错误代
801*4882a593Smuzhiyun	码整数。如果是一个判断,那么函数应该返回一个 "成功" 布尔值。
802*4882a593Smuzhiyun
803*4882a593Smuzhiyun比如, ``add work`` 是一个命令,所以 add_work() 在成功时返回 0,在失败时返回
804*4882a593Smuzhiyun-EBUSY。类似的,因为 ``PCI device present`` 是一个判断,所以 pci_dev_present()
805*4882a593Smuzhiyun在成功找到一个匹配的设备时应该返回 1,如果找不到时应该返回 0。
806*4882a593Smuzhiyun
807*4882a593Smuzhiyun所有 EXPORTed 函数都必须遵守这个惯例,所有的公共函数也都应该如此。私有
808*4882a593Smuzhiyun(static) 函数不需要如此,但是我们也推荐这样做。
809*4882a593Smuzhiyun
810*4882a593Smuzhiyun返回值是实际计算结果而不是计算是否成功的标志的函数不受此惯例的限制。一般的,
811*4882a593Smuzhiyun他们通过返回一些正常值范围之外的结果来表示出错。典型的例子是返回指针的函数,
812*4882a593Smuzhiyun他们使用 NULL 或者 ERR_PTR 机制来报告错误。
813*4882a593Smuzhiyun
814*4882a593Smuzhiyun
815*4882a593Smuzhiyun17) 不要重新发明内核宏
816*4882a593Smuzhiyun------------------------------
817*4882a593Smuzhiyun
818*4882a593Smuzhiyun头文件 include/linux/kernel.h 包含了一些宏,你应该使用它们,而不要自己写一些
819*4882a593Smuzhiyun它们的变种。比如,如果你需要计算一个数组的长度,使用这个宏
820*4882a593Smuzhiyun
821*4882a593Smuzhiyun.. code-block:: c
822*4882a593Smuzhiyun
823*4882a593Smuzhiyun	#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
824*4882a593Smuzhiyun
825*4882a593Smuzhiyun类似的,如果你要计算某结构体成员的大小,使用
826*4882a593Smuzhiyun
827*4882a593Smuzhiyun.. code-block:: c
828*4882a593Smuzhiyun
829*4882a593Smuzhiyun	#define sizeof_field(t, f) (sizeof(((t*)0)->f))
830*4882a593Smuzhiyun
831*4882a593Smuzhiyun还有可以做严格的类型检查的 min() 和 max() 宏,如果你需要可以使用它们。你可以
832*4882a593Smuzhiyun自己看看那个头文件里还定义了什么你可以拿来用的东西,如果有定义的话,你就不应
833*4882a593Smuzhiyun在你的代码里自己重新定义。
834*4882a593Smuzhiyun
835*4882a593Smuzhiyun
836*4882a593Smuzhiyun18) 编辑器模式行和其他需要罗嗦的事情
837*4882a593Smuzhiyun--------------------------------------------------
838*4882a593Smuzhiyun
839*4882a593Smuzhiyun有一些编辑器可以解释嵌入在源文件里的由一些特殊标记标明的配置信息。比如,emacs
840*4882a593Smuzhiyun能够解释被标记成这样的行:
841*4882a593Smuzhiyun
842*4882a593Smuzhiyun.. code-block:: c
843*4882a593Smuzhiyun
844*4882a593Smuzhiyun	-*- mode: c -*-
845*4882a593Smuzhiyun
846*4882a593Smuzhiyun或者这样的:
847*4882a593Smuzhiyun
848*4882a593Smuzhiyun.. code-block:: c
849*4882a593Smuzhiyun
850*4882a593Smuzhiyun	/*
851*4882a593Smuzhiyun	Local Variables:
852*4882a593Smuzhiyun	compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c"
853*4882a593Smuzhiyun	End:
854*4882a593Smuzhiyun	*/
855*4882a593Smuzhiyun
856*4882a593SmuzhiyunVim 能够解释这样的标记:
857*4882a593Smuzhiyun
858*4882a593Smuzhiyun.. code-block:: c
859*4882a593Smuzhiyun
860*4882a593Smuzhiyun	/* vim:set sw=8 noet */
861*4882a593Smuzhiyun
862*4882a593Smuzhiyun不要在源代码中包含任何这样的内容。每个人都有他自己的编辑器配置,你的源文件不
863*4882a593Smuzhiyun应该覆盖别人的配置。这包括有关缩进和模式配置的标记。人们可以使用他们自己定制
864*4882a593Smuzhiyun的模式,或者使用其他可以产生正确的缩进的巧妙方法。
865*4882a593Smuzhiyun
866*4882a593Smuzhiyun
867*4882a593Smuzhiyun19) 内联汇编
868*4882a593Smuzhiyun------------------------------
869*4882a593Smuzhiyun
870*4882a593Smuzhiyun在特定架构的代码中,你可能需要内联汇编与 CPU 和平台相关功能连接。需要这么做时
871*4882a593Smuzhiyun就不要犹豫。然而,当 C 可以完成工作时,不要平白无故地使用内联汇编。在可能的情
872*4882a593Smuzhiyun况下,你可以并且应该用 C 和硬件沟通。
873*4882a593Smuzhiyun
874*4882a593Smuzhiyun请考虑去写捆绑通用位元 (wrap common bits) 的内联汇编的简单辅助函数,别去重复
875*4882a593Smuzhiyun地写下只有细微差异内联汇编。记住内联汇编可以使用 C 参数。
876*4882a593Smuzhiyun
877*4882a593Smuzhiyun大型,有一定复杂度的汇编函数应该放在 .S 文件内,用相应的 C 原型定义在 C 头文
878*4882a593Smuzhiyun件中。汇编函数的 C 原型应该使用 ``asmlinkage`` 。
879*4882a593Smuzhiyun
880*4882a593Smuzhiyun你可能需要把汇编语句标记为 volatile,用来阻止 GCC 在没发现任何副作用后就把它
881*4882a593Smuzhiyun移除了。你不必总是这样做,尽管,这不必要的举动会限制优化。
882*4882a593Smuzhiyun
883*4882a593Smuzhiyun在写一个包含多条指令的单个内联汇编语句时,把每条指令用引号分割而且各占一行,
884*4882a593Smuzhiyun除了最后一条指令外,在每个指令结尾加上 \n\t,让汇编输出时可以正确地缩进下一条
885*4882a593Smuzhiyun指令:
886*4882a593Smuzhiyun
887*4882a593Smuzhiyun.. code-block:: c
888*4882a593Smuzhiyun
889*4882a593Smuzhiyun	asm ("magic %reg1, #42\n\t"
890*4882a593Smuzhiyun	     "more_magic %reg2, %reg3"
891*4882a593Smuzhiyun	     : /* outputs */ : /* inputs */ : /* clobbers */);
892*4882a593Smuzhiyun
893*4882a593Smuzhiyun
894*4882a593Smuzhiyun20) 条件编译
895*4882a593Smuzhiyun------------------------------
896*4882a593Smuzhiyun
897*4882a593Smuzhiyun只要可能,就不要在 .c 文件里面使用预处理条件 (#if, #ifdef);这样做让代码更难
898*4882a593Smuzhiyun阅读并且更难去跟踪逻辑。替代方案是,在头文件中用预处理条件提供给那些 .c 文件
899*4882a593Smuzhiyun使用,再给 #else 提供一个空桩 (no-op stub) 版本,然后在 .c 文件内无条件地调用
900*4882a593Smuzhiyun那些 (定义在头文件内的) 函数。这样做,编译器会避免为桩函数 (stub) 的调用生成
901*4882a593Smuzhiyun任何代码,产生的结果是相同的,但逻辑将更加清晰。
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun最好倾向于编译整个函数,而不是函数的一部分或表达式的一部分。与其放一个 ifdef
904*4882a593Smuzhiyun在表达式内,不如分解出部分或全部表达式,放进一个单独的辅助函数,并应用预处理
905*4882a593Smuzhiyun条件到这个辅助函数内。
906*4882a593Smuzhiyun
907*4882a593Smuzhiyun如果你有一个在特定配置中,可能变成未使用的函数或变量,编译器会警告它定义了但
908*4882a593Smuzhiyun未使用,把它标记为 __maybe_unused 而不是将它包含在一个预处理条件中。(然而,如
909*4882a593Smuzhiyun果一个函数或变量总是未使用,就直接删除它。)
910*4882a593Smuzhiyun
911*4882a593Smuzhiyun在代码中,尽可能地使用 IS_ENABLED 宏来转化某个 Kconfig 标记为 C 的布尔
912*4882a593Smuzhiyun表达式,并在一般的 C 条件中使用它:
913*4882a593Smuzhiyun
914*4882a593Smuzhiyun.. code-block:: c
915*4882a593Smuzhiyun
916*4882a593Smuzhiyun	if (IS_ENABLED(CONFIG_SOMETHING)) {
917*4882a593Smuzhiyun		...
918*4882a593Smuzhiyun	}
919*4882a593Smuzhiyun
920*4882a593Smuzhiyun编译器会做常量折叠,然后就像使用 #ifdef 那样去包含或排除代码块,所以这不会带
921*4882a593Smuzhiyun来任何运行时开销。然而,这种方法依旧允许 C 编译器查看块内的代码,并检查它的正
922*4882a593Smuzhiyun确性 (语法,类型,符号引用,等等)。因此,如果条件不满足,代码块内的引用符号就
923*4882a593Smuzhiyun不存在时,你还是必须去用 #ifdef。
924*4882a593Smuzhiyun
925*4882a593Smuzhiyun在任何有意义的 #if 或 #ifdef 块的末尾 (超过几行的),在 #endif 同一行的后面写下
926*4882a593Smuzhiyun注解,注释这个条件表达式。例如:
927*4882a593Smuzhiyun
928*4882a593Smuzhiyun.. code-block:: c
929*4882a593Smuzhiyun
930*4882a593Smuzhiyun	#ifdef CONFIG_SOMETHING
931*4882a593Smuzhiyun	...
932*4882a593Smuzhiyun	#endif /* CONFIG_SOMETHING */
933*4882a593Smuzhiyun
934*4882a593Smuzhiyun
935*4882a593Smuzhiyun附录 I) 参考
936*4882a593Smuzhiyun-------------------
937*4882a593Smuzhiyun
938*4882a593SmuzhiyunThe C Programming Language, 第二版
939*4882a593Smuzhiyun作者:Brian W. Kernighan 和 Denni M. Ritchie.
940*4882a593SmuzhiyunPrentice Hall, Inc., 1988.
941*4882a593SmuzhiyunISBN 0-13-110362-8 (软皮), 0-13-110370-9 (硬皮).
942*4882a593Smuzhiyun
943*4882a593SmuzhiyunThe Practice of Programming
944*4882a593Smuzhiyun作者:Brian W. Kernighan 和 Rob Pike.
945*4882a593SmuzhiyunAddison-Wesley, Inc., 1999.
946*4882a593SmuzhiyunISBN 0-201-61586-X.
947*4882a593Smuzhiyun
948*4882a593SmuzhiyunGNU 手册 - 遵循 K&R 标准和此文本 - cpp, gcc, gcc internals and indent,
949*4882a593Smuzhiyun都可以从 https://www.gnu.org/manual/ 找到
950*4882a593Smuzhiyun
951*4882a593SmuzhiyunWG14 是 C 语言的国际标准化工作组,URL: http://www.open-std.org/JTC1/SC22/WG14/
952*4882a593Smuzhiyun
953*4882a593SmuzhiyunKernel process/coding-style.rst,作者 greg@kroah.com 发表于 OLS 2002:
954*4882a593Smuzhiyunhttp://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
955