linux内核双向链表使用list klist

news2024/9/27 6:00:45

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

文章目录

  • 前言
  • 一、list和klist是什么?
  • 二、代码示例
    • 1.list
    • 2.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); // 初始化链表节点
		printk("no INIT_LIST_HEAD i = %d\n", i);
        // 将新节点添加到链表头
        list_add_tail(&data->list, &my_list);
    }
}

// 遍历链表并打印值
static void print_list(void) {
    struct my_data *data;
    struct list_head *pos;

    list_for_each(pos, &my_list) {
        data = list_entry(pos, struct my_data, list);
        pr_info("Value: %d\n", data->value);
    }
}

// 清理链表并释放内存
static void cleanup_list(void) {
    struct my_data *data;
    struct list_head *pos, *q;

    list_for_each_safe(pos, q, &my_list) {
        data = list_entry(pos, struct my_data, list);
        list_del(pos); // 从链表中删除节点
        kfree(data);   // 释放内存
    }
}

static int __init my_module_init(void) {
    pr_info("Initializing module...\n");
    init_list();
    print_list();
    return 0;
}

static void __exit my_module_exit(void) {
    pr_info("Cleaning up module...\n");
    cleanup_list();
}

module_init(my_module_init);
module_exit(my_module_exit);

2.klist

代码如下(示例):
多线程暂不完善仅供参考

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/klist.h>
#include <linux/kref.h>


struct my_klist_node {
    struct klist_node n_klist; // klist_node 
    int data;                // 额外的数据
};

// 自定义的获取和释放函数
void my_get(struct klist_node *node) {
    struct my_klist_node *my_node = container_of(node, struct my_klist_node, n_klist);
    printk(KERN_INFO "Getting node with data: %d\n", my_node->data);
    //kref_get(&node->n_ref); // 增加引用计数
}

void my_put(struct klist_node *node) {
    struct my_klist_node *my_node = container_of(node, struct my_klist_node, n_klist);
    printk(KERN_INFO "Putting node with data: %d\n", my_node->data);
    //kref_put(&node->n_ref, my_kref_release); // 释放内存并减少引用计数
	kfree(my_node);
}

// 定义一个全局 klist 实例
DEFINE_KLIST(my_klist, my_get, my_put);

// 添加节点到 klist 的函数
void my_add_node(int value) {
    struct my_klist_node *new_node;
    
    new_node = kmalloc(sizeof(*new_node), GFP_KERNEL);
    if (!new_node)
        return;

    new_node->data = value;
    klist_add_head(&new_node->n_klist, &my_klist);
}

void my_del_node(int value) {
    struct my_klist_node *new_node;

    klist_del(&new_node->n_klist);
}

static void my_print(void)
{
	struct klist_iter i;
	struct klist_node *node;
	struct my_klist_node *my_node;
	
	klist_iter_init_node(&my_klist, &i, NULL);
	while ((node = klist_next(&i)))
	{
		my_node = container_of(node, struct my_klist_node, n_klist);
		printk(KERN_INFO "klist_iter_init_node data: %d\n", my_node->data);
	}
	klist_iter_exit(&i);
}

// 模块加载函数
static int __init my_module_init(void) {
    klist_init(&my_klist, my_get, my_put); // 初始化 klist
    int i = 0;
	for(i;i < 5; i++)
	{
		my_add_node(i*10); // 添加一个节点
	}

	my_print();
    return 0;
}

// 模块卸载函数
static void __exit my_module_exit(void) {
	struct klist_iter i;
	struct klist_node *node;
	struct my_klist_node *my_node;
	
	klist_iter_init_node(&my_klist, &i, NULL);
	while ((node = klist_next(&i)))
	{
		my_node = container_of(node, struct my_klist_node, n_klist);
		printk(KERN_INFO "klist_iter_init_node data: %d\n", my_node->data);
		//klist_remove 不能在此使用,spin死锁
		klist_del(&my_node->n_klist); //这个会减少引用计数,可能并不会删除,线程可能不安全
		//kfree(my_node);
	}
	klist_iter_exit(&i);
}

module_init(my_module_init);
module_exit(my_module_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Example of using klist in the Linux kernel.");


总结

上面介绍了内核中list和klist和测试代码,仅供参考

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2169132.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring Boot打造甘肃非遗文化传承网站

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本甘肃非物质文化网站就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信…

如何像专家一样修复任何 iPhone 上的“iPhone 已禁用”错误

“我忘记了密码&#xff0c;并且我的 iPhone 在多次输入错误密码后就被禁用了&#xff0c;如何再次访问我的手机&#xff1f;” 作为最安全的数字设备之一&#xff0c;iPhone 必须使用正确的密码解锁。即使您可以使用 Face ID 或 Touch ID 访问您的设备&#xff0c;在充电或重…

交警车辆通入城行证管理建设方案和必要性-———未来之窗行业应用跨平台架构

一、系统目标 建立一个高效、便捷、规范的车辆入城通行证管理系统&#xff0c;提高交警部门的管理效率&#xff0c;优化城市交通流量&#xff0c;减少交通拥堵&#xff0c;保障城市交通安全。 二、系统功能模块 1. 通行证申请模块 - 提供在线申请入口&#xff0c;申请人填…

【MySQL】聚合函数、group by子句

目录 聚合函数 count([distinct] column) sum([distinct] column) avg([distinct] column) max([distinct] column) min([distinct] column) group by子句 1.如何显示每个部门的平均薪资和最高薪资 2.显示每个部门每种岗位的平均薪资和最低薪资 3.显示平均工资低于200…

maven给springboot项目打成jar包 maven springboot打包配置

基于maven的spring boot 打包分离依赖及配置文件 使用springCloud或springboot的过程中&#xff0c;发布到生产环境的网速受限&#xff0c;如果每次将60,70M甚至更大的jar包上传&#xff0c;速度太慢了&#xff0c;采取jar包和配置文件分离的方式可以极大的压缩jar包大小&#…

npm 安装newman时idealTree:vue: sill idealTree buildDeps卡住了(实测成功)

删除 C:\Users\{账户}\ 文件夹中的 .npmrc 文件在命令提示符里执行 npm cache verify 在命令提示符里执行 npm config set registry https://registry.npmmirror.com 切换淘宝源来源&#xff1a; https://blog.csdn.net/weixin_39245942/article/details/135748323

【Verilog学习日常】—牛客网刷题—Verilog企业真题—VL62

序列发生器 描述 编写一个模块&#xff0c;实现循环输出序列001011。 模块的接口信号图如下&#xff1a; 要求使用Verilog HDL实现&#xff0c;并编写testbench验证模块的功能。 输入描述&#xff1a; clk&#xff1a;时钟信号 rst_n&#xff1a;复位信号&#xff0c;低电平…

【学习笔记】手写 Tomcat 七

目录 一、优化 Dao 1. 设置 UserDaoImpl 为单例模式 2. 创建 Dao 工厂 3. 在 Service 层获取 UserDao 的实例 二、优化 Service 1. 设置 UserServiceImpl 为单例模式 2. 创建 Service 工厂 3. 在 Servlet 层获取 Service 实现类的对象 三、优化 Servlet 1. 使用配置…

Map+Set

我们前面接触过的string、vector、list这些都算序列式容器&#xff0c;它们都有一定的关联性&#xff0c;即使随便换位置也无伤大雅&#xff0c;因为是它们靠位置顺序来保存的。但是今天的MapSet就不是了&#xff0c;它们算关联式容器&#xff0c;两个位置之间有紧密的联系&…

Linux-df命令使用方法

Linux-df&#xff08;disk filesystem&#xff09;命令 df 命令是 Unix 和 Linux 系统中用于报告文件系统磁盘空间使用情况的工具。 df [OPTION]... [FILE]...OPTION 常用选项&#xff08;博主一般df -h用的较多&#xff0c;可读性较好&#xff09; -h&#xff1a;以人类可读的…

Uniapp 微信小程序 最新 获取用户头像 和 昵称 方法 有效可用

文章目录 前言代码实现运行效果技术分析 前言 同事有个需求 授权获取用户头像 和 昵称 。之前做过线上小程序发版上线流程 就实现了下 最新的方法和 api 有些变化 记录下 代码实现 先直接上代码 <template><view class"container"><buttonclass&qu…

如何部署北斗定位应用,基于国产自主架构LS2K1000LA-i处理器平台

北斗卫星导航系统(以下简称北斗系统)是着眼于国内经济社会发展需要,自主建设、独立运行的卫星导航系统。经过多年发展,北斗系统已成为面向全球用户提供全天候、全天时、高精度定位、导航与授时服务的重要新型基础设施。 图 1 北斗定位系统的应用优势 强可控:北斗系统是国…

Ollama本地部署大模型及应用

文章目录 前言一、下载安装1.Mac2.Windows3.linux4.docker5.修改配置&#xff08;可选&#xff09;1.linux系统2.window 系统3.mac系统 二、Ollama使用1.命令2.模型下载3.自定义模型4.API 服务 三、Open WebUI 使用四、Dify使用 前言 Ollama 是一个专注于本地部署大型语言模型…

第四届摩纳哥智能化可持续发展游艇码头交流会

第四届摩纳哥智能化可持续发展游艇码头交流会 游艇生态和经济转型 2024年9月23日&#xff0c;第四届摩纳哥智能化可持续发展游艇码头交流会于摩纳哥游艇俱乐部顺利落幕。该交流会由摩纳哥游艇码头顾问公司&#xff08;M3&#xff09;主办&#xff0c;吸引了全球250名游艇行业领…

数据集-目标检测系列-口罩检测数据集 mask>> DataBall

数据集-目标检测系列-口罩检测数据集 mask>> DataBall 数据集-目标检测系列-口罩检测数据集 mask 数据量&#xff1a;1W DataBall 助力快速掌握数据集的信息和使用方式&#xff0c;享有百种数据集&#xff0c;持续增加中。 数据项目地址&#xff1a; gitcode: https…

JAVA笔记 | 实际上用到的策略模式(可直接套用)

自己开发中用到了策略模式&#xff0c;这样写不一定是最好的&#xff0c;但是满足了业务场景跟使用要求&#xff0c;做个笔记&#xff0c;下次有用到可以快速复习跟套用 假设使用场景&#xff1a;有几只宠物&#xff0c;猫跟狗等&#xff0c;要求他们做各种动作&#xff0c;比如…

无人机之物流货运篇

一、无人机货运的崛起 随着电商、快递行业的蓬勃发展&#xff0c;传统的地面物流已经难以满足日益增长的快递量和对速度的追求。而无人机货运凭借其高效、快捷、灵活的特点&#xff0c;逐渐成为了物流行业的新宠。无人机可以在城市上空快速穿梭&#xff0c;不受地面交通拥堵的限…

语言模型发展史

四个阶段 第一阶段&#xff1a;基于规则和统计的语言模型 由人工设计特征并使用统计方法对固定长度的文本窗口序列进行建模分析&#xff0c;这种建模方式也被称为N-gram语言模型。 优点&#xff1a; 1&#xff09;采用极大似然估计, 参数易训练 2&#xff09;完全包含了前n-…

Arthas vmtool(从 jvm 里查询对象,执行 forceGc)

文章目录 二、命令列表2.1 jvm相关命令2.1.15 vmtool&#xff08;从 jvm 里查询对象&#xff0c;执行 forceGc&#xff09;举例1&#xff1a;获取对象 二、命令列表 2.1 jvm相关命令 2.1.15 vmtool&#xff08;从 jvm 里查询对象&#xff0c;执行 forceGc&#xff09; vmtoo…

nodejs 014: React.FC 与 Evergreen(常青树) React UI 框架的的Dialog组件

React.FC React.FC是React中用于定义函数组件“Function Component”的类型。它代表&#xff0c;可以帮助你在TypeScript中提供类型检查和自动补全。使用React.FC时&#xff0c;可以明确指定组件的props类型&#xff0c;并且它会自动推导children属性。下面是一个使用 React.F…