1. 程式人生 > >8.Linux核心設計與實現 P77---list_for_each()與list_for_each_safe()的區別 (轉)

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的處理也是基於這個原因。