链表简介
链表是一种常用的数据结构,它通过指针将一系列数据节点连接成一条数据链。相对于数组,链表具有更好的动态性,建立链表时无需预先知道数据总量,可以随机分配空间,可以高效地在链表中的任意位置实时插入或删除数据。链表的开销主要是访问的顺序性和组织链的空间损失。
链表的种类有很多:
单向链表、双向链表、循环链表等等。
Linux内核链表属于双向循环链表。
传统链表与Linux内核链表的区别:
传统链表一个节点包含数据域和指针域,指针域指向的位置往往时下一个或上一个节点的开始位置。传统链表的一个缺陷就是每个节点的数据域的数据类型是相同的,用户无法给每个节点安排不同的数据类型。
Linux内核链表解决了上述缺陷,它的指针域的指针指向的位置时下一个或上一个节点指针域的开始位置,这样用户可以任意指定数据域的数据类型。指针域的类型时统一的。
内核链表
结构:
struct list_head
{
struct list_head *next, *prev;
};
list_ head 结构包含两个指向 list_head 结构的指针prev和next,由此可见,内核的链表具备双链表功能,实际上,通常它都组织成双向循环链表。
函数:
1、 INIT_ LIST_HEAD:创建链表
2、 list_ add:在链表头插入节点
3、 list_ add_tail:在链表尾插入节点
4、 list_ del:删除节点
5、 list_ entry:取出节点
6、 list_ for_ each:遍历链表
代码编写
mylist.c文件
#include <linux/init.h>
#include <linux/module.h>
#include <linux/list.h> //使用内核链表需要的头文件
struct score//自定义结构体,学生的学号和成绩
{
int number;//数据域
int english;
int math;
struct list_head list;//指针域
};
struct list_head score_head;//定义链表头结点
struct score stu1, stu2, stu3, *tmp;
struct list_head *pos; //用于遍历链表的指针
static int mylist_list()
{
//创建链表
INIT_LIST_HEAD(&score_head); //创建链表,参数是头结点指针域的地址
stu1.number = 1;
stu1.english = 1;
stu1.math = 1;
stu2.number = 2;
stu2.english = 2;
stu2.math = 2;
stu3.number = 3;
stu3.english = 3;
stu3.math = 3;
//插入节点
list_add_tail(&(stu1.list), &score_head);//在链表尾插入节点,
list_add_tail(&(stu2.list), &score_head);//参数1节点指针域地址
list_add_tail(&(stu3.list), &score_head);//参数2头结点指针域地址
//遍历链表
list_for_each(pos, &score_head)
//第一个参数是list_head指针,第二个参数是头结点地址,要使用大括号,是for循环
//随着遍历的进行,pos指针分别指向每一个节点
{
//取出节点,注意:返回值是节点指针
tmp = list_entry(pos, struct score, list);
//参数1:光标指针,参数2:节点类型,参数3:节点指针域名字
printk("第 %d 号学生\n", tmp->number);
printk("英语成绩:%d\n", tmp->english);
printk("数学成绩:%d\n", tmp->math);
printk("\n");
}
return 0;
}
static void mylist_exit()
{
//删除节点,参数为节点的指针域地址
list_del(&(stu1.list));
list_del(&(stu2.list));
list_del(&(stu3.list));
}
module_init(mylist_list);
module_exit(mylist_exit);
makefile 文件:
obj-m := mylist.o
KDIR := /home/ARM_Linux/system2/season4/First/part3/linux-ok6410
all:
make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm
clean:
rm -f *.o *.ko *.order *.symvers *.bak *.mod.c