8.Linux内核设计与实现 P77---list_for_each()与list_for_each_safe()的区别

list_for_each()的定义:


  1. /**  
  2.  * list_for_each    -   iterate over a list  
  3.  * @pos:    the &struct list_head to use as a loop counter.  
  4.  * @head:   the head for your list.  
  5.  */  
  6. #define list_for_each(pos, head) \  
  7.     for (pos = (head)->next, prefetch(pos->next); pos != (head); \  
  8.         pos = pos->next, prefetch(pos->next))  

list_for_each_safe()的定义:

  1. /**  
  2.  * list_for_each_safe   -   iterate over a list safe against removal of list entry  
  3.  * @pos:    the &struct list_head to use as a loop counter.  
  4.  * @n:      another &struct list_head to use as temporary storage  
  5.  * @head:   the head for your list.  
  6.  */  
  7. #define list_for_each_safe(pos, n, head) \  
  8.     for (pos = (head)->next, n = pos->next; pos != (head); \  
  9.         pos = n, n = pos->next)  

由上面两个对比来看,list_for_each_safe()函数比list_for_each()多了一个中间变量n

 

当在遍历的过程中需要删除结点时,来看一下会出现什么情况:

list_for_each():list_del(pos)将pos的前后指针指向undefined state,导致kernel panic,另如果list_del_init(pos)将pos前后指针指向自身,导致死循环。

list_for_each_safe():首先将pos的后指针缓存到n,处理一个流程后再赋回pos,避免了这种情况发生。


因此之遍历链表不删除结点时,可以使用list_for_each(),而当由删除结点操作时,则要使用list_for_each_safe()。

其他带safe的处理也是基于这个原因。

 

你可能感兴趣的:(8.Linux内核设计与实现 P77---list_for_each()与list_for_each_safe()的区别 )