内核数据结构

内核数据结构

(作者:Baron_wu 禁止转载)

这部分包含了修改内核模块,所以要使用到内核链接表数据结构。

首先你得定义一个包含元素的结构去插入链表。
下边这段代码用C语言定义了生日结构:

struct birthday
{
	int day;
	int month;
	int year;
	struct list_head list;
};

注意struct list_head list。

结构list_head在包含目录的<linux/types.h>里有定义。它的作用就是嵌入包含列表节点的链接表。List_head这个结构非常简单,它仅包含两个成员:next和prev。它分别是下一个和上一个节点的入口。通过嵌入包含结构的链表,这让Linux通过一系列的宏函数管理数据结构变得可能。

接下来向链表插入元素

我们首先可以声明一个list_head,把他用作列表的参考头。使用宏LIST_HEAD()。

static LIST_HEAD(birthday_list);

这个宏定义了birthday_list并且初始化了birthday_list的变量。它是list_head结构类型。
我们创建并初始化birthday结构:


struct birthday *person;
person = kmalloc(sizeof(*person),GFP_KERNEL);
person->day = 2;
person->month = 8;
person->year = 1995;
INIT_LIST_HEAD(&person->list);

Kmalloc()函数相当于用户级别的malloc()函数。它的作用是分配内存,但是内核内存是已经被分配好的。
GFP_KERNEL是一个指明内核空间分配的标志;INIT_LIST_HEAD()初始化birthday结构的成员。
我们可以用list_add_tail()添加一个实例到链表的末尾。

list_add_tail(&person->list);

遍历链表:
通过list_for_each_entry()遍历时,包含三个参数。

  • 例如:
struct birthday *ptr;
list_for each_entry(ptr,&birthday_list,list){
	/* on each iteration ptr points */
	/* to the next birthday struct  */
}

接下来移除链表元素
可以通过list_del()

list_del(struct list_head *element);

这种删除会保留一些残余项在list中。
最简单的移除所有元素的方法是遍历list。
list_for_each_entry_safe()和list_for_each_entry()有相似之处。

  • 例如:
struct birthday *ptr, *next;
list_for each_entry_safe(ptr,next,&birthday_list,list){
	/* on each iteration ptr points */
	/* to the next birthday struct  */
	list_del(&ptr->list);
	kfree(ptr);
}

Kfree()函数把之前kmalloc()分配的空间返回给内核。

在模块起始点创建一个链接表包含五个数据结构元素,遍历这些元素,并在内核加载缓冲器里输出它的内容。使用dmesg查看
在模块退出时,删除所有元素并返回内存空间到内核。使用dmesg查看

实验截图:

内核数据结构