Note: The Code referenced in this article comes from LXR, And the analyzed kernel version is v2.6.31.
The Linux kernel Implements similar operations on different types of cyclic linked lists by defining list_head and a group of operations on list_head. This avoids repeated operation functions for cyclic linked lists of different data types, the Code is fully used and is a very effective programming method.
List_head definition:
Reference content is as follows: Struct list_head { Struct list_head * next, * prev; }; |
Next let's look at the circular linked list (1) of any data structure. each node in the linked list adds a list_head type variable, and other variables of the node are arbitrary. (Note: The position pointed to by each pointer is not the starting position of the node data, but the starting address of the list_head type variable .)
Figure 1
In this way, all nodes are connected through list_head variables. How can we get a pointer of a node type in the middle from the list_head type? Let's look at this operation: list_entry (p, t, m), where t is the node type of the linked list, m is the variable name of the list_head type in the node, p is the pointer to the variable. This operation is used to obtain the pointer to the linked list node from the list_head pointer.
Reference content is as follows: # Define list_entry (ptr, type, member )\ Container_of (ptr, type, member)
# Define container_of (ptr, type, member )({\ Const typeof (type *) 0)-> member) * _ mptr = (ptr); \/* _ mptr and ptr type values are the same, is a copy of ptr */ (Type *) (char *) _ mptr-offsetof (type, member);})/* address minus offset (in bytes */
# Define offsetof (TYPE, MEMBER) (size_t) & (TYPE *) 0)-> MEMBER)/* calculates the offset of the variable in the structure (in bytes) */ |