内核链表的应用

本文构建了一个双向循环的内核链表,然后对链表进行遍历并打印了数据,最后释放了链表节点。使用到的数据结构和链表操作函数如下:

struct list_head                      内核提供的双向循环链表节点的结构体

LIST_HEAD(name)               该宏定义并初始化一个名为name的struct list_head类型节点

INIT_LIST_HEAD(name)      该宏初始化一个由name指向的 struct list_head类型节点,事先需要定义好一个struct list_head类型变量,

          并将变量的指针赋给name,然后再使用该宏

list_for_each(pos, head)       该宏可以遍历以head为链表头的循环链表,pos是遍历到的每个节点,pos和head均为指针类型。

list_entry(ptr, type, number)    该宏可以得到type类型的结构体指针,number为包含在该type类型结构体中的struct list_head类型成员变量,

ptr为&number。返回值为指向type类型的指针。

list_for_each_safe(pos, n, head)该宏类似于list_for_each宏,区别在于每次遍历,n指向了pos的下一个节点。该宏可用于释放链表节点之用。

程序代码如下:

 1  #include <linux/slab.h>
 2   #include <linux/sched.h>
 3   #include <linux/module.h>
 4   #include <linux/kernel.h>
 5   #include <linux/init.h>
 6   #include <linux/list.h>
 7
 8   struct fox {
 9           int data;
10           struct list_head list;
11   };
12
13   int i;
14   struct list_head *temp;
15   struct fox *tmp;
16   LIST_HEAD(head);
17
18   static int __init test_init(void)
19   {
20           for (i = 0; i < 10; i++) {
21                   tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
22                   tmp->data = i;
23                   INIT_LIST_HEAD(&tmp->list);
24                   list_add_tail(&tmp->list, &head);
25           }
26
27           list_for_each(temp, &head) {
28                   tmp = list_entry(temp, struct fox, list);
29                   printk("<0> %d\n", tmp->data);
30           }
31
32           return 0;
33   }
34
35   static void __exit test_exit(void)
36   {
37           struct list_head *next;
38
39           printk("<1> byebye\n");
40           list_for_each_safe(temp, next, &head) {
41                   tmp = list_entry(temp, struct fox, list);
42                   printk("<0> %d\n", tmp->data);
43                   kfree(tmp);
44           }
45   }
46
47   module_init(test_init);
48   module_exit(test_exit);
49   MODULE_LICENSE("GPL");

需要注意的是,在释放链表时,不可以直接用list_del(pos)宏来删除节点,该宏仅仅是把struct list_head节点从其链表中卸下来,而且不释放。而我们需要删除的是fox结构体,所以只能使用本文中的这种方法,利用list_for_each_safe()宏,将需要释放的节点指针保存到pos中,同时将下一个节点指针保存在next中,这样就保证了释放节点时链表不会丢失。其实list_head节点是不用单独去释放的,该结构体一般会以结构体变量的形式保存在更大的结构体中,只要释放更大结构题即可。如本例所示的那样。

内核链表的应用

时间: 07-14

内核链表的应用的相关文章

Linux 内核链表

一 . Linux内核链表 1 . 内核链表函数 1.INIT_LIST_HEAD:创建链表 2.list_add:在链表头插入节点 3.list_add_tail:在链表尾插入节点 4.list_del:删除节点 5.list_entry:取出节点 6.list_for_each:遍历链表 2.程序代码

例说Linux内核链表(二)

链表使用 我认为熟悉内核链表功能最好的方法就是看一些简单的实例,实例是一个非常好的素材去更好的理解链表. 下面是一个例子,包含创建,添加,删除和遍历链表. <span style="font-size:14px;"><span style="color:#330099;">#include <stdio.h> #include <stdlib.h> #include "list.h" struct

Linux 内核 链表 的简单模拟(2)

接上一篇Linux 内核 链表 的简单模拟(1) 第五章:Linux内核链表的遍历 /** * list_for_each - iterate over a list * @pos: the &struct list_head to use as a loop cursor. * @head: the head for your list. */ #define list_for_each(pos, head) for (pos = (head)->next; pos != (head);

linux驱动开发要知道的那些知识(二)------list内核链表

内核链表 链表数据结构简介 链表是一种常用的组织有序数据的数据结构,它通过指针将一系列数据节点连接成一条数据链,是线性表的一种重要实现方式.相对于数组,链表具有更好的动态性,建立链表时无需预先知道数据总量,可以随机分配空间,可以高效地在链表中的任意位置实时插入或删除数据.链表的开销主要是访问的顺序性和组织链的空间损失. 通常链表数据结构至少应包含两个域:数据域和指针域,数据域用于存储数据,指针域用于建立与下一个节点的联系.按照指针域的组织以及各个节点之间的联系形式,链表又可以分为单链表.双链表.

深入分析Linux内核链表

1. 普通单链表 2. 内核链表 上图是本人从其他博客盗来的,差点被糊弄过去. 下图是本人自己用KeyNote画的(唉!!画图真的是让人心好累啊!!). 差异是不是很明显啊?! Read The Fucking Source Code 1. 初始化 /* include/linux/types.h */ struct list_head { struct list_head *next, *prev; }; /* include/linux/list.h *//*××××××××××××××××

10、内核链表的学习

首先是创建内核模块. 按照上面的那张图,我们知道,我们创建链是使用INIT_LIST_HEAD这个函数.现在我们来使用source insight查看该函数的结构. 该函数是对我们的链表头进行初始化的.我们把链表头做一个参数传进来之后.我们分别用next和prev指针同时指向他本身. 可以看到,该函数是个内联函数.该函数只有一个参数,是struct list_head类型的指针,他就是我们要初始化的链表头. 所以我们得来创建这个链表头结构.Struct list_head list score_

内核链表

能不能一种链表中链接不同的类型呢,相应这种号召,内核链表诞生了. 内核链表之所以能够链接不同的类型的数据,是因为它和普通链表不一样,它链接的不是数据结构的起始地址,而是链接的该数据结构中的的list_head属性. 下面是比较重要的函数: 其他的都很简单,专门介绍一下list_entry函数: 函数最后返回的是这个结构体节点起始地址.Ptr是这个节点中list_head属性的地址,type是这个结构体节点的真实类型,member是这个结点中list_head属性的名字. 其中typeof关键字调

例说Linux内核链表(一)

介绍 众所周知,Linux内核大部分是使用GNU C语言写的.C不同于其他的语言,它不具备一个好的数据结构对象或者标准对象库的支持.所以可以借用Linux内核源码树的循环双链表是一件很值得让人高兴的事. 在include/linux/list.h文件中用C实现了一个好用的循环链表.它是有效而且易于操作的,否则它也不会被内核使用(译者注:在kernel中大量的使用了循环双链表结构,比如在在进程描述符实体中我们就可以看到很多struct list_head的身影).不管何时,依靠这种结构,在内核中都

例说Linux内核链表(三)

经常使用的linux内核双向链表API介绍 linux link list结构图例如以下: 内核双向链表的在linux内核中的位置:/include/linux/list.h 使用双向链表的过程,主要过程包括创建包括struct link_head结构的结构体(item),建立链表头.向链表中加入item(自己定义数据结构.双向链表数据单元).删除链表节点.遍历链表,判空等. 1.建立自己定义链表数据结构 struct kool_list{ int to; struct list_head li

linux内核链表的使用

linux内核链表:链表通常包括两个域:数据域和指针域.struct list_head{struct list_head *next,*prev;};include/linux/list.h中实现了一套精彩的链表数据结构.传统的链表指针指向下一个节点的头部.linux链表指针指向下一个指针list_head结构(*next),双向循环.不会随着外部数据的变化而变化,使它具有通用性.? -------------------------------------------------------