linux内核双向链表使用list klist

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:
linux内核中大量使用了链表数据结构来存储各种数据,比如device和driver使用klist存储,下面是list和klist使用示例


提示:以下是本篇文章正文内容,下面案例可供参考

一、list和klist是什么?

list:
list_head:双向链表,不带头节点,适用于需要按顺序存储和访问数据的场景。
在这里插入图片描述

klist:
klist: Linux 内核中用于管理和操作内核对象列表的数据结构。可以理解为一种带有引用计数的链表,主要用于跟踪和管理一组相关的对象
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
内核接口:
list_head:api:include\linux\list.h 中
LIST_HEAD_INIT \宏初始化
LIST_HEAD \宏初始化
INIT_LIST_HEAD \初始化

list_add \添加到头节点后面,头部添加
list_add_tail \添加到头节点前面,尾部添加

list_del \删除list中元素
list_replace 替换旧元素为新的元素

list_for_each
list_for_each_safe

RCU版:
INIT_LIST_HEAD_RCU
list_add_rcu
list_add_tail_rcu
list_del_rcu
list_for_each_entry_rcu
list_for_each_entry_srcu

klist:api:include\linux\klist.h 中
DEFINE_KLIST
klist_init
klist_add_tail
klist_add_head
klist_add_behind
klist_add_before
klist_del
klist_remove
klist_node_attached

二、代码示例

1.list

代码如下(示例):

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/slab.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("ChatGPT");
MODULE_DESCRIPTION("A Simple List Head Example");

struct my_data {
   
   
    int value;
    struct list_head list; // 使用 list_head 实现链表
};

static LIST_HEAD(my_list); // 创建链表头

// 初始化链表并添加元素
static void init_list(void) {
   
   
    struct my_data *data;
    int i = 0;
    
    for (i = 0; i < 5; i++) {
   
   
        data = kmalloc(sizeof(struct my_data), GFP_KERNEL);
        data->value = i;
        //INIT_LIST_HEAD(&data->list); // 初始化链表节点
### klist Drivers Information 在Linux内核中,`klist`是一种用于管理链表的数据结构,广泛应用于各种场景之中。对于驱动程序而言,`klist`被用来维护遍历设备及其对应的驱动程序列表。 #### 使用 `klist` 查看驱动程序信息 为了查看与`klist`相关的驱动程序信息,可以利用内核调试工具或编写自定义模块来访问这些数据。下面是一个简单的例子,展示如何通过读取 `/sys/kernel/debug/driver/` 下的内容获取当前加载的驱动程序列表: ```bash cat /sys/kernel/debug/drivers/klist_drivers ``` 如果上述路径不存在,则可能需要启用相应的配置选项或者安装额外的支持包。 另外,在源码层面,可以通过如下方式迭代并打印所有注册到特定总线上的驱动器实例: ```c #include <linux/device.h> #include <linux/list.h> void print_klist_drivers(struct bus_type *bus) { struct device_driver *drv; struct klist_iter i; klist_iter_init_node(&bus->p->drivers_kset.k_list, &i, NULL); while ((drv = next_driver(&i))) { printk(KERN_INFO "Driver Name: %s\n", drv->name); } klist_iter_exit(&i); } ``` 这段代码展示了怎样基于给定的总线对象(`bus`)遍历其下的每一个驱动程序节点,并输出它们的名字。需要注意的是这只是一个简化版的例子,实际应用时还需要考虑更多的边界条件以及错误处理逻辑[^1]。 #### 设备与驱动匹配过程中的角色 当涉及到设备与驱动之间的关联时,`struct device_driver` `struct device` 结构体起到了核心的作用。前者包含了有关驱动的信息服务接口;后者则代表具体的硬件实体。两者共同构成了Linux设备模型的基础框架之一。每当有新的设备加入系统时,就会尝试将其与现有的驱动相匹配,而这一过程中会用到诸如 `compatible` 字段这样的属性来进行筛选配对工作[^2]。 #### 资源管理自动释放机制 除了基本的功能外,Linux还提供了完善的资源管理方案,确保即使是在复杂环境下也能安全有效地分配回收各类物理及虚拟资源。例如,当一个驱动即将卸载时,系统能够依据预先建立好的链接关系图谱,自动化地完成一系列清理动作,从而避免潜在的风险隐患[^3]。 #### 历史遗留问题技术演进 早期版本的内核实现里曾采用过不同的API设计模式,比如直接调用了 `device_register()` 函数来完成某些初始化任务。随着时间推移发展进步,许多旧有的做法已经被更加现代化的方法所取代,但理解这部分历史背景有助于更好地把握整个体系架构的变化趋势[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值