链表的遍历

 当我们在链表添加/修改多个节点后,我们最终是要通过查找链表中的某一个节点并对其数据进行操作,我们将逐一分析kernel/include/linux/list.h中关于链表遍历的接口。

1,list_entry用于获取struct list_head结构体指针所在结构体变量的首地址。

@ptr:指向我们要求首地址的结构体内的struct list_head成员变量,ptr的类型也为struct list_head。

@type:要求首地址的结构体类型,即struct list_head变量所在的结构体的类型。

@member:要求首地址结构体类型内struct list_head变量的变量名。

/**
 * list_entry - get the struct for this entry
 * @ptr:        the &struct list_head pointer.
 * @type:       the type of the struct this is embedded in.
 * @member:     the name of the list_struct within the struct.
 */
#define list_entry(ptr, type, member) 
        container_of(ptr, type, member)

 list_entry调用了contianer_of宏,container_of宏的定义与分析将在另一篇随笔中讲述。

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

/**
 * container_of - cast a member of a structure out to the containing structure
 * @ptr:        the pointer to the member.
 * @type:       the type of the container struct this is embedded in.
 * @member:     the name of the member within the struct.
 *
 */
#define container_of(ptr, type, member) ({                      
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    
        (type *)( (char *)__mptr - offsetof(type,member) );})

  

2,list_first_entry用于获取链表中第一个节点所在结构体的首地址。

@ptr:链表头节点;

@type:链表节点struct list_head变量所在结构体的类型;

@member:链表节点在所求首地址结构体内的成员变量名;

/**
 * list_first_entry - get the first element from a list
 * @ptr:        the list head to take the element from.
 * @type:       the type of the struct this is embedded in.
 * @member:     the name of the list_struct within the struct.
 *
 * Note, that list is expected to be not empty.
 */
#define list_first_entry(ptr, type, member) 
        list_entry((ptr)->next, type, member)

3,list_for_each遍历一个链表。

@pos:struct list_head类型的指针,用于指向我们遍历的链表节点;

@head:我们要遍历链表的头节点;

/**
 * list_for_each        -       iterate over a list
 * @pos:        the &struct list_head to use as a loop cursor.
 * @head:       the head for your list.
 */     
#define list_for_each(pos, head)       
        for (pos = (head)->next; pos != (head); pos = pos->next)

4,__list_for_each与list_for_each完全一样,遍历一个链表,同时也不做预取。

/**
 * __list_for_each      -       iterate over a list
 * @pos:        the &struct list_head to use as a loop cursor.
 * @head:       the head for your list.
 *
 * This variant doesn't differ from list_for_each() any more.
 * We don't do prefetching in either case.
 */
#define __list_for_each(pos, head) 
        for (pos = (head)->next; pos != (head); pos = pos->next)

5,__list_for_each_prev用于从后向前反向遍历。

/**
 * list_for_each_prev   -       iterate over a list backwards
 * @pos:        the &struct list_head to use as a loop cursor.
 * @head:       the head for your list.
 */
#define list_for_each_prev(pos, head) 
        for (pos = (head)->prev; pos != (head); pos = pos->prev)

6,list_for_each_safe安全的遍历一个链表,其机制是我们多传入一个struct list_head的指针n,用于指向pos的下一个节点,以保证我们在删除pos指向的节点时,仍能继续遍历链表的剩余节点。

/**
 * list_for_each_safe - iterate over a list safe against removal of list entry
 * @pos:        the &struct list_head to use as a loop cursor.
 * @n:          another &struct list_head to use as temporary storage
 * @head:       the head for your list.
 */
#define list_for_each_safe(pos, n, head) 
        for (pos = (head)->next, n = pos->next; pos != (head); 
                pos = n, n = pos->next)

7,list_for_each_prev_safe反向遍历,安全查找。

/**
 * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
 * @pos:        the &struct list_head to use as a loop cursor.
 * @n:          another &struct list_head to use as temporary storage
 * @head:       the head for your list.
 */
#define list_for_each_prev_safe(pos, n, head) 
        for (pos = (head)->prev, n = pos->prev; 
             pos != (head); 
             pos = n, n = pos->prev)

8,3、4、5、6、7在遍历链表时返回的是struct list_head指针的地址。当我们使用struct list_head型变量将一个节点挂到一个链表时,我们不是为了仅仅操纵这个光凸凸的节点,而是将struct list_head变量放到一个结构体内,根据对链表上struct list_head的遍历来得出strcut list_head所在结构体的首地址,list_for_each_entry正是为了完成这一功能而实现。

/**
 * list_for_each_entry  -       iterate over list of given type
 * @pos:        the type * to use as a loop cursor.
 * @head:       the head for your list.
 * @member:     the name of the list_struct within the struct.
 */
#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))

我们将所求结构体类型的指针变量pos、链表的头head和所求结构体内struct list_head的变量名member传到list_for_each_entry之后, list_entry的第一个参数用head->next指向下一个节点,此节点的地址也就是在所属结构体内的struct list_head成员变量的地址,第二个参数用typeof(*pos)求得pos的结构体类型,第三个参数为所求结构体内struct list_head的变量名。

9,list_for_each_entry_reverse反向遍历链表并返回链表节点所在的结构体的首地址

/**
 * list_for_each_entry_reverse - iterate backwards over list of given type.
 * @pos:        the type * to use as a loop cursor.
 * @head:       the head for your list.
 * @member:     the name of the list_struct within the struct.
 */
#define list_for_each_entry_reverse(pos, head, member)                  
        for (pos = list_entry((head)->prev, typeof(*pos), member);      
             &pos->member != (head);    
             pos = list_entry(pos->member.prev, typeof(*pos), member))


10,list_prepare_entry用于准备一个结构体的首地址,用在list_for_each_entry_contine()中。

/**
 * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
 * @pos:        the type * to use as a start point
 * @head:       the head of the list
 * @member:     the name of the list_struct within the struct.
 *
 * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
 */
#define list_prepare_entry(pos, head, member) 
        ((pos) ? : list_entry(head, typeof(*pos), member))

11,list_for_each_entry_contine从当前pos的下一个节点开始继续遍历剩余的链表,不包括pos。

如果我们将pos、head、member传入list_for_each_entry,此宏将会从链表的头节点开始遍历。

/**
 * list_for_each_entry_continue - continue iteration over list of given type
 * @pos:        the type * to use as a loop cursor.
 * @head:       the head for your list.
 * @member:     the name of the list_struct within the struct.
 *
 * Continue to iterate over list of given type, continuing after
 * the current position.
 */
#define list_for_each_entry_continue(pos, head, member)                 
        for (pos = list_entry(pos->member.next, typeof(*pos), member);  
             &pos->member != (head);    
             pos = list_entry(pos->member.next, typeof(*pos), member))

12,list_for_each_entry_contine_reverse从当前的pos的前一个节点开始继续反向遍历剩余的链表,不包括pos。

/**
 * list_for_each_entry_continue_reverse - iterate backwards from the given point
 * @pos:        the type * to use as a loop cursor.
 * @head:       the head for your list.
 * @member:     the name of the list_struct within the struct.
 *
 * Start to iterate over list of given type backwards, continuing after
 * the current position.
 */
#define list_for_each_entry_continue_reverse(pos, head, member)         
        for (pos = list_entry(pos->member.prev, typeof(*pos), member);  
             &pos->member != (head);    
             pos = list_entry(pos->member.prev, typeof(*pos), member))

13,list_for_each_entry_from从pos开始遍历剩余的链表。

/**
 * list_for_each_entry_from - iterate over list of given type from the current point
 * @pos:        the type * to use as a loop cursor.
 * @head:       the head for your list.
 * @member:     the name of the list_struct within the struct.
 *
 * Iterate over list of given type, continuing from current position.
 */
#define list_for_each_entry_from(pos, head, member)                     
        for (; &pos->member != (head);  
             pos = list_entry(pos->member.next, typeof(*pos), member))

14,list_for_each_entry_safe遍历链表,返回type类型的结构体的首地址,并防止因删除链表节点而导致的遍历出错。

/**
 * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
 * @pos:        the type * to use as a loop cursor.
 * @n:          another type * to use as temporary storage
 * @head:       the head for your list.
 * @member:     the name of the list_struct within the struct.
 */
#define list_for_each_entry_safe(pos, n, head, member)                  
        for (pos = list_entry((head)->next, typeof(*pos), member),      
                n = list_entry(pos->member.next, typeof(*pos), member); 
             &pos->member != (head);                                    
             pos = n, n = list_entry(n->member.next, typeof(*n), member))

15,list_for_each_entry_safe_continue从pos节点的下一个节点开始遍历剩余的链表,并防止因删除链表节点而导致的遍历出错。

/**
 * list_for_each_entry_safe_continue - continue list iteration safe against removal
 * @pos:        the type * to use as a loop cursor.
 * @n:          another type * to use as temporary storage
 * @head:       the head for your list.
 * @member:     the name of the list_struct within the struct.
 *
 * Iterate over list of given type, continuing after current point,
 * safe against removal of list entry.
 */
#define list_for_each_entry_safe_continue(pos, n, head, member)                 
        for (pos = list_entry(pos->member.next, typeof(*pos), member),          
                n = list_entry(pos->member.next, typeof(*pos), member);         
             &pos->member != (head);                                            
             pos = n, n = list_entry(n->member.next, typeof(*n), member))

16,list_for_each_entry_safe_from从pos节点开始继续遍历剩余的链表,并防止因删除链表节点而导致的遍历出错。其与list_for_each_entry_safe_contine的不同在于在第一次遍历时,pos没有指向它的下一个节点,而是从pos开始遍历。

/**
 * list_for_each_entry_safe_from - iterate over list from current point safe against removal
 * @pos:        the type * to use as a loop cursor.
 * @n:          another type * to use as temporary storage
 * @head:       the head for your list.
 * @member:     the name of the list_struct within the struct.
 *
 * Iterate over list of given type from current point, safe against
 * removal of list entry.
 */
#define list_for_each_entry_safe_from(pos, n, head, member)                     
        for (n = list_entry(pos->member.next, typeof(*pos), member);            
             &pos->member != (head);                                            
             pos = n, n = list_entry(n->member.next, typeof(*n), member))

17,list_for_each_entry_safe_reverse从pos的前一个节点开始反向遍历一个链表,并防止因删除链表节点而导致的遍历出错。

/**
 * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
 * @pos:        the type * to use as a loop cursor.
 * @n:          another type * to use as temporary storage
 * @head:       the head for your list.
 * @member:     the name of the list_struct within the struct.
 *
 * Iterate backwards over list of given type, safe against removal
 * of list entry.
 */
#define list_for_each_entry_safe_reverse(pos, n, head, member)          
        for (pos = list_entry((head)->prev, typeof(*pos), member),      
                n = list_entry(pos->member.prev, typeof(*pos), member); 
             &pos->member != (head);                                    
             pos = n, n = list_entry(n->member.prev, typeof(*n), member))

18,list_safe_reset_next返回当前pos节点的下一个节点的type结构体首地址。

/**
 * list_safe_reset_next - reset a stale list_for_each_entry_safe loop
 * @pos:        the loop cursor used in the list_for_each_entry_safe loop
 * @n:          temporary storage used in list_for_each_entry_safe
 * @member:     the name of the list_struct within the struct.
 *
 * list_safe_reset_next is not safe to use in general if the list may be
 * modified concurrently (eg. the lock is dropped in the loop body). An
 * exception to this is if the cursor element (pos) is pinned in the list,
 * and list_safe_reset_next is called after re-taking the lock and before
 * completing the current iteration of the loop body.
 */
#define list_safe_reset_next(pos, n, member)                            
        n = list_entry(pos->member.next, typeof(*pos), member)
原文地址:https://www.cnblogs.com/watson/p/3593237.html