• 链表的遍历


     当我们在链表添加/修改多个节点后,我们最终是要通过查找链表中的某一个节点并对其数据进行操作,我们将逐一分析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)
  • 相关阅读:
    Java 基础
    Java 数据类型
    Spring 拦截器实现事物
    SSH 配置日记
    Hibernate 知识提高
    Jsp、Servlet
    leetcode 97. Interleaving String
    leetcode 750. Number Of Corner Rectangles
    leetcode 748. Shortest Completing Word
    leetcode 746. Min Cost Climbing Stairs
  • 原文地址:https://www.cnblogs.com/watson/p/3593237.html
Copyright © 2020-2023  润新知