Linux内核编码风格


Coding style is all about readability and maintainability using commonly available tools.  

缩进


所有的缩进均应是8字符格式。

If you need more than 3 levels indentation, you're screwed anyway, and should 
fix your program.

注:关于这点保留意见,目前我(也)比较习惯用4字符格式的TAB。

Don't put multiple assignments on a single line.

Get a decent editor and don't leave whitespace at the end of lines.

换行


每行的长度限制在80各字符

However, never break user-visible strings such as printk messages, because 
that breaks the ability to grep for them.  

括号和空格


As shown to us by the prophets Kernighan and Ritchie, the preferred way is to 
put the opening brace on the line, and push the closing brace first, thusly:
if (x is true) {
        we do y
}

上面的规则适用于所有的代码块,除了函数。

Do not unnecessarily use braces where a single statement will do.

        if (condition)
                action();

and
        if (condition)
                do_this();
        else
                do_that();

This does not apply if only one branch of a conditional statement is a single 
statement; in the latter case use braces in both braches.

注:这个规则我保留意见。由于任何under-developing的代码片段都没办法保证在“现在和将来”都仅包含一条语句。因此我的选择是:在任何代码片段/分支处,均使用括号。

在Linux kernel的编程风格中,空格的使用主要依赖于function-versus-keyword的使用。

Use a space after (most) keywords.
The notable exceptions are sizeof, typeof, alignof, and __attribute__,
which look somewhat like functions.

Do not add spaces around (inside) parenthesized expressions.

When declaring pointer data or a function that returns a pointer type, the 
preferred usd of '*' is adjacent to the data name or function name and not 
adjacent to the type name. Examples:
    char *line_banner;
    char *match__strdup(substring_t *s);

Use one space around (on each side of) most binary and ternary operators, 
but no space after unary operators.

命名


GLOBAL variables need to have descriptive names, as do global functions.

Encoding the types of a function into the name (so-called Hungarian notaion) 
is brain damaged - the compiler knows the types anyway and can check those, and 
it only confuses the programmer. No wonder MicroSoft makes buggy programs.
=.= 黑的漂亮  

LOCAL variable names should be short, and to the point.

自定义类型


typedefs应尽量少用。仅在满足一下条件之一时,typedefs才算是能适当提高可读性的选择。

  • totally opaque objects (where the typedef is actively used to _hide_ what the
    object is).
  • clear integer types, where the abstaction _helps_ avoid confusion whether it
    is ‘int’ or ‘long’. 例如 u8/u16/u32就是很好的抽象
  • when you use sparse to literally create a _new_ type for type-checking.
    — 暂时不太理解:-(
  • New types which are identical to standard C99 types, in certain exceptional
    circumstances.
  • Types safe for use in userspace. — 暂时不太理解:-(

函数


Functions should be short and sweet, and do just one thing. 
They should fit on one or two screenfuls of text.

The maximum length of a function is inversely proportional to the complexity 
and indentation level of that function.
-- 当函数逻辑简单时,稍微长一点没有关系;
-- 当函数逻辑复杂时,可以通过helper函数缩短函数的长度。同时如果需要考虑性能,inline是个不错的选择。

Another measure of the function is the number of local variables. 
They shouldn't exceed 5-10, or you're doing something wrong.
依据:A human brain can generally easily keep track about 7 different things.

In source file, seperate functions with one blank line.

If the function is exported, the EXPORT macro for it should follow immediately 
after the closing function brace line.

In function prototype, include parameter names with their data types.

集中管理函数的退出条件


这部分主要是讨论goto的实用技巧(goto反对党请绕道)。

The goto statement comes in handy when a function exits from multiple locations 
and some common works such as cleanup has to be done.

Choose label names which say what the goto does or why the goto exits.

goto语句在以下情况下,可以合理的使用:

  • unconditional statements are easier to understand and follow
  • nesting is reduced
  • errors by not updating individual exit points when making modifications are prevented — 暂时不理解:-(
  • save the compiler work to optimize redundant code away

注释


这部分主要是一些避免over-commenting的原则。

NEVER try to explain HOW your code works in a commment:
it's much better to write the code so the \_working\_ is obvious, and it's a 
waste of time to explain badly written code.

Generally, you want your comments to tell WHAT your code does, not HOW. --发人深省啊!

Try to avoid putting comments inside a function body.
Instead, put the comments at the head of the function, telling people what it does,
and possibly WHY it does it.  

Linux style for comments is the C89 "/* ... */" style.
Don't use C99-style "// ..." comments.

The preferred style for long (multi-line) comments is:
/*
 * This is the preferred style for multi-line
 * comments in the Linux kernel source code.
 * Please use it consistently.
 */

宏,枚举


Names of macros defining constants and labels in enums are capitalized.

Enums are preferred when defining serveral related constants.

CAPITALIZED macro names are appreciated but macros resembling functions may be  
named in lower case.

Generally, inline functions are preferable to macros resembling functions. -- 个人更认同这一原则。

Macros with multiple statements should be eclosed in a do-which block.

打印内核消息

Make the messages concise, clear, and unambiguous.

For messages that aren't associated with a particular device, <linux/printk.h> 
defines pr_notice(), pr_info(), pr_warn(), pr_err(), etc.

inline的使用


Abundant use of the inline keyword leads to a much bigger kernel, which in turn 
slows the system as a whole down, due to a bigger icache footprint for the CPU 
and simply because there is less memory available for the pagecache.

A reasonable rule of thumb is to not put inline at functions that have more 
than 3 lines of code in them.  --即,inline应限制用于小函数 

函数返回值


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.

不要重复发明内核宏定义

The header file include/linux/kernel.h contains a number of macros that you 
should use, rather than explicitly coding some variant of them yourself.

条件编译


Wherever possible, don't use preprocessor conditional (#if, #ifdef) in .c files, 
doing so makes code harder to read and logic harder to follow.

Prefer to compile out entire functions, rather than portions of functions or 
portions of expressions.

Within code, where possible, use the IS_ENABLED macro to convert a Kconfig 
symbol into a C boolean expression, and use it in a normal C conditional.

At the end of any non-trivial #if or #ifdef block (more than a few lines), 
place a comment after the #endif on the same line, noting the conditional 
expression used. For instance:
    #ifdef CONFIG_SOMETHING
    ...
    #endif /* CONFIG_SOMETHING */

参考资料


Linux kernel coding style