Common Kernel API and Macros

The kernel provides many helper macros and functions. Knowing these will make your code cleaner and more idiomatic.

Container Of

Get the parent structure from a member pointer:

#include <linux/container_of.h>

struct my_device {
        int id;
        struct cdev cdev;  /* Embedded cdev */
        char name[32];
};

/* In a cdev callback, we get a pointer to cdev.
 * container_of gives us the parent my_device. */
static int my_open(struct inode *inode, struct file *file)
{
        struct cdev *cdev = inode->i_cdev;
        struct my_device *dev = container_of(cdev, struct my_device, cdev);

        pr_info("Opening device %s (id=%d)\n", dev->name, dev->id);
        file->private_data = dev;
        return 0;
}

How It Works

container_of(ptr, type, member)

/* Equivalent to: */
(type *)((char *)(ptr) - offsetof(type, member))

Array Size

Get the number of elements in a static array:

#include <linux/array_size.h>

static const char *names[] = { "foo", "bar", "baz" };

for (i = 0; i < ARRAY_SIZE(names); i++)
        pr_info("Name: %s\n", names[i]);

Only works with actual arrays, not pointers! ARRAY_SIZE(pointer) gives wrong results.

Bit Operations

#include <linux/bits.h>

/* Create a bitmask */
BIT(n)        /* 1 << n */
BIT_ULL(n)    /* 1ULL << n (64-bit) */

/* Mask of bits 0 to n-1 */
GENMASK(high, low)
GENMASK_ULL(high, low)

/* Examples */
#define STATUS_READY   BIT(0)    /* 0x01 */
#define STATUS_ERROR   BIT(1)    /* 0x02 */
#define STATUS_BUSY    BIT(2)    /* 0x04 */

#define DATA_MASK      GENMASK(7, 0)     /* 0xFF */
#define ADDR_MASK      GENMASK(31, 12)   /* 0xFFFFF000 */

Bitfield Extraction

#include <linux/bitfield.h>

#define FIELD_A  GENMASK(7, 0)
#define FIELD_B  GENMASK(15, 8)

u32 reg = readl(base + REG_OFFSET);

/* Extract field values */
u8 a = FIELD_GET(FIELD_A, reg);
u8 b = FIELD_GET(FIELD_B, reg);

/* Prepare field values */
reg = FIELD_PREP(FIELD_A, 0x12) | FIELD_PREP(FIELD_B, 0x34);
writel(reg, base + REG_OFFSET);

Min and Max

#include <linux/minmax.h>

/* Type-safe min/max */
int a = 5, b = 10;
int smaller = min(a, b);  /* 5 */
int larger = max(a, b);   /* 10 */

/* Clamping to a range */
int val = clamp(x, min_val, max_val);

/* With explicit type */
u32 result = min_t(u32, value1, value2);

/* Three-way min/max */
int smallest = min3(a, b, c);

Alignment

#include <linux/align.h>

/* Round up to alignment */
ALIGN(x, a)

/* Round down to alignment */
ALIGN_DOWN(x, a)

/* Check if aligned */
IS_ALIGNED(x, a)

/* Examples */
size_t aligned = ALIGN(17, 8);     /* 24 */
size_t down = ALIGN_DOWN(17, 8);   /* 16 */
bool ok = IS_ALIGNED(16, 8);       /* true */

Likely and Unlikely

Branch prediction hints:

#include <linux/compiler.h>

/* Tell compiler this branch is usually taken */
if (likely(condition)) {
        /* Common case */
}

/* Tell compiler this branch is rarely taken */
if (unlikely(error)) {
        /* Error handling */
}

Use sparingly - only when you know the branch behavior and it’s performance-critical.

String Functions

The kernel has its own string functions (not libc):

#include <linux/string.h>

/* Copying */
strscpy(dst, src, size);        /* Safe strcpy */
strscpy_pad(dst, src, size);    /* Pad with zeros */

/* Comparison */
int cmp = strcmp(s1, s2);
int cmp = strncmp(s1, s2, n);
int cmp = strcasecmp(s1, s2);   /* Case-insensitive */

/* Searching */
char *p = strstr(haystack, needle);
char *p = strchr(str, 'c');

/* Length */
size_t len = strlen(str);
size_t len = strnlen(str, max);

/* Memory operations */
memset(ptr, 0, size);
memcpy(dst, src, size);
memmove(dst, src, size);        /* Handles overlap */
int cmp = memcmp(p1, p2, size);

Never use strcpy() or strcat() in kernel code. Use strscpy() instead.

Memory Allocation

#include <linux/slab.h>

/* Basic allocation */
ptr = kmalloc(size, GFP_KERNEL);
ptr = kzalloc(size, GFP_KERNEL);    /* Zero-initialized */

/* Array allocation */
ptr = kmalloc_array(n, element_size, GFP_KERNEL);
ptr = kcalloc(n, element_size, GFP_KERNEL);  /* Zeroed */

/* Freeing */
kfree(ptr);

/* String duplication */
new_str = kstrdup(str, GFP_KERNEL);
new_str = kstrndup(str, max_len, GFP_KERNEL);

Printf-like Functions

#include <linux/kernel.h>

/* Kernel logging */
pr_info("Message: %d\n", value);
pr_err("Error: %s\n", msg);
pr_debug("Debug: %p\n", ptr);   /* Only if DEBUG defined */

/* Device-aware logging */
dev_info(dev, "Device ready\n");
dev_err(dev, "Error: %d\n", ret);
dev_dbg(dev, "Register: 0x%08x\n", reg);

/* Format to buffer */
int len = snprintf(buf, size, "Value: %d", val);
int len = scnprintf(buf, size, "Value: %d", val);  /* Returns chars written, not what would be */

Kernel Printf Specifiers

Specifier Meaning
%d, %i Signed decimal
%u Unsigned decimal
%x, %X Hexadecimal
%08x Hex with leading zeros
%p Pointer (hashed for security)
%px Raw pointer (debug only)
%pK Pointer (kernel restriction aware)
%pS Symbol name from pointer
%pF Function name from pointer
%*ph Hex dump of buffer
%pI4 IPv4 address
%pI6 IPv6 address
%pM MAC address
%pUb UUID
/* Examples */
pr_info("Pointer: %p\n", ptr);         /* Hashed address */
pr_info("Function: %pS\n", func_ptr);  /* "my_function+0x10" */
pr_info("MAC: %pM\n", mac_addr);       /* "00:11:22:33:44:55" */
pr_info("Hex: %*ph\n", 16, buffer);    /* "01 02 03 04..." */

Time and Delays

#include <linux/delay.h>

/* Busy-wait delays (use sparingly) */
udelay(10);       /* Microseconds */
mdelay(1);        /* Milliseconds (avoid if possible) */

/* Sleeping delays (process context only) */
usleep_range(min_us, max_us);  /* Preferred for us delays */
msleep(10);                    /* Milliseconds */
ssleep(1);                     /* Seconds */
#include <linux/jiffies.h>

/* Timeout values */
unsigned long timeout = jiffies + msecs_to_jiffies(100);

/* Check if timeout expired */
if (time_after(jiffies, timeout))
        return -ETIMEDOUT;

List Operations

#include <linux/list.h>

struct my_item {
        int value;
        struct list_head list;  /* Embed list node */
};

/* Initialize list head */
LIST_HEAD(my_list);
/* Or dynamically: */
struct list_head my_list;
INIT_LIST_HEAD(&my_list);

/* Add items */
list_add(&item->list, &my_list);       /* Add at head */
list_add_tail(&item->list, &my_list);  /* Add at tail */

/* Remove items */
list_del(&item->list);

/* Iterate */
struct my_item *item;
list_for_each_entry(item, &my_list, list) {
        pr_info("Value: %d\n", item->value);
}

/* Safe iteration (allows removal) */
struct my_item *tmp;
list_for_each_entry_safe(item, tmp, &my_list, list) {
        list_del(&item->list);
        kfree(item);
}

Mutex and Spinlock Helpers

#include <linux/mutex.h>
#include <linux/spinlock.h>

/* Static initialization */
DEFINE_MUTEX(my_mutex);
DEFINE_SPINLOCK(my_lock);

/* Dynamic initialization */
struct mutex lock;
mutex_init(&lock);

struct spinlock lock;
spin_lock_init(&lock);

Summary

Macro/Function Purpose
container_of Get parent structure from member
ARRAY_SIZE Array element count
BIT(n) Create bitmask
GENMASK Create bit range mask
FIELD_GET/PREP Extract/prepare bitfields
min/max/clamp Safe comparisons
ALIGN Memory alignment
likely/unlikely Branch hints
strscpy Safe string copy
kzalloc Allocate zeroed memory
pr_* / dev_* Kernel logging
LIST_HEAD Linked list operations

Next Steps

Continue to kernel data structures for an in-depth look at linked lists, hash tables, and trees.


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.