Fundamentals 32 min read

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.

Liangxu Linux
Liangxu Linux
Liangxu Linux
Master Linux Kernel Coding Style: Tools, Rules, and Best Practices

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)) {
    ...
}
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

KernelCLinuxcoding styleAstyleCheckpatchLindent
Liangxu Linux
Written by

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.)

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.