内核链表的使用
<---百草枯--->
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 
 | 
posted on 2013-08-14 00:04 Jason-liang 阅读(7264) 评论(0) 收藏 举报
                    
                
                
            
        
浙公网安备 33010602011771号