Chapter 44: Coding Standards
- Why consistent coding standards matter for a team project
- Naming conventions for functions, variables, types, and macros
- Indentation, spacing, and brace style
- Comment guidelines and documentation expectations
- File organization and header file structure
- How to enforce standards with clang-format and checkpatch
44.1 Why Standards Matter
In a team of five developers building a kernel, code will be read far more often than it is written. Consistent formatting and naming conventions reduce cognitive overhead, prevent bugs, and make code reviews productive. These standards apply to all C and assembly code in the kernel tree.
44.2 Naming Conventions
| Element | Convention | Example |
|---|---|---|
| Functions | snake_case | alloc_page(), uart_send() |
| Global variables | snake_case with descriptive names | kernel_page_table, system_timer |
| Local variables | snake_case, short but clear | i, count, page_addr |
| Types (typedef) | snake_case with _t suffix | uint32_t (standard), page_t, process_t |
| Struct/enum tags | snake_case | struct pcb, enum vm_flags |
| Macros | UPPER_SNAKE_CASE | PAGE_SIZE, MAX_PROCESSES |
| Inline functions | snake_case (same as regular functions) | static inline round_up() |
| File names | snake_case.c / snake_case.h | uart.c, page_alloc.c |
44.3 Formatting
Indentation and Braces
/* Indent: 4 spaces. No tabs. */
/* Braces: K&R style (opening brace on same line). */
void example_function(void) {
if (condition) {
do_something();
} else {
do_other();
}
for (int i = 0; i < count; i++) {
process_item(items[i]);
}
}
/* Always use braces for loops and conditionals, even single lines. */
if (error)
return -1; /* WRONG: no braces */
if (error) {
return -1; /* CORRECT */
}
/* One space after if/for/while, before opening paren. */
if (x) /* CORRECT */
if(x) /* WRONG */
Spacing
/* One space around binary operators. */
int sum = a + b * c;
/* No space between function name and opening paren. */
void *kmalloc(size_t size);
kmalloc(256); /* CORRECT */
kmalloc (256); /* WRONG */
/* Pointer: * goes next to the variable name. Not next to the type. */
int *ptr; /* CORRECT */
int* ptr; /* WRONG */
int * ptr; /* WRONG */
/* One space after commas in function arguments. */
function(a, b, c); /* CORRECT */
function(a,b,c); /* WRONG */
Switch Statements
switch (value) {
case OPTION_A:
handle_a();
break;
case OPTION_B:
handle_b();
/* fallthrough */
case OPTION_C:
handle_c();
break;
default:
handle_default();
break;
}
44.4 Comments
/*
* Block comments for file headers and function
* descriptions. Use /* for multi-line.
*/
int documented_function(void);
/* Single-line comments for implementation details. */
// C++ style comments are also acceptable for short notes. //
Every public function in header files must have a doc comment explaining what it does, its parameters, and return value:
/**
* alloc_page - Allocate a single physical page.
*
* Returns a pointer to the page's physical address (identity-mapped),
* or NULL if no free pages are available.
* The allocated page is zeroed.
*/
void *alloc_page(void);
44.5 Header File Structure
/* kernel/include/timer.h */
#ifndef __TIMER_H__
#define __TIMER_H__
#include <stdint.h>
/* Public API */
void timer_init(void);
uint64_t timer_get_ticks(void);
void timer_sleep(uint64_t ms);
/* Internal (only for timer.c) */
#ifdef __TIMER_INTERNAL__
extern volatile uint64_t system_ticks;
void timer_irq_handler(void);
#endif
#endif /* __TIMER_H__ */
Rules for header files:
- Every header must have a
#ifndefinclude guard - Include only what is needed (no transitive includes)
- Do not define variables in header files
- Keep the public API separate from internal implementation details using
#ifdef
44.6 File Organization
/*
* kernel/mm/page_alloc.c - Physical page allocator
*
* Implements a buddy allocator for physical memory management.
*/
#include "kernel.h"
#include "mm.h"
/* Private defines */
#define MAX_ORDER 10
/* Private structs */
struct free_list {
struct free_list *next;
};
/* Private globals */
static struct free_list page_buckets[MAX_ORDER + 1];
/* Forward declarations */
static void split_page(int order);
/* Public functions */
void *alloc_page(void) { ... }
void free_page(void *page) { ... }
/* Private functions */
static void split_page(int order) { ... }
Structure within a C file:
- File header comment
- Includes
- Defines and macros
- Type definitions and structs
- Global variables
- Forward declarations of static functions
- Public functions
- Private functions
44.7 What Not to Do
/* NEVER: */
goto label; /* No gotos except for cleanup */
extern int global; /* No extern globals in headers */
#define max(a,b) a>b?a:b /* No function-like macros when inline works */
int *p = malloc(100); /* No malloc in kernel; use kmalloc */
void fn() { /* No empty parens in K&R style; use (void) */
; /* No empty statements */
}
44.8 Enforcing Standards
Use clang-format to automatically format code. Our .clang-format file defines the project style:
# .clang-format
BasedOnStyle: LLVM
IndentWidth: 4
UseTab: Never
BreakBeforeBraces: Attach
AllowShortIfStatementsOnASingleLine: false
ColumnLimit: 100
# Format all C source files
clang-format -i kernel/**/*.c kernel/**/*.h
# Run the Linux kernel checkpatch script for additional checks
./scripts/checkpatch.pl -f kernel/mm/page_alloc.c
All code submitted for review must pass clang-format without changes.
44.9 Our Implementation
Our kernel follows these standards throughout. Key conventions to remember:
- Language: C17 with GNU extensions, no C++
- Compiler: aarch64-none-elf-gcc with -Wall -Wextra -Werror
- Formatting: clang-format with the project .clang-format file
- Header guards:
#ifndef __FILENAME_H__ - Error returns: negative errno values (e.g.,
-ENOMEM) - Success returns: 0 for success, positive values for results (like file descriptors)
44.10 Exercises
Exercise 1: Review and Fix
Take a kernel source file and run clang-format on it. Review the diff and understand every change clang-format made.
Exercise 2: Write a checkpatch Rule
Add a custom checkpatch.pl rule that flags any use of // comments (optionally, or flag any goto label).
44.11 Summary
Consistent coding standards make the kernel codebase readable, maintainable, and reviewable. Snake_case naming, K&R braces, 4-space indentation, and avoid tabs are the foundation. Header files use include guards and separate public from private API. Automatic enforcement with clang-format ensures code meets the standard without manual effort.