Style guide of the Linux Kernel
a quick look, including the most important sections here for my reference.
2 minute Presentation
Recommend the full read too:
https://www.kernel.org/doc/Documentation/process/coding-style.rst
Writing Clean, Kernel-Level C: A Practical Guide to Linux Kernel Coding Style
Whether you're hacking on drivers, tinkering with kernel modules, or just want to write tighter C code, the Linux kernel coding style guide offers timeless advice. This post summarizes the 22 chapters of the official guide into practical, digestible takeaways.
1. Indentation: Tabs, Not Spaces
Use tabs (8 spaces wide) for indentation—no spaces. If your code is shifting too far right, it's a sign of deep nesting, which is discouraged.
Rule of thumb: If you're more than 3 levels deep, refactor.
The preferred way to ease multiple indentation levels in a switch statement is
to align the ``switch`` and its subordinate ``case`` labels in the same column
instead of ``double-indenting`` the ``case`` labels. E.g.:
.. code-block:: c
switch (suffix) {
case 'G':
case 'g':
mem <<= 30;
break;
case 'M':
case 'm':
mem <<= 20;
break;
case 'K':
case 'k':
mem <<= 10;
fallthrough;
default:
break;
}
Don't put multiple statements on a single line unless you have
something to hide:
.. code-block:: c
if (condition) do_this;
do_something_everytime;
Don't use commas to avoid using braces:
.. code-block:: c
if (condition)
do_this(), do_that();
Always uses braces for multiple statements:
.. code-block:: c
if (condition) {
do_this();
do_that();
}
Don't put multiple assignments on a single line either. Kernel coding style
is super simple. Avoid tricky expressions.2. Break Long Lines Logically
Limit lines to 80 characters. Break long statements into meaningful chunks, aligning with open parentheses if needed.
Never break strings like printk() messages—makes grepping harder.
3. Braces & Spaces: K&R Style Wins
Use Kernighan & Ritchie brace style:
if (condition) {
do_something();
}The other issue that always comes up in C styling is the placement of
braces. Unlike the indent size, there are few technical reasons to
choose one placement strategy over the other, but the preferred way, as
shown to us by the prophets Kernighan and Ritchie, is to put the opening
brace last on the line, and put the closing brace first, thusly:
.. code-block:: c
if (x is true) {
we do y
}
This applies to all non-function statement blocks (if, switch, for,
while, do). E.g.:
.. code-block:: c
switch (action) {
case KOBJ_ADD:
return "add";
case KOBJ_REMOVE:
return "remove";
case KOBJ_CHANGE:
return "change";
default:
return NULL;
}
However, there is one special case, namely functions: they have the
opening brace at the beginning of the next line, thus:
.. code-block:: c
int function(int x)
{
body of function
}
Heretic people all over the world have claimed that this inconsistency
is ... well ... inconsistent, but all right-thinking people know that
(a) K&R are **right** and (b) K&R are right. Besides, functions are
special anyway (you can't nest them in C).Function definitions place the opening brace on a new line. Use spaces after keywords, not inside parentheses.
Do not unnecessarily use braces where a single statement will do.
.. code-block:: c
if (condition)
action();
and
.. code-block:: c
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 branches:
.. code-block:: c
if (condition) {
do_this();
do_that();
} else {
otherwise();
}
Also, use braces when a loop contains more than a single simple statement:
.. code-block:: c
while (condition) {
if (test)
do_something();
}4. Naming: Be Descriptive, Not Cute
Local vars: short (e.g.,
i,tmp)Global vars/functions: descriptive (e.g.,
count_active_users)
Avoid Hungarian notation. Let the compiler infer types.
5. Typedefs: Use Sparingly
Avoid typedef for structs and pointers unless:
It's an opaque type (e.g.,
pte_t)It's for fixed-width integers (e.g.,
u32)You're interfacing with userspace (
__u32)
6. Functions: Keep 'Em Short
Should fit in 1–2 screenfuls (~80x24)
Limit local vars to ~5–10
Break complex logic into helper functions
Bloated functions? That's a function-growth-hormone-imbalance syndrome.
7. Exiting Functions: Goto is OK
Use goto for centralized cleanup:
if (error) goto cleanup;Avoid multiple return points that repeat code. Labels should explain purpose, like out_free_buf:.
8. Comments: Say What, Not How
Prefer explaining what the code does. Keep multi-line comments like:
/* * Explain the purpose clearly. */Avoid over-commenting or explaining obvious logic.
9. Formatting: Don't Trust Your Editor
Don't rely on emacs or indent defaults. Use clang-format or .editorconfig. Avoid including editor-specific modelines in source files.
10. Kconfig Files: Tab + Two Spaces
Kconfig entries are indented with one tab, and help text is indented with two spaces.
11. Data Structures: Reference Counts Required
Always reference count shared structures. Locking maintains consistency; refcounting ensures lifetime safety.
12. Macros: Inline Functions Preferred
Avoid:
Multi-statement macros without
do { } while(0)Macros that change control flow (
return,goto)Side-effect-laden parameters
Use static inline functions when possible.
13. Kernel Messages: Be Precise
Use pr_info(), dev_err(), etc. No periods at end of messages. Avoid noisy logs; pr_debug() is compiled out by default.
14. Memory Allocation: Favor Safe Forms
Use:
kmalloc(sizeof(*p), ...)oversizeof(type)kcalloc(n, sizeof(...), ...)for zeroed arrays
No need to cast void* return from allocators.
The kernel provides the following general purpose memory allocators:
kmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc(), and
vzalloc(). Please refer to the API documentation for further information
about them. :ref:`Documentation/core-api/memory-allocation.rst
<memory_allocation>`
The preferred form for passing a size of a struct is the following:
.. code-block:: c
p = kmalloc(sizeof(*p), ...);
The alternative form where struct name is spelled out hurts readability and
introduces an opportunity for a bug when the pointer variable type is changed
but the corresponding sizeof that is passed to a memory allocator is not.
Casting the return value which is a void pointer is redundant. The conversion
from void pointer to any other pointer type is guaranteed by the C programming
language.15. The Inline Disease
Don’t abuse inline. GCC does a better job than you.
Rule of thumb: Avoid inlining functions with more than 3 lines of logic.
16. Return Values: Predicate vs Command
Predicates return boolean (
pci_dev_present()→ 0/1)Commands return error codes (
add_work()→ 0/-Exxx)
Helps avoid boolean vs integer bugs.
Functions can return values of many different kinds, and one of the
most common is a value indicating whether the function succeeded or
failed. Such a value can be represented as an error-code integer
(-Exxx = failure, 0 = success) or a ``succeeded`` boolean (0 = failure,
non-zero = success).
Mixing up these two sorts of representations is a fertile source of
difficult-to-find bugs. If the C language included a strong distinction
between integers and booleans then the compiler would find these mistakes
for us... but it doesn't. To help prevent such bugs, always follow this
convention::
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.17. bool: Use With Care
Use bool for clarity, but not in memory-critical structs—its size varies. Prefer bitfields or u8 in performance-sensitive data.
The Linux kernel bool type is an alias for the C99 _Bool type. bool values can
only evaluate to 0 or 1, and implicit or explicit conversion to bool
automatically converts the value to true or false. When using bool types the
!! construction is not needed, which eliminates a class of bugs.
When working with bool values the true and false definitions should be used
instead of 1 and 0.
bool function return types and stack variables are always fine to use whenever
appropriate. Use of bool is encouraged to improve readability and is often a
better option than 'int' for storing boolean values.
Do not use bool if cache line layout or size of the value matters, as its size
and alignment varies based on the compiled architecture. Structures that are
optimized for alignment and size should not use bool.
If a structure has many true/false values, consider consolidating them into a
bitfield with 1 bit members, or using an appropriate fixed width type, such as
u8.
Similarly for function arguments, many true/false values can be consolidated
into a single bitwise 'flags' argument and 'flags' can often be a more
readable alternative if the call-sites have naked true/false constants.
Otherwise limited use of bool in structures and arguments can improve
readability.18. Use Kernel Macros
Use standard macros like:
ARRAY_SIZE(arr) sizeof_field(struct, field)Avoid re-implementing well-tested patterns.
.. code-block:: c
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
Similarly, if you need to calculate the size of some structure member, use
.. code-block:: c
#define sizeof_field(t, f) (sizeof(((t*)0)->f))
19. Editor Modelines: Just Say No
Don’t embed Vim or Emacs config lines in source code. Everyone has their own setup.
20. Inline Assembly: Minimal and Meaningful
Use inline asm only when necessary. Prefer helper functions. Put large asm blocks in .S files.
21. Conditional Compilation: Prefer IS_ENABLED()
Avoid #ifdef clutter in .c files. Use:
if (IS_ENABLED(CONFIG_FOO)) { ... }This lets the compiler validate code paths while compiling out unused ones.
22. Don't Crash the Kernel
Avoid panic(), BUG(), etc. Use WARN_ON_ONCE() when necessary. Remember: panic_on_warn is user-configured—not an excuse to crash.
Bonus: Appendix - References
This style is inspired by the K&R book and practical kernel experience. For deeper insights, read:
The C Programming Language – Kernighan & Ritchie
The Practice of Programming – Kernighan & Pike
Final Thoughts
Coding for the kernel teaches you discipline. The style guide encourages clarity, robustness, and maintainability—qualities that benefit any large C project, kernel or not.
Got questions or want an illustrated version with examples? Drop a comment or message!

