zerons's Blog

For The Dream

linux 内核代码格式 Documentation/CodingStyle

zerons posted @ 2014年12月08日 11:33 in chanllenge , 677 阅读

tabs为8空格, 这样对结构块的开始结尾比较清晰, 特别当你对着电脑看了很多小时, 大缩进让看代码更容易. 有人会说8缩进让代码太靠右了, 一行里面很难写完, 如果你有了至少四层的缩进, 那只能说你的代码写太差了.

不要在一行里面写多条语句, 除非你想做一些特别的事.

避免奇怪的表达式.

不要用空格代表缩进.

每行最多有80个字符

大括号的用法, 一般控制结构前一个大括号在行尾, 后一个大括号占一行的首非空字符. 函数的时候, 两半大括号都占一行. 在一般只有一条语句的控制结构里面最好不使用{}

        比如:

        if (condition)

                do_this;

        或者:

        if (condition)

                do_this;

        else

                do_else;

但是如果有一个分支只有一条语句, 每个里面都使用{}

 

多数关键字后用一个空格, 除了(sizeof, typeof, alignof, __attribute__). 在(后面和)前面不要加多余的空格. 指针的*紧贴着指针名, 像char *pointer; char *match_strdup(substring_t *s); 在下列运算符左右都加一个空格= + - < > * / % | & ^ <= >= == != ? :   但是&(取地址) *(指针) + - ~(取反) !(非) sizeof typeof alignof __attribute__ 后面不加空格. ++ -- 前面不要或后面不要空格.

 

变量名函数名, 不要使用混合大小写的名字(一些全局的除外), 例如, 全局函数想计算当前活动的用户数, 函数名应该是count_active_users()或者更简单的, 而不是cntusr(). 不要把类型加进变量名或者函数名中.  本地(局部)变量或函数的命名应该简洁明了, 像循环计数i或者一个临时tmp; 一个函数里面不要太多变量以致于自己都容易弄混...

 

不要给结构体或者指针用typedef. typedef只用于(totally opaque objects, clear integer types, use sparse to literally create a new type for type_checking, new types identical to C99 types, types safe for use in userspace, ==), 一个标准就是永远不要用typedef,

 

函数应该尽量短, 只做一件事就好. 长短一两页即可(80x24), do one thing and do it well.

当然, 如果你的函数里面有一个很长的switch-case结构. 或者, 你有一个比较复杂的函数(大一的学生都看不懂)you should adhere to the maximum limits all the more closely, 使用恰当名字的函数.

函数的局部变量应该在5-10, 否则你就走太远了.

源码中函数前后用空白行分开. 如果函数需要被导出, EXPORT*宏应该在}的下一行

函数声明中, 参数应该也包括参数名,

 

适当的使用goto, 当一个函数有多个退出点的时候,

 

注释, 适当的使用注释, 不要解释你的代码是怎么工作的, 解释你的代码是做什么的, 而不是怎么做的.

尽量不要在一个函数体内部写注释.

内核函数注释有特定的格式, Documentation/kernel-doc-nano-HOWTO.txt and scripts/kernel-doc

linux使用C89格式注释/*...*/, 不要使用C99// ... 注释

多行注释如下

        /*

         * something

         * something

         */

 

emacs用户

 

Kconfig文件格式   Documentation/kbuild/kconfig-language.txt

 

各种数据结构都应该有一个引用计数, 内核中是没有垃圾收集机制的. 如果另外一个线程能使用你的数据结构但是却没有一个引用计数, 很可能就是一个bug了.

 

宏, 枚举和RTL

避免使用宏的情况: 里面包含控制流的, 如exit return; 宏里面包含了一个局部本地变量的; 宏被当作左值用了; 宏定义时的封装问题

 

输出内核信息

输出信息要准确明了

 

函数返回值问题, if the name of a function is an action or an imperative command, the function should return an error-code integer. if the name is a predicate, the function should return a "succeeded" boolean.

 

不要重复做轮子, include/linux/kernel.h里面包含一些常用的宏变量

 

不要带有一些编辑器插入的语句

 

 

2014-12-17 update

1. 头文件

        例子: asm/delay.h => linux/delay.h (https://groups.google.com/forum/#!topic/fa.linux.kernel/yccGyGoT3pQ)

 

2. printk VS pr_*

        (http://stackoverflow.com/questions/22077540/order-of-preference-printk-vs-dev-dbg-vs-netdev-dbg, https://lkml.org/lkml/2014/7/14/174)

        Depending on what you are coding you should use a different print style:

                printk(): never

                pr_debug(): always good

                dev_dbg(): prefered when you have a struct device object

                netdev_dbg(): prefered when you have a struct netdevice object

                [something]_dbg(): prefered when you have a that something object

 

3. Documentation/zh_CN/CodingStyle


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter