2

Macros in Linux kernel

I have just entered in the wonderful world of Linux kernel development.To begin with, I decided to look at the link list implementation in linux kernel.While going through the link list implementation in linux kernel,I came across few interesting macros which seems really intriguing,so I decided to dive deeper in their implementation details. Two among them which we will be discussing today are :

  • offsetof
  • container_of

I will be referring the following structure in examples to explain things further for these two macros.

offsetof 
Syntax : offsetof(STRUCT_TYPE, MEMBER)

This macro will return a byte offset of a MEMBER(field in STRUCT_TYPE) from the beginning of the structure (of type STRUCT_TYPE).The return value is of type size_t.
It works on the principle of zero pointer trick and is defined as follows in linux kernel code:

The above expression works successfully without crash because compiler does not try to derefer the actual pointer value(i.e. 0). Rather it will evaluate the offset address of the member from the starting address of the structure.In this particular case, structure’s base address is 0 and the address returned is actual byte offset position of the member from the starting address of structure.

Example:

Following is a code snippet to fetch the offset address of the “var_char” data member of the struct “my_struct” which is defined above. Since var_char is the second member of my_struct defined after int so the offsetof macro will return the offset equals to the size of the int which is 4 on my machine.

 

Container_of
Syntax : container_of(ptr, type, member)

The basic building block of the container_of macro is “typeof()” function. “typeof()” is a non-standard GNU C extension. It takes one argument and return its respective type.  E.g.
typeof (*x) y;
This declares variable y with the type of what x points to.Please refer gcc documentation for further details.

->Statements in Expression
A compound statement enclosed in parentheses may appear as an expression in GNU C.A compound statement is a sequence of statements surrounded by braces, in this construct, parentheses go around the braces.The last thing in the compound statement should be an expression followed by a semicolon; the value of last sub-expression serves as the value of the entire compound statement.For example:
int var = ({10; 15;}) + 2; ———————-> ({10;15;}) is the expression whose value is 15
printf(“%d\n”, var); ———————-> prints var as 17.

Lets look at the implementation of container_of macro in linux kernel

The above expression yields the starting address of the structure which contain element member and the ptr contains the address of member.

If you look more closely at the definition of macro after learning the above building block, you will find it easy to understand. The first line of macro for type checking purposes .It declares the pointer __mptr of type (((type *)0)->member) and stores the provided ptr value in __mptr. In second line of macro definition, it subtracts the offset of the structure’s member from its address yielding the address of
the container structure. That’s it! Yes that’s how the container address is calculated and returned.

As you can see in the following example,  container_of macro can be used to extract the address of the original structure pointer from its given member pointer. For e.g. lets assume that in some legacy code, you can only have an access to the pointer of data member of some given structure, i.e. lets assume we only have the pointer to the var_char and we want to access the pointer of the my_struct instance i.e. my_var in following example, then we can use container_of macro to fetch the pointer of the instance my_var.

Container_of and offsetof macro have practical usage at different places in kernel code implementation. I will share another post to explain the usage and the need of these macros. Till then keep surfing 🙂

Also, to know more about these macros , you can search these over on the link provided to see their actual implementation in linux code : http://lxr.free-electrons.com/ident

Share Button

Prateek Gupta

2 Comments

  1. couldn’t really understand the use of first line of code in container_of macro. How does it help in type checking?

    Also worth noting is that going purely by ANSI C standard, these macros may not work on all systems because ANSI standard doesn’t mandate that all the members of a structure needs to be saved in contiguous memory locations or the memory layout of all structure variables will be same.

  2. Couldn’t understand the use of first line in container_of macro. How does it help in type checking?

    Also, note that ANSI C standard doesn’t mandate the all variables of structures should have similar memory layout so a compiler may be ANSI compliant and yet these macros may not work correctly. Thats why these are not part of C standard.

Leave a Reply

Your email address will not be published.