Master Linux Kernel Coding Style: Tools, Rules, and Best Practices
This guide explains why adhering to the Linux kernel coding style matters, introduces automatic tools such as checkpatch.pl, Lindent, and astyle for fixing style violations, and details the core conventions for indentation, line length, brace placement, naming, comments, macros, and other critical aspects of kernel C code.
From Coding‑Style Errors to Solutions
When a patch for a Linux kernel driver was applied, many style violations caused the patch to be rejected; the issue was resolved by re‑creating the patch after following the kernel coding guidelines. As code bases grow, automated tools become essential for maintaining style consistency.
Quick Tools for Fixing Coding Style
scripts/checkpatch.pl
This script checks whether a patch complies with the kernel coding standards. Use the -f option when checking a regular source file.
scripts/Lindent
The Lindent program located in the scripts directory can automatically fix indentation problems, but it requires the external indent utility. Install it on Ubuntu with apt-get install indent.
astyle
Highly recommended for its convenience; it can convert code to linux, java, gnu, and other styles with a single command.
Linux Kernel Code Style Overview
The official documentation (Documentation/CodingStyle) defines the preferred style. Key points include:
1. Indentation
Tabs are 8 characters wide; using 4‑character tabs is discouraged. Proper indentation helps identify block boundaries, especially after long coding sessions. For deep nesting, consider refactoring rather than increasing indentation depth.
In switch statements, align the switch keyword and its case labels on the same column to avoid extra indentation.
switch (suffix) {
case 'G':
case 'g':
mem <<= 30;
break;
case 'M':
case 'm':
mem <<= 20;
break;
case 'K':
case 'k':
mem <<= 10;
/* fall through */
default:
break;
}Avoid placing multiple statements on one line unless the intent is explicitly hidden.
if (condition) do_this;
do_something_everytime;2. Breaking Long Lines
Limit line length to 80 columns. Split longer statements into meaningful fragments, except for user‑visible strings (e.g., printk) which should remain intact for easy grepping.
3. Braces and Spaces
Follow the K&R style: opening braces at the end of the controlling line, closing braces on a line by themselves. Function definitions place the opening brace on the next line.
if (x is true) {
we do y
} switch (action) {
case KOBJ_ADD:
return "add";
case KOBJ_REMOVE:
return "remove";
default:
return NULL;
}Single‑statement blocks need not use braces, but if a block contains only one conditional branch, both branches should use braces.
if (condition) {
do_this();
do_that();
} else {
otherwise();
}3.1 Spaces
Keywords such as if, for, while are followed by a space; exceptions include sizeof, typeof, alignof, and __attribute__, which behave like functions and should not have a space before the opening parenthesis.
s = sizeof(struct file);Place a space around most binary and ternary operators, but not after unary operators.
a = b + c;
++i;
--j;Avoid trailing whitespace; Git will warn about it and can automatically strip it.
4. Naming
Prefer short, descriptive names. Use tmp for temporary variables, i for loop counters, and descriptive names for global variables and functions (e.g., count_active_users() instead of cntuser()).
5. Typedef
Generally avoid typedef unless you need opaque types, clear integer‑type distinctions, or specific kernel‑internal uses. When used, follow the documented conventions.
6. Functions
Functions should be short enough to fit on one or two screens and perform a single task. Limit local variables to 5‑10; split larger functions into helpers. Exported functions must follow the return‑value conventions described later.
int system_is_up(void) {
return system_state == SYSTEM_RUNNING;
}
EXPORT_SYMBOL(system_is_up);7. Centralized Exit Paths
Use goto for common cleanup when a function has multiple exit points. Label names should be descriptive (e.g., out_free_buffer:) and avoid generic numbering.
int fun(int a) {
int result = 0;
char *buffer;
buffer = kmalloc(SIZE, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
if (condition1) {
while (loop1) {
...
}
result = 1;
goto out_free_buffer;
}
...
out_free_buffer:
kfree(buffer);
return result;
}8. Comments
Write comments that explain *what* the code does, not *how*. Prefer kernel‑doc style for API functions. Use the multi‑line comment style shown in the kernel documentation.
/*
* This is the preferred style for multi-line
* comments in the Linux kernel source code.
* Please use it consistently.
*/9. Formatting Tools
GNU Emacs can be configured for kernel style, but its defaults are unsuitable. Use the provided Emacs Lisp snippet to set linux-tabs-only style for files under ~/src/linux-trees. Alternatively, use indent with -kr -i8 or scripts/Lindent.
10. Kconfig Files
Indent config lines with a tab; indent help text an additional two spaces. Mark dangerous options clearly in the description string.
config AUDIT
bool "Auditing support"
depends on NET
help
Enable auditing infrastructure ...11. Data Structures
Expose reference‑counted structures when they are visible outside a single execution context. Reference counting prevents premature deallocation and allows lock‑free concurrent access.
12. Macros, Enums, and RTL
Macro and enum names should be uppercase; function‑like macros may use lowercase. Prefer inline functions over complex macros, and wrap multi‑statement macros in a do { ... } while (0) block.
#define macrofun(a, b, c) \
do { \
if (a == 5) \
do_this(b, c); \
} while (0)13. Kernel Logging
Use the appropriate device‑specific macros ( dev_err(), dev_warn(), etc.) or generic pr_* macros for messages. Avoid printing raw numbers and ensure messages are clear and unambiguous.
14. Memory Allocation
Prefer kmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc(), and vzalloc(). Pass sizeof(*ptr) rather than the type name to avoid bugs when the pointer type changes.
p = kmalloc(sizeof(*p), GFP_KERNEL);15. Inline Functions
Inline functions are useful for small, performance‑critical code, but overusing them inflates the kernel binary and harms cache performance. Generally, functions longer than three lines should not be inlined unless the compiler can fully optimize them away.
16. Return Values and Naming
Functions that perform actions should return error codes (negative on failure, zero on success). Predicate functions should return a boolean‑style value (1 for true, 0 for false). Exported functions must follow this convention.
17. Re‑using Kernel Macros
Use existing macros from include/linux/kernel.h such as ARRAY_SIZE(), FIELD_SIZEOF(), min(), and max() instead of redefining them.
18. Editor Modelines
Do not embed editor‑specific modelines (Emacs, Vim, etc.) in source files; they interfere with other developers' configurations.
19. Inline Assembly
Use inline assembly only when necessary; otherwise prefer C. When writing multi‑instruction inline asm, separate instructions with newlines and end each line (except the last) with a backslash‑newline ( \n\t) for proper formatting.
asm ("magic %reg1, #42
\t"
"more_magic %reg2, %reg3"
: /* outputs */
: /* inputs */
: /* clobbers */);20. Conditional Compilation
Avoid scattering #if / #ifdef throughout .c files. Prefer placing conditionals in header files or using IS_ENABLED() macros so the compiler can perform constant folding while still checking the code for correctness.
if (IS_ENABLED(CONFIG_SOMETHING)) {
...
}Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
