內核鏈表的使用


<---百草枯--->

qq--916923477--maooam

內核鏈表

1、內核鏈表是一個雙向循環的鏈表,它的結構是:struct list_head list;它的每一個節點都與普通的鏈表的節點完全不一樣,它是由一個大的結構體和里面有一個小的結構體組成,即:

 

  

 

其中一個小的結構體list為prev和next,而大結構體是整一個節點的內容。

先定義一下在下面要用到的變量:

struct kool_list { int to; struct list_head list; int from; };
 
struct kool_list *tmp; struct list_head *pos, *q; unsigned int i;
struct kool_list mylist;

 

2、內核鏈表的函數:

2.1初始化的函數:

INIT_LIST_HEAD (&mylist.list); /*初始化鏈表頭 */

 

2.2在內核鏈表中插入節點

tmp = (struct kool_list *) malloc (sizeof (struct kool_list));
 
/* 或者INIT_LIST_HEAD(&tmp->list); */ printf ("enter to and from:"); scanf ("%d %d", &tmp->to, &tmp->from);
 
list_add (&(tmp->list), &(mylist.list)); /* 也可以用list_add_tail() 在表尾增加元素 */

 

2.3遍歷內核鏈表

list_for_each (pos, &mylist.list) {
/* 在這里 pos->next 指向next 節點, pos->prev指向前一個節點.這里的節點是     struct kool_list類型. 但是,我們需要訪問節點本身,
    而不是節點中的list字段,宏list_entry()正是為此目的。 */
tmp = list_entry (pos, struct kool_list, list);
printf ("to= %d from= %d\n", tmp->to, tmp->from);

 

2.4刪除某個節點

/*現在,我們可以釋放 kool_list節點了.我們本可以調用 list_del()刪除節點元素,
  * 但為了避免遍歷鏈表的過程中刪除元素出錯,因此調用另一個更加安全的宏 list_for_each_safe(),
  * 具體原因見后面的分析*/
printf ("deleting the list using list_for_each_safe()\n"); list_for_each_safe (pos, q, &mylist.list) {   tmp = list_entry (pos, struct kool_list, list);   printf ("freeing item to= %d from= %d\n", tmp->to, tmp->from);   list_del (pos);   free (tmp);
}

 

3、實例代碼:

#include <stdio.h> #include <stdlib.h>
#include "list.h"
struct kool_list { int to; struct list_head list; int from; };
int main (int argc, char **argv) {
struct kool_list *tmp; struct list_head *pos, *q; unsigned int i;
struct kool_list mylist; INIT_LIST_HEAD (&mylist.list); /*初始化鏈表頭 */
/* 給mylist增加元素 */ for (i = 5; i != 0; --i) {   tmp = (struct kool_list *) malloc (sizeof (struct kool_list));
  /* 或者INIT_LIST_HEAD(&tmp->list); */   printf ("enter to and from:");   scanf ("%d %d", &tmp->to, &tmp->from);
  list_add (&(tmp->list), &(mylist.list));   /* 也可以用list_add_tail() 在表尾增加元素 */ } printf ("\n");
printf ("traversing the list using list_for_each()\n"); list_for_each (pos, &mylist.list) {
  /* 在這里 pos->next 指向next 節點, pos->prev指向前一個節點.這里的節點是      struct kool_list類型. 但是,我們需要訪問節點本身,
     而不是節點中的list字段,宏list_entry()正是為此目的。 */
  tmp = list_entry (pos, struct kool_list, list);
  printf ("to= %d from= %d\n", tmp->to, tmp->from);
} printf ("\n"); /* 因為這是循環鏈表,也可以以相反的順序遍歷它,   *為此,只需要用'list_for_each_prev'代替'list_for_each',
  * 也可以調用list_for_each_entry() 對給定類型的節點進行遍歷。   * 例如:   */ printf ("traversing the list using list_for_each_entry()\n"); list_for_each_entry (tmp, &mylist.list, list)   printf ("to= %d from= %d\n", tmp->to, tmp->from); printf ("\n");
/*現在,我們可以釋放 kool_list節點了.我們本可以調用 list_del()刪除節點元素,
  * 但為了避免遍歷鏈表的過程中刪除元素出錯,因此調用另一個更加安全的宏 list_for_each_safe(),
  * 具體原因見后面的分析*/
printf ("deleting the list using list_for_each_safe()\n"); list_for_each_safe (pos, q, &mylist.list) {   tmp = list_entry (pos, struct kool_list, list);   printf ("freeing item to= %d from= %d\n", tmp->to, tmp->from);   list_del (pos);   free (tmp); }
return 0; }

4、附加:

當鏈表又被刪除節點(list_del()函數調用)后,遍歷鏈表的操作只能用使用list_for_each_safe(p, n, head) 和list_for_each_entry_safe(p,n head, list),但要注意,二者使用的時候,里面的臨時變量n指針所指向的 結構體是不一樣的(具體參考:inc/cli_info.h中的cli_info_list_find_by_fd()函數,這個函數寫了2種表達方式):
#if 1  //you can choose this expression or the next for list all of the elements. struct cli_info *n; list_for_each_entry_safe(pnode,n, &head->list, list) { #else struct list_head *p, *n; list_for_each_safe(p, n, &head->list) {   pnode = list_entry(p,struct cli_info,list); #endif


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM