【Linux】list_for_each_entry用法

参考:

http://blog.sina.com.cn/s/blog_5e99b41e0100rxgf.html

http://hi.baidu.com/shiftedmind/blog/item/1a7c8381e6a67fa56d8119da.html

         在Linux内核源码中,经常要对链表进行操作,其中一个很重要的宏是list_for_each_entry:

意思大体如下:

         假设下面几个结点,则第一个member代表head,list_for_each_entry的作用就是循环遍历每一个pos中的member子项。

list_for_each_entry应用:

         它实际上是一个 for 循环,利用传入的 pos 作为循环变量,从表头 head 开始,逐项向后(next 方向)移动 pos,直至又回head(prefetch() 可以不考虑,用于预取以提高遍历速度 )。 

在程序中的使用如下:

list_for_each_entry(pos , head,member)

{       

………………

      addr =    pos;  //对返回值pos的操作,这样更容易去理解list_for_each_entry,可以把它看作for()循环

………………

}


宏list_for_each_entry的实现:

[cpp]  view plain  copy
  1. /** 
  2.  * list_for_each_entry  -   iterate over list of given type 
  3.  * @pos:    the type * to use as a loop cursor. 
  4.  * @head:   the head for your list. 
  5.  * @member: the name of the list_struct within the struct. 
  6.  */  
  7. #define list_for_each_entry(pos, head, member)              \  
  8.     for (pos = list_entry((head)->next, typeof(*pos), member);   \  
  9.          prefetch(pos->member.next), &pos->member != (head);  \  
  10.          pos = list_entry(pos->member.next, typeof(*pos), member))  

对程序中for循环的三步分析:

(1),pos = list_entry((head)->next, typeof(*pos), member)

         pos相当于循环中返回的循环变量,这里就是返回一个结构体指针。实现过程如下:

函数list_entry():

[cpp]  view plain  copy
  1. /** 
  2.  * list_entry - get the struct for this entry 
  3.  * @ptr:    the &struct list_head pointer. 
  4.  * @type:   the type of the struct this is embedded in. 
  5.  * @member: the name of the list_struct within the struct. 
  6.  */  
  7. #define list_entry(ptr, type, member) \  
  8.     container_of(ptr, type, member)  

跟进:container_of这个函数

         这个不做重点分析,这个函数的做用是:它的作用显而易见,那就是根据一个结构体变量中的一个域成员变量的指针来获取指向整个结构体变量的指针。

[cpp]  view plain  copy
  1. /** 
  2.  * container_of - cast a member of a structure out to the containing structure 
  3.  * @ptr:    the pointer to the member. 
  4.  * @type:   the type of the container struct this is embedded in. 
  5.  * @member: the name of the member within the struct. 
  6.  * 
  7.  */  
  8. #define container_of(ptr, type, member) ({          \  
  9.     const typeof(((type *)0)->member)*__mptr = (ptr);    \  
  10.              (type *)((char *)__mptr - offsetof(type, member)); })  

所以list_entry()的作用为:如上图所示,可以以通过已知的指向member子项的指针,获得整个结构体的指针(地址)

(2),   prefetch(pos->member.next),&pos->member!= (head);  

         prefetch的含义是告诉cpu那些元素有可能马上就要用到,告诉cpu预取一下,这样可以提高速度用于预取以提高遍历速度;

         &pos->member !=(head)  ,这个判断循环条件。

(3),  pos= list_entry(pos->member.next, typeof(*pos), member)) 

         和第(1)实现相似,用于逐项向后(next 方向)移动 pos

  • 8
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
list_for_each_entry_safe是Linux中链表遍历的一个函数,用于遍历一个双向链表,并在遍历过程中安全地删除、插入或替换节点。它的语法如下: ``` list_for_each_entry_safe(pos, n, head, member) { // 执行操作 } ``` 其中,pos和n是指向链表节点的指针,head是链表头指针,member是链表节点中指向下一个节点的指针成员名。这个函数会遍历链表中的所有节点,并在每次遍历时执行操作,直到遍历完整个链表。在执行操作时,可以安全地删除、插入或替换节点,因为list_for_each_entry_safe会在遍历过程中保证节点的正确性。 例如,下面的代码演示了如何使用list_for_each_entry_safe来遍历一个链表,并删除其中的某些节点: ``` struct my_node { int data; struct list_head list; }; struct list_head my_list; // 初始化链表 INIT_LIST_HEAD(&my_list); // 添加节点 struct my_node *node1 = kmalloc(sizeof(struct my_node), GFP_KERNEL); node1->data = 1; list_add_tail(&node1->list, &my_list); struct my_node *node2 = kmalloc(sizeof(struct my_node), GFP_KERNEL); node2->data = 2; list_add_tail(&node2->list, &my_list); struct my_node *node3 = kmalloc(sizeof(struct my_node), GFP_KERNEL); node3->data = 3; list_add_tail(&node3->list, &my_list); // 遍历链表并删除节点 struct my_node *pos, *n; list_for_each_entry_safe(pos, n, &my_list, list) { if (pos->data == 2) { list_del(&pos->list); kfree(pos); } } ``` 在这个例子中,我们首先创建了一个链表,并向其中添加了三个节点。然后使用list_for_each_entry_safe遍历链表,并在每次遍历时判断节点中的数据是否等于2。如果是,则使用list_del删除节点,并释放节点内存。最终,链表中只剩下两个节点。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值