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

yizhihongxing

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日

相关文章

  • Win10创造者更新预览版14986自制ISO镜像下载地址汇总

    Win10创造者更新预览版14986自制ISO镜像下载地址汇总攻略 本攻略将详细介绍如何获取Win10创造者更新预览版14986的自制ISO镜像下载地址。请按照以下步骤进行操作: 步骤一:访问官方网站 首先,打开你的浏览器并访问Win10官方网站。你可以在搜索引擎中输入\”Win10官方网站\”来找到正确的链接。 步骤二:导航到下载页面 在官方网站上,寻找一…

    other 2023年8月4日
    00
  • Linux里LVM磁盘扩容详细步骤

    下面是关于“Linux里LVM磁盘扩容详细步骤”的完整攻略。 准备工作 在进入具体操作之前,需要先进行一些准备工作。 查看LVM分区信息 首先需要确定LVM和分区的信息,使用如下命令来查看: sudo pvs sudo vgs sudo lvdisplay 其中,pvs用于显示物理卷信息,vgs用于显示卷组信息,lvdisplay用于显示逻辑卷信息。 扩容磁…

    other 2023年6月28日
    00
  • qt如何发送https请求

    qt如何发送https请求 在Qt中发送HTTPS请求可以通过Qt网络模块中提供的QNetworkAccessManager类实现。HTTPS在网络请求中使用的是TLS/SSL协议保证数据传输的安全性。在使用QNetworkAccessManager发送HTTPS请求前,需要在Qt项目中引入OpenSSL库,这是由于Qt本身并不包含用于TLS/SSL连接的实…

    其他 2023年3月28日
    00
  • JavaSript中变量的作用域闭包的深入理解

    JavaScript中变量的作用域闭包的深入理解 在JavaScript中,变量的作用域和闭包是非常重要的概念。理解它们的工作原理对于编写高质量的JavaScript代码至关重要。本攻略将详细讲解变量的作用域和闭包,并提供两个示例来说明这些概念。 变量的作用域 变量的作用域指的是变量在代码中可访问的范围。在JavaScript中,有三种作用域:全局作用域、函…

    other 2023年8月19日
    00
  • mybatis typeAliases 给实体类起别名的方法

    MyBatis TypeAliases给实体类起别名的方法 在MyBatis中,可以使用typeAliases来为实体类起别名。这样做的好处是可以简化代码中使用的实体类名称,提高可读性和可维护性。以下是使用typeAliases给实体类起别名的完整攻略。 步骤一:配置typeAliases 首先,需要在MyBatis的配置文件(例如mybatis-confi…

    other 2023年6月28日
    00
  • windows下使用vscode搭建golang环境并调试的过程

    下面就给大家介绍一下windows下使用vscode搭建golang环境并调试的过程的完整攻略。 环境搭建 安装Golang 首先,我们需要在官网(https://golang.org/dl/)下载golang的安装包并进行安装。安装完成后,可以在命令行中输入go version,若成功打印出版本号,则说明安装成功。 安装VSCode 接着,我们需要在官网(…

    other 2023年6月27日
    00
  • Scratch3.0初始化加载七牛云上的sbs文件的方法

    首先,Scratch3.0是一个非常流行的图形化编程工具,七牛云是一家云存储和内容分发网络服务商,为用户提供了方便快捷的云端存储服务。在Scratch3.0中,我们可以使用七牛云的存储空间来初始化加载sbs文件。以下是详细的攻略: 步骤1:在七牛云上创建存储空间 首先,你需要在七牛云上注册账号并且创建存储空间。创建存储空间时可以选择不同的存储区域、空间名称和…

    other 2023年6月20日
    00
  • htmlvideomuted属性

    以下是“htmlvideomuted属性”的完整攻略: HTML Video muted属性 HTML Video元素是用于在网页中嵌入视频的标准元素。muted属性是Video元素的一个布尔属性,用于控制视频是否静音播放。本攻略中,我们将详细讲解HTML Video muted属性的使用方法。 使用方法 要使用HTML Video muted属性,我们需要…

    other 2023年5月8日
    00
合作推广
合作推广
分享本页
返回顶部