Understanding the container_of Macro in Linux Kernel Development
The container_of macro, defined in kernel.h, serves a crucial role in Linux kernel programming by enabling retrieval of a structure's address from its member's address:
/**
* container_of - Get the container structure from a member pointer
* @ptr: Pointer to the structure member
* @type: Type of the containing structure
* @member: Name of the member within the structure
*/
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
Key components in this implementation:
typeof: A GCC extension that determines a variable's type at compile timeoffsetof: Defined in stddef.h, calculates the byte offset of a member within its sturcture
#define offsetof(STRUCT_TYPE, MEMBER) ((size_t) &((STRUCT_TYPE *)0)->MEMBER)
The offsetof macro works by treating address 0 as the base of the structure, then taking the address of the specified member. This yields the member's byte offset from the structure's start.
Breaking down container_of:
-
The first line creates a type-safe pointer to the member:
const typeof( ((type *)0)->member ) *__mptr = (ptr);This ensures type safety by deriving the member's type through:
- Casting 0 to a pointer of the container type
- Accessing the member
- Using
typeofto get the member's type
-
The second line calculates the container's address:
(type *)( (char *)__mptr - offsetof(type,member) );This converts the member pointer to a byte pointer, subtracts the member's offset, and casts the result back to the container type.