1. list_for_each
1. list_for_each prototype
# Define list_for_each (pos, head )\
For (pos = (head)-> next, prefetch (pos-> next); pos! = (Head );\
Pos = pos-> next, prefetch (pos-> next ))
It is actually a for loop. It uses the input pos as the cyclic variable, starting from the header, moving the pos one by one (next) until it returns to the head (prefetch () this parameter can be left blank and used for prefetch to increase the traversal speed ).
Note: This macro must place list_head In the first member of the data structure. At this point, its address is the address of the structure variable.
2. usage (take the sub-process accessing the current process as an example ):
Struct list_head {
Struct list_head * next, * prev;
};
The following definitions are available in struct task_struct:
Struct list_head children;
So
Struct task_struct * task;
Struct list_head * list;
List_for_each (list, & current-> chilidren ){
Task = list_entry (list, struct task_struct, sibling);/* The task points to the current subprocess */
}
The list_entry () function is used ():
The function is used in figure 1 to obtain the pointer (address) of the entire struct through a known pointer to the member subitem)
# Define list_entry (ptr, type, member )\
Container_of (ptr, type, member)
Ii. list_for_each_entry:
In the Linux kernel source code, you often need to operate the linked list. One of the most important macros is list_for_each_entry:
The meaning is roughly as follows:
Assuming there are only two nodes, the first member represents the head,
List_for_each_entry cyclically traverses the member subitem in each pos.
Figure 1:
Pos:
_______________________
|
|
| ...... |
|
|
| Member: | _________ |__> member |
| {|
| * Prev; |
| * Next; -- | ---------- | * next ;-------------
|}| |
|-^ ---- | ____________ |
|
|
| _________________________________________________ |
Macro list_for_each_entry:
# Define list_for_each_entry (pos, head, member )\
For (pos = list_entry (head)-> next, typeof (* pos), member );\
Prefetch (pos-> member. next), & pos-> member! = (Head );\
Pos = list_entry (pos-> member. next, typeof (* pos), member ))
List_entry (head)-> next, typeof (* pos), member) returns (head)-> next after the position of the physical pointer minus offsetof () bytes of data, physical address of the parent variable pos. the type of the parent variable is automatically returned by typeof (* pos) during compilation.
Therefore, list_for_each_entry traverses the childs struct of Type typeof (* pos) mounted under the head. Of course, each child struct contains similar two-way linked list list_head items such as struct list_head node, in this way, the cyclic pos will point to each child on the two-way linked list in turn. (member is the variable name defined in the child type)
The list_entry () function is used ():
The function is used in figure 1 to obtain the pointer (address) of the entire struct through a known pointer to the member subitem)
# Define list_entry (ptr, type, member )\
Container_of (ptr, type, member)
And function prefetch:
# Define prefetch (x) _ builtin_prefetch (x)
Builtin_prefetch is used:
Prefetch means to tell the cpu elements that may be used immediately and tell the cpu to prefetch, which can increase the speed.
The container_of () function is used here ():
493 # define container_of (ptr, type, member )({\
494 const typeof (type *) 0)-> member) * _ mptr = (ptr );\
495 (type *) (char *) _ mptr-offsetof (type, member ));})
Here, the offsetof () function is used:
Source code found on lxr:
# Define offset_of (type, memb )\
47 (unsigned long) (& (type *) 0)-> memb ))
Offsetof (TYPE, MEMBER)
This macro is defined in Linux kernel code (version 2.6.22) as follows:
# Define offsetof (TYPE, MEMBER) (size_t) & (TYPE *) 0)-> MEMBER );
Analysis:
(TYPE *) 0, force convert 0 to TYPE pointer, note p = (TYPE *) 0, p is the pointer to TYPE, its value is 0. Then p-> MEMBER is the element of MEMBER, and & (p-> MEMBER) is the address of MENBER, and the base address is 0, which is cleverly converted to the offset in TYPE. It is OK to forcibly convert the result to the size_t type. size_t is actually an int.
Typedef _ kernel_size_t size_t;
Typedef unsigned int _ kernel_size_t;
It can be seen that the macro is used to find the offset of MEMBER in TYPE.