linux内核双向链表使用list klist

embedded/2024/10/19 7:27:39/

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

文章目录


前言

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


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

listklist_16">一、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

二、代码示例

list_62">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);

list_138">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); // 初始化 klistint 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.ppmy.cn/embedded/120073.html

相关文章

springboot第74集:设计模式

解析 核心线程数与CPU核数相同&#xff1a;避免线程过多导致的上下文切换&#xff0c;提高CPU利用率。无界队列&#xff1a;适合任务量大且任务执行时间短的场景&#xff0c;避免因队列满而拒绝任务。 IO密集型任务 场景描述 适用于执行大量IO操作的任务&#xff0c;如文件读写…

JDBC进阶

目录 JDBC进阶 实体类和ORM 主键回显 批量操作 连接池 介绍 常见的连接池 Druid连接池 Hikari连接池 连接池与软编码 其他配置 Druid配置 Hikari配置 JDBC进阶 实体类和ORM 在使用JDBC操作数据库时会发现数据都是零散的&#xff0c;明明在数据库中是一行完整的数…

3-2 AUTOSAR RTE对Runnable的作用

返回总目录->返回总目录<- 一、前言 通过RTE给runnable提供触发事件。 runnable是可以被触发的,但是需要通过RTE来实现这个触发和调用runnable通过RTE给runnable提供所需资源。 RTE将runnable需要的一些资源通过接口传输给它(Port的实现)将BSW和SWC做隔绝。 因此OS和r…

冒泡排序-C语言

1.问题&#xff1a; 从小到大对10个数进行排序&#xff0c;要求使用冒泡排序实现。 2.解答&#xff1a; 排序规律有两种&#xff1a;一种是“升序”&#xff0c;从小到大&#xff1b;另一种是“降序”&#xff0c;从大到小。 3.代码&#xff1a; #include<stdio.h>//头…

《深度学习》—— 神经网络中的调整学习率

文章目录 一、什么是调整学习率&#xff1f;二、使用PyTorch中的库函数进行调整学习率三种常用的方法1. StepLR2. MultiStepLR3. CosineAnnealingLR 一、什么是调整学习率&#xff1f; 调整学习率&#xff08;Adjusting Learning Rate&#xff09;是在机器学习&#xff0c;特别…

Ubuntu20.04中ros2 foxy版本安装gazebo,并运行小车运动demo

这里默认你安装好了ros2 foxy版本 sudo apt install gazebo11sudo apt install ros-foxy-gazebo-ros-pkgs建议把其他的包也安装了 sudo apt install ros-foxy-gazebo-*安装速度的话&#xff0c;比安装ros环境快多了。 此时&#xff0c;可以在/opt/ros/foxy/share目录下看到若…

2024最新国内镜像源设置(npm、yarn、pnpm)

淘宝镜像源https://registry.npmmirror.com/ 腾讯云镜像源https://mirrors.cloud.tencent.com/npm/ cnpm是一个基于npm的中国镜像源https://r.cnpmjs.org/ # 查询当前使用的镜像源 npm get registry# 设置为淘宝镜像源 npm config set registry https://registry.npmmirror.co…

MRC接收机

MRC&#xff08;Maximum Ratio Combining&#xff0c;最大比联合&#xff09;接收机是一种无线通信接收技术&#xff0c;主要用于提高接收机的性能。以下是对MRC接收机的详细解析&#xff1a; 一、技术原理 MRC技术会同时接收来自多个天线的无线信号&#xff0c;然后将这些信…