Saturday 9 August 2014

Linux: Managing double linked list in the Linux kerne

Linux: Managing double linked list in the Linux kernel

# LIST_HEAD(list_name): Creat an new double linked list.  
 
$ list_add(n,p): Inserts an element pointed to by n right after the specified element pointed to by p. To insert n at the beginning of the list, set p to the address of the list head.

 $ list_add_tail(n,p): Inserts an element pointed to by n right before the specified element pointed to by p. To insert n at the end of the list, set p to the address of the list head.

 $ list_del(p): Deletes an element pointed to by p

 $ list_empty(p): Checks if the list specified by the address p of its head is empty.

 $ list_entry(p,t,m): Returns the address of the data structure of type t in which the list_head field that has the name m and the address p is included.
                    #define list_entry(ptr, type, member)                                   \
                     ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

 $ list_for_each(p,h): Scans the elements of the list specified by the address h of the head; in each iteration, a pointer to the list_head structure of the list element is returned in p.
                  #define list_for_each(pos, head)                                        \
                   for (pos = (head)->next; pos != (head); pos = pos->next)

$ list_for_each_entry(p,h,m): Returns the address of the data structure embedding the list_head structure rather than the address of the list_head structure itself.

    #define list_for_each_entry(pos, head, member)                          \
       for (pos = list_entry((head)->next, typeof(*pos), member);      \
             &pos->member != (head);                                    \
             pos = list_entry(pos->member.next, typeof(*pos), member))



Why this is ((type*)0)->member, not (type*)->member????

Simply because (type*)->member would be invalid syntax, thus typeof would be impossible. So it uses a NULL pointer, which it doesn't dereference anyway - it's used just so typeof can refer to the member.
How this works:

  • The typeof trick is used to declare a pointer of the type of the member. This pointer gets is initialized with the pointer passed by the caller
  • The offset of that member in the struct is subtracted from the address of the pointer: this yields the address of the containing object

No comments:

Post a Comment