博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
链表的遍历
阅读量:6854 次
发布时间:2019-06-26

本文共 11765 字,大约阅读时间需要 39 分钟。

 当我们在链表添加/修改多个节点后,我们最终是要通过查找链表中的某一个节点并对其数据进行操作,我们将逐一分析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

你可能感兴趣的文章
View的setTag()与getTag()方法使用
查看>>
UML中类结构图示例
查看>>
03-hibernate注解-关系映射级别注解-一对一
查看>>
EasyUI combotree的使用
查看>>
C#网络编程二:SOCKET编程
查看>>
【多媒体封装格式详解】--- AAC ADTS格式分析
查看>>
联想IDEAPAD 320C-15笔记本显卡驱动问题
查看>>
ES6简介
查看>>
全国实时天气预警查询
查看>>
c# WebApi之解决跨域问题:Cors
查看>>
UWP FillRowViewPanel
查看>>
目前的.NET(C#)世界里,主流的ORM框架
查看>>
Java 基础知识点
查看>>
Linux--忘记MySQL密码的解决方法和输入mysqld_safe --skip-grant-tables &后无法进入MySQL的解决方法...
查看>>
vimperator
查看>>
(原創) 如何使用boost::array? (C/C++) (template) (boost)
查看>>
Oracle for Windows 相关下载地址
查看>>
电子书下载:Microsoft Silverlight 4 Business Application Development: Beginners Guide
查看>>
arm 裸奔经验
查看>>
.Net下RabbitMQ的使用(2) -- 发送接收消息
查看>>