内核链表的使用


<---百草枯--->

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