内核链表设计

1、编写一个内核模块,在模块中完成内核链表的创建、插入、删除、遍历等操作。

背景知识

1、内核链表实例分析

内核链表最大的特点是它的通用性,不必因为结构体中数据域的不同而单独为操作链表设计一套方法。

Linux内核在linux/lish.h文件中定义了内核通用链表list_head类型基本结构:

struct list_head

{struct list_head *next,*prev;}

内核链表的常用用途是将某一个数据结构本身串成链表,或将某些链表与一个数据结构联系起来,下面通过实例来说明将某一个数据结构本身串成链表的过程。

1)加入list_head结构成员

假设有一个example_struct结构需要连接成链表,因而其结构里面加上list_head成员,就组成了结构链表,如:

struct example_struct{

struct list_head list;

int priority;

.../*其他成员*/

}

在example_struct 结构中的list成员,用来将example_struct结构串成链表。可理解为list_head“背负”的负载是example_struct结构。

2)创建list_head结构

使用前必须申请链表头并用INIT_LIST_HEAD宏初始化链表头,可使用两种方法:

struct list_head example_list;

INIT_LIST_HEAD(&example_list);

或者

LIST_HEAD(example_list);

其中,这两个宏include/linux/list.h中定义如下:

#define LIST_HEAD(name) struct list_head name=LIST_HEAD_INIT(name)

#define INIT_LIST_HEAD(ptr) do{(ptr)->next=(ptr);(ptr)->pre=(ptr);}while(0)

宏定义INIT_LIST_HEAD初始化了链表,即向前、向后的指针都指向链表头。这样,就已经初始化了一个example_list的链表头,以后就可以向链表中增加链表元素了。

3)链表与用户结构连接

list_entry宏将example_list链表与example_struct结构类型连接起来。

下面这个代码行就是从example_list链表中得到的结点对应的example_struct结构指针,其中ptr是example_list链表中的指针,如ptr=example_list->next。

struct example_struct *node=list_entry(ptr,struct example_struct,list);

在上面代码行中的宏定义list_entry将一个list_head结构指针映射回一个指向结构example_struct的指针,即得到list_head的宿主结构。其宏定义在include/linux/list.h中

#define list_entry(ptr,type,member) container_of(ptr,type,member)

list_entry的功能是得到链表中结点的结构,它的参数含义为:

ptr是链表中的一个struct list_head结构元素指针。type是用户定义的结构类型,其中,包含struct list_head结构成员。member用户定义结构中的struct list_head结构成员名字。

4)遍历链表

下面使用list_entry宏遍历链表得到链表指针,再从链表指针映射回对应结构example_struct的指针,然后,对其成员priority进行操作,函数example_add_entry的功能是给链表加入新的结构成员。

mylist.c

Makefile

安装模块后insmod mylist.ko

.........................

模块初始化函数mylist_init被调用,在模块加载函数中,创建了一个内核链表,该链表的数据域是姓名和学号,指针域为list_head;接着使用list_add插入节点,使用list_for_each遍历整个链表,使用list_entry找出数据结构指针。由于list_add插入节点使用的是头插法,也就是说每次都在头节点处插入,因此先插入的节点反而在遍历时后打印出来。

内核链表是我们进行内核学习必须掌握的数据结构之一,它可以说是内核中使用得最为广泛的数据结构。除了能够正确使用内核链表,对于内核链表中各种操作方法的理解也是我们需要做到的。通过使用source insight查看内核源码在include/linux/list.h下分析内核链表的初始化、插入、删除、搬移、合并和遍历等操作的具体实现方法。如果你真正理解了内核链表,那么不仅对你学习内核有帮助,将它一直到你的应用程序中使用,也会使你的程序变得更加健壮。

另外一个函数:

时间: 2024-10-10 04:28:08

内核链表设计的相关文章

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

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

linux内核链表的移植与使用

一.  Linux内核链表为双向循环链表,和数据结构中所学链表类似,具体不再细讲.由于在内核中所实现的函数十分经典,所以移植出来方便后期应用程序中的使用. /*********************************** 文件名:kernel link list of linux.h 作者:Bumble Bee 日期:2015-1-31 功能:移植linux内核链表 ************************************/ /*链表结点数据结构*/ struct lis

Linux内核链表深度分析【转】

本文转载自:http://blog.csdn.net/coding__madman/article/details/51325646 链表简介: 链表是一种常用的数据结构,它通过指针将一系列数据节点连接成一条数据链.相对于数组,链表具有更好的动态性,建立链表时无需预先知道数据总量,可以随机分配空间,可以高效地在链表中的任意位置实时插入或者删除数据.链表的开销主要是访问的顺序性和组织链的空间损失. 内核链表的好主要体现为两点,1是可扩展性,2是封装.可扩展性肯定是必须的,内核一直都是在发展中的,所

链表的艺术——Linux内核链表分析

引言: 链表是数据结构中的重要成员之中的一个.因为其结构简单且动态插入.删除节点用时少的长处,链表在开发中的应用场景许多.仅次于数组(越简单应用越广). 可是.正如其长处一样,链表的缺点也是显而易见的.这里当然不是指随机存取那些东西,而是因为链表的构造方法(在一个结构体中套入其同类型指针)使得链表本身的逻辑操作(如添加结点,删除结点,查询结点等),往往与其应用场景中的业务数据相互混杂.这导致我们每次使用链表都要进行手工打造,做过链表的人肯定对此深有了解. 是否能将链表从变换莫測的业务数据中抽象出

Linux内核链表深度分析

链表简介: 链表是一种常用的数据结构,它通过指针将一系列数据节点连接成一条数据链.相对于数组,链表具有更好的动态性,建立链表时无需预先知道数据总量,可以随机分配空间,可以高效地在链表中的任意位置实时插入或者删除数据.链表的开销主要是访问的顺序性和组织链的空间损失. 内核链表的好主要体现为两点,1是可扩展性,2是封装.可扩展性肯定是必须的,内核一直都是在发展中的,所以代码都不能写成死代码,要方便修改和追加.将链表常见的操作都进行封装,使用者只关注接口,不需关注实现.分析内核中的链表我们 可以做些什

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内核链表

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 *//*××××××××××××××××