这篇短小的文档用于描述linux内核编程中推荐的编程风格。编程风格是很个人
化的东西,我不想把我的观点_强加_给任何人,但这是我必须维护的代码中所遵循
的,我也建议其他部份的代码也能违背它。请起码给这儿的观点一些考虑。
首先,我建议你复印一份GNU代码风格,不是去读它linux 内核 命名法,而是把它烧了,这是个很
不错的姿态。
下边就是Linux内核编程风格:
第一章:缩进
制表符(tabs)占8个字符,所以缩进也是8个字符。有些异端运动想使用4个字符
(甚至是2个字符)的缩进,这和把PI(圆周率)定为3没哪些两样。
缘由:缩进的根本目的是拿来清晰地标识一个控制块的起始。非常是当你连续盯
着屏幕看了20个小时后,你才会感悟到更长的缩进的用处了。
现今,有些人提出8字符缩进会促使代码太偏向一侧,当使用80字符的终端
时很难阅读。答案是假如你须要三层以上的缩进,这么你已然完蛋了,应当改改
你的程序了。
简而言之,8字符缩进促使阅读代码更为容易,而且在你的缩进层次过深时提出
警告。应当留意这样的警告。
关于这一点,我不能指摘,4个字符的缩进确实有它的用处,缩进太多反倒看着累。
但是有时侯仅仅两层嵌套都会使代码很长。
第二章:括弧的位置
括弧位置的问题在C编程风格中常常被提出。和缩进大小不同,括弧位置的选择
并没有太多技术上的诱因,而更多的是个人的喜好。例如Kernighan和Ritchie的
弟子们把左括弧置于一行的最后,把右括弧置于一行的开始,象这样:
if(xistrue){
wedoy
}
然而,函数是一种特殊的情况,函数的左括弧置于下一行的开始,象这样:
intfunction(intx)
{
bodyoffunction
}
全世界的异端人士强调这些不一致的做法...嗯...不太一致,并且所有思维正
确的人晓得(a)K&R是_对_的(b)K&R是对的。并且,函数确实是特殊的(你在C
中未能对函数进行嵌套)。
注意到右括弧完全占有单独的一行,_除非_当它前面还有未完成的句子,例如do
句子中的“while”或者if句子中的“else”,想这样:
do{
bodyofdo-loop
}while(condition);
和
if(x==y){
..
}elseif(x>y){
...
}else{
....
}
缘由:K&R。
还有,注意到这些括弧的布局方式还降低了空行(或则说是几乎是空行)的数量,
但是没有降低可读性。由于你屏幕上的空行是不可回收资源(这儿想一下25行的
终端屏幕),这样你会有更多的空行用于加注释。
第三章:命名
C是个斯巴达式(崇尚简约风格的)语言,所以你的命名方式也应当这么。与
Modula-2和Pascal程序员不同,C程序员不使用
ThisVariableIsATemporaryCounter这样甜美的名子。一个C程序员会把一个变量
称作“tmp”linux查看端口占用,这样的变量名更容易写,但是理解上去也不算太难。
_并且_,虽然人人就会对大小写混杂的名子蹙眉头,全局变量名则必须这么。管
一个全局函数叫“foo”是故意找岔。
_全局_变量(只有在_真正_须要时才使用)须要有个描述性强的名子,这点和全
局函数一样。假如你有个函数用于对活跃用户进行计数,你应当叫它
“count_active_users()”,而不是“cntusr()”。
把函数的类型加入到名子中(所谓的瑞士命名法)是脑损伤的表现-编译器
晓得类型,才能对它进行检测,这些命名法只会把程序员自己搞晕。为啥谷歌做
了这么多饱含bug的程序。哈哈^_^,有道理,不要作茧自缚
_局部_变量应当短小简练。假如你有个随机的整数循环变量,可能最好叫它“i”。
把它称作“loop_counter”是效率低下的,在不会发生混淆的情况下。类型地,
“tmp”可以被用于任何类型的储存临时值的变量。
假如你害怕混淆你的局部变量,这么你才会有另一个问题,所谓的函数膨胀荷尔
蒙失衡综合症,请看下一章。
第四章:函数
函数应当短小而优雅,并且只能做一件事。她们应当只用一两屏幕(我们都晓得,
ISO/ANSI标准屏幕大小是80x24)才能装下,只做而且做好一件事。
函数的最大宽度应当与函数的复杂性和缩进层次成正比。所以,假若你有个只有
一个很长(但很简单)的case句子的函数,对许多case做一些甚少的操作,这么
这个函数长点也没有关系。
然而,假若你有一个复杂的函数,你害怕一个中等智力的初三中学生可能难以理解,
这么你应当更严格地遵循最大宽度限制。使用有描述性名子的帮助函数(你可以
让编译器in-line这种帮助函数,假若你觉得性能很重要的话,但是编译器估计
会比你做的要好)。
函数的另一个指标是局部变量的数量kali linux,局部变量的数量不应超过5-10个,否则一
定是那里有问题了。再设计一下这个函数,把它分解得更小一些。人的脑部通常
可以同时跟踪7个不同的东西,超过了7个都会晕菜。其实你很聪明,不过可能你
有时会想理解一下两礼拜前所写的代码。
第五章:注释
注释是好东西,不过存在过于注释的危险。_永远_不要在注释中解释你的代码是
怎样工作的:更好的做法是写出工作方法显而易见的代码linux 内核 命名法,解释糟糕的代码是浪
费时间。
通常来说,注释应当说明代码在做哪些,而不是如何做。而且,不要把注释加在
函数主体中:假如函数太复杂以至于必须对各个部份进行注释,这么你可能要再
去读读第四章。你可以加入一些短小的注释来提醒或警告一些聪明(或难看)的
做法,但不要太过度。更好的选择是,把注释置于函数头,说明函数在做哪些,
可能还包括它为何做。
第六章:你的代码乱七八糟
没哪些,我们都碰到过。你可能从老Unix用户哪里据说过“GNUemacs”会手动
对齐C源代码,但缺省的设置不是挺好(事实上,缺省设置比胡乱敲击还糟糕-
一群使用GNUemacs猴子永远不会作出漂亮的程序)。
靠!我就是用emacs的!不过如今手动对齐还算可以了。
所以,你或则彻底仍掉GNUemacs,或则采用更理性的设置。假如选择前者,你
可一把下边的代码加到你的.emacs文件中:
(defunlinux-c-mode()
"CmodewithadjusteddefaultsforusewiththeLinuxkernel."
(interactive)
(c-mode)
(c-set-style"K&R")
(setqc-basic-offset8))
这会定义M-xlinux-c-mode命令。当编撰Linux模块时,假若你把字符串“-*-
linux-c-*-”放在文件的头两行中,这个模式都会被手动激活。还有,假如你
想在编辑/usr/src/linux目录下的源文件时linux-c-mode被手动激活,你在你的.
emacs文件中须要加入
(setqauto-mode-alist(cons'("/usr/src/linux.*/.*\.[ch]$".linux-c-mode)
auto-mode-alist))
然而纵使你用不了emacs,并不是世界末日:你还可以使用“indent”。
又一次,GNUindent使用了和GNUemacs一样的脑死亡设置,所以你须要给它一
些命令行选项。并且,这不算太坏,由于虽然是GNUindent的作者们也意识到了
K&R的权威性(GNU的人也不是魔鬼,她们只是在这件事上被欺骗了),所以你可
以使用选项“-kr-i8”(表示“K&R,8字符缩进”)运行indent。
“indent”有很多选项,非常是注释布局部份,你可能想瞧瞧它的man指南。但
是请记住:“indent”不能更改糟糕的程序。
个人认为现今emacs对缩进对齐的处理早已不错了,问题在于你使用不同的Linux
发行版,都会面对不同的.emacs文件,有时侯我不得不随身携带我的.emacs文件,
或则把它放到我的email的储存箱上面
第七章:配置文件
配置选项(arch/xxx/config.in,以及所有Config.in文件)使用了有些不同的
缩进形式。
代码中使用的是3字符缩进,config-选项中应当使用2字符缩进标示依赖关系。
前者只应用于bool/tristat选项。对于其他选项,采用你觉得最合适的缩进形式
就可以了。诸如:
if["$CONFIG_EXPERIMENTAL"="y"];then
tristate'Applynitroglycerineinsidethekeyboard(DANGEROUS)'CONFIG_BOOM
if["$CONFIG_BOOM"!="n"];then
bool'Outputnicemessageswhenyouexplode'CONFIG_CHEER
fi
fi
通常来说,所有不稳定的选项应当标为CONFIG_EXPERIMENTAL。所有可能受损数
据的的选项应当标为(DANGEROUS),其他的试验选项应当标为(EXPERIMENTAL)。
第八章:数据结构
供多线程使用的数据结构应当采用引用计数(referencecounts)。在内核中,
垃圾回收(garbagecollection)是不存在的(内核之外的垃圾回收效率不高),
这意味着你_必须_使用引用计数。
引用计数的使用能防止锁的使用,使不同的用户才能并行使用数据结构-不需
要担忧结构会由于睡眠而忽然消失。
注意到加锁_不是