Kernel Coding Style

The Linux kernel has strict coding conventions. Following them is essential for upstream acceptance and code readability.

Why Coding Style Matters

  • Consistency: 20+ years of kernel code follows these rules
  • Readability: Easier to review and maintain
  • Upstream acceptance: Non-compliant patches are rejected
  • Tooling: checkpatch.pl enforces style automatically

Core Rules

Indentation: Tabs, Not Spaces

/* CORRECT: Tab indentation */
static int foo(void)
{
       if (condition) {
              do_something();
       }
}

/* WRONG: Space indentation */
static int foo(void)
{
    if (condition) {
        do_something();
    }
}
  • Use tabs (8 characters wide)
  • Tabs for indentation, spaces for alignment

Line Length: 80-100 Characters

Keep lines under 80 characters when possible, 100 max:

/* CORRECT: Break long lines sensibly */
ret = some_really_long_function_name(argument1, argument2,
                                     argument3, argument4);

/* WRONG: Excessively long line */
ret = some_really_long_function_name(argument1, argument2, argument3, argument4, argument5);

Brace Placement

Opening braces on the same line as the statement:

/* CORRECT */
if (condition) {
        do_something();
} else {
        do_other();
}

for (i = 0; i < n; i++) {
        process(i);
}

/* WRONG: K&R style for if/for/while */
if (condition)
{
        do_something();
}

Exception: Functions have opening brace on new line:

/* CORRECT for functions */
static int my_function(int x)
{
        return x * 2;
}

/* WRONG for functions */
static int my_function(int x) {
        return x * 2;
}

Single-Statement Bodies

Omit braces for single statements (usually):

/* CORRECT */
if (condition)
        do_something();

for (i = 0; i < n; i++)
        process(i);

/* Also CORRECT (some prefer braces always) */
if (condition) {
        do_something();
}

Exception: If one branch has braces, use them on all:

/* CORRECT */
if (condition) {
        do_something();
        do_more();
} else {
        do_other();  /* Braces because if-branch has them */
}

Spaces

Around keywords:

if (condition)    /* Space after if */
for (i = 0; ...)  /* Space after for */
while (running)   /* Space after while */
switch (value)    /* Space after switch */
return value;     /* Space after return if returning value */

Around operators:

x = a + b;        /* Spaces around binary operators */
x += 1;           /* Spaces around assignment */
if (a == b)       /* Spaces around comparison */

No space after function names:

function(args);   /* CORRECT */
function (args);  /* WRONG */

No space inside parentheses:

if (condition)    /* CORRECT */
if ( condition )  /* WRONG */

Naming Conventions

Functions and variables: lowercase with underscores

static int read_sensor_data(void);
int buffer_size = 1024;

Macros and constants: UPPERCASE

#define MAX_BUFFER_SIZE 4096
#define DRIVER_NAME "my_driver"

Types: lowercase with _t suffix (or no suffix)

typedef struct {
        int x, y;
} point_t;

Global variables: Prefix with module name

static int mydrv_debug_level = 0;
static struct device *mydrv_dev;

Function Style

Declaration

/* Return type on same line if it fits */
static int my_function(int arg1, char *arg2)

/* Or on separate line if long */
static struct some_very_long_type *
create_new_object(struct parent *parent, const char *name)

Argument Alignment

/* Align continued arguments */
ret = register_device(dev, name,
                      flags, mode,
                      callback);

Function Length

  • Aim for functions under 40-50 lines
  • One function, one purpose
  • If it’s too long, split it

Comments

C-style Comments

/* This is a single-line comment */

/*
 * This is a multi-line comment.
 * Note the leading asterisks aligned.
 */

Never use C++ comments in C files:

// WRONG: Don't use C++ style comments

Function Documentation

Use kernel-doc format for exported functions:

/**
 * my_function - Brief description
 * @arg1: Description of first argument
 * @arg2: Description of second argument
 *
 * Longer description of what this function does.
 * Can span multiple paragraphs.
 *
 * Context: Can be called from process context only.
 * Return: 0 on success, negative errno on failure.
 */
int my_function(int arg1, char *arg2)
{
        ...
}

Using checkpatch.pl

The kernel includes a style checker:

# Check a file
/kernel/linux/scripts/checkpatch.pl --file mydriver.c

# Check a patch
/kernel/linux/scripts/checkpatch.pl mypatch.patch

# Stricter checking
/kernel/linux/scripts/checkpatch.pl --strict --file mydriver.c

Common checkpatch Warnings

Warning Fix
“code indent should use tabs” Replace spaces with tabs
“line over 80 characters” Break the line
“space required after ‘,’” Add space
“braces {} not necessary” Remove braces from single statement
“trailing whitespace” Remove trailing spaces
“Missing Signed-off-by” Add SOB line to patch

SPDX License Identifier

Every source file must start with SPDX identifier:

// SPDX-License-Identifier: GPL-2.0
/*
 * my_driver.c - My awesome driver
 */

Common licenses:

  • GPL-2.0 - GNU GPL version 2 only
  • GPL-2.0-only - Same as above (explicit)
  • GPL-2.0-or-later - GPL v2 or any later version
  • GPL-2.0 OR BSD-2-Clause - Dual-licensed

Kernel-Specific Patterns

Error Codes

Return negative errno values:

if (error)
        return -EINVAL;  /* Not EINVAL, not -1 */

Goto for Cleanup

Standard cleanup pattern:

static int init_device(void)
{
        int ret;

        ret = allocate_resources();
        if (ret)
                return ret;

        ret = setup_hardware();
        if (ret)
                goto err_setup;

        ret = register_device();
        if (ret)
                goto err_register;

        return 0;

err_register:
        teardown_hardware();
err_setup:
        free_resources();
        return ret;
}

NULL Checks

/* CORRECT */
if (!ptr)
        return -EINVAL;

if (ptr)
        use_ptr(ptr);

/* Also acceptable but verbose */
if (ptr == NULL)
        return -EINVAL;

Boolean Expressions

/* CORRECT: Use bare expression */
if (is_valid)
        ...

/* WRONG: Redundant comparison */
if (is_valid == true)
        ...

Static Analysis with Sparse

Sparse is a semantic checker for C that understands kernel address-space annotations:

# Check your module with Sparse
make C=1 modules

# Check the whole kernel build
make C=2 allmodconfig

Key Annotations

Annotation Purpose
__user Pointer to user space memory
__iomem Pointer to I/O mapped memory
__kernel Pointer to kernel space memory
__bitwise Type-restricted bitwise integer
__force Override address space check (use sparingly)

Sparse detects dangerous pointer confusions — for example, passing a __user pointer where a kernel pointer is expected, which would bypass copy_from_user() safety.

See Sparse Documentation for details.

Summary

Key style rules:

  • Tabs for indentation (8 spaces wide)
  • 80-100 character line limit
  • K&R brace style for control structures, function-style for functions
  • Spaces around operators and keywords
  • lowercase_with_underscores for names
  • Use checkpatch.pl before submitting
  • Use Sparse (make C=1) to catch address-space bugs

Resources

Next

Learn about kernel data types and endianness handling.


Back to top

Linux Driver Development Guide is a community resource for learning kernel driver development. Not affiliated with the Linux Foundation. Content provided for educational purposes.

This site uses Just the Docs, a documentation theme for Jekyll.