Linux内核设备驱动之内核中链表的使用笔记整理

Linux内核设备驱动之内核中链表的使用笔记整理

1. 简介

在Linux内核中,链表(linked list)是一个常用的数据结构,用于实现不同的数据结构,例如队列、栈、哈希表等。链表的结构相对于数组更加灵活,可以动态地添加和删除元素,但是在访问链表中的元素时需要遍历整个链表,因此访问速度相对较慢。在驱动程序中,链表的使用也很普遍,例如用于管理设备队列、内存块等。

Linux内核提供了链表实现的头文件<linux/list.h>,通过struct list_head结构体定义链表节点。每个节点包含两个指针,next指向链表的下一个节点,prev指向链表的前一个节点。所以可以通过链表遍历访问链表中的所有节点。以下将从链表的定义、初始化、添加/删除、遍历等方面进行详细介绍。

2. 链表定义与初始化

链表是由多个链表节点构成的,每个链表节点都有其自己的数据域和指向前一个节点和后一个节点的指针。所以链表节点的定义如下:

struct list_head {
    struct list_head *prev, *next;
};

struct list_head即是一个链表节点。

在定义好链表节点结构体之后,就可以定义链表了,链表即是由多个链表节点构成的,形式上”的链表即是指向链表节点的指针。

struct list_head my_list_head;

链表的初始化可以使用INIT_LIST_HEAD宏来完成。该宏将链表的头部节点设为空,使所有节点都不再被链接起来。

INIT_LIST_HEAD(&my_list_head);

3. 添加/删除节点

链表添加/删除节点的操作是非常常见的操作。本部分将介绍如何在链表中添加/删除节点。

链表中的每一个元素都被形式化地视为一个链表节点,它的链表属性通过list_head数据结构而实现,我们可插入任何的元素到这个节点的前面或者后面。

以下代码展示如何插入一个元素(一个inode)到链表中。

void add_to_list(struct inode *node, struct list_head *head)
{
    list_add(&node->list, head);
}

list_add是一个Linux提供的宏,以下是它的定义:

#define list_add(new, head) __list_add((new), (head), (head)->next)

可以看到,list_add函数的参数中,第一个参数new是新的节点,第二个参数head是链表的头部节点,第三个参数则是new节点添加的位置。将新节点插入到链表头部或尾部的代码如下:

# 链表头部插入新节点
void add_to_head(struct inode *node, struct list_head *head)
{
    list_add(&node->list, head);
}

# 链表尾部插入新节点
void add_to_tail(struct inode *node, struct list_head *head)
{
    list_add_tail(&node->list, head);
}

在链表中删除一个节点,可以使用list_del宏,该宏对链表节点的前后指针进行处理,将当前节点从链表中删掉:

void delete_one_node(struct inode *node, struct list_head *head)
{
    list_del(&node->list);
}

4. 遍历链表

遍历链表是必不可少的,而Linux内核链表的遍历有两种方式,一种是while loop遍历,另一种则是各种带有foreach宏的快捷方式,以下详细介绍这两种方式。

遍历链表的基本操作就是从链表的头部节点依次往下遍历,对于每一个节点执行想要的操作,这里我们展示如何遍历整个链表并输出每一个节点的地址信息:

void traverse_list(struct list_head *head)
{
    struct inode *pos, *next;
    list_for_each_entry_safe(pos, next, head, list) {
        printk(KERN_INFO "entry: %p\n", pos);
    }
}

在上述代码中,list_for_each_entry_safe是一个宏,其依次遍历链表中的每一个节点,在节点的list成员中获取前/后指针(pos),在代码块中对pos节点进行操作,next则是遍历保护结构体,防止在遍历时节点被意外地删除。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Linux内核设备驱动之内核中链表的使用笔记整理 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • Google I/O 2015谷歌开发者大会前瞻 实时地球/Android M 是啥?

    Google I/O 2015谷歌开发者大会前瞻 Google I/O是全球最大的开发者盛会之一,每年都会吸引大量的开发者和科技爱好者聚集在一起,共同研讨最新的技术和趋势。2015年的Google I/O大会将于5月28日-29日在美国加州举行,本文将对该大会进行前瞻,并解释其中几个关键技术的含义和应用领域。 实时地球 实时地球是一种新型的地理可视化技术,可…

    other 2023年6月26日
    00
  • 详解vue服务端渲染(SSR)初探

    详解vue服务端渲染(SSR)初探 本文将详细讲解Vue服务端渲染(SSR)的核心概念、实现过程和优化技巧,帮助读者全面理解Vue SSR的工作原理和优化方法。 什么是Vue SSR? Vue SSR是指将Vue组件在服务器端渲染成HTML字符串,然后再将该字符串发送给浏览器端进行解析和展示的技术。与客户端渲染(CSR)不同,Vue SSR可以让搜索引擎更好…

    other 2023年6月27日
    00
  • 3dmax默认路径怎么自定义设置?

    当你在使用 3D Max 进行建模、渲染等操作时,它默认会保存和保留文件在一些特定的文件夹路径中。但是,如果你想要保存到自己的文件夹路径中却找不到合适的设置选项该怎么办呢? 下面就为大家详细讲解“3dmax默认路径怎么自定义设置”的完整攻略: 第一步:打开菜单栏 首先,我们需要打开 3D Max 的菜单栏。在菜单栏中,选择“自定义”选项卡,然后选择“首选项(…

    other 2023年6月25日
    00
  • Android判断后台服务是否开启的两种方法实例详解

    Android判断后台服务是否开启的两种方法实例详解 在Android开发中,有时候我们需要判断某个后台服务是否正在运行。下面将详细介绍两种方法来实现这个目标。 方法一:通过ActivityManager判断 public static boolean isServiceRunning(Context context, Class<?> serv…

    other 2023年10月13日
    00
  • Spring Bean生命周期之Bean元信息的配置与解析阶段详解

    接下来我将详细讲解“Spring Bean生命周期之Bean元信息的配置与解析阶段详解”的完整攻略。 Spring Bean的元信息 在Spring中,Bean的元信息是Spring容器在启动时读取配置文件或注解生成的BeanDefinition,它主要包含Bean的定义、Bean的依赖、Bean的作用域、延迟加载等一系列的Bean属性配置。通常情况下,我们…

    other 2023年6月27日
    00
  • Nacos配置的多文件加载与共享配置方式

    Nacos是阿里巴巴开源的一个服务发现和配置中心框架,支持多种配置格式和数据源,具有高可用和可扩展性。在使用Nacos进行配置管理时,可以通过多文件加载和共享配置方式实现更加灵活和高效的配置管理。 多文件加载 在Nacos中,可以将配置按照不同的属性隔离到不同的文件中,然后使用nacos-client来同时加载多个配置文件进行统一管理。 具体步骤如下: 创建…

    other 2023年6月25日
    00
  • Linux环境变量配置的完整攻略

    Linux环境变量配置的完整攻略 在Linux环境下,环境变量是一种非常重要的配置项,它可以影响系统的各种行为,例如命令搜索路径、程序库搜索路径、语言设置等。因此,正确配置环境变量对于系统安全、性能、可维护性都具有极为重要的作用,同时也是Linux系统管理工作中不可避免的一部分。下面就是环境变量配置的完整攻略。 1. 环境变量的定义 环境变量是存在于shel…

    other 2023年6月27日
    00
  • tokudb的特点验证

    tokudb的特点验证 Tokudb是一个高性能、节省空间的MySQL存储引擎,它采用了特别的技术,包括 Fractal Tree 索引、Hot Column Cache、无限扩展等等。那么,如何验证Tokudb这些特点呢? Fractal Tree 索引 Tokudb的 Fractal Tree 索引是其最大的特点之一,它可以在索引中支持无限个条目。这就是…

    其他 2023年3月28日
    00
合作推广
合作推广
分享本页
返回顶部