Linux模型01 - Kobject驱动模型(图文结合 + 详细的demo)

2024-05-03 17:58

本文主要是介绍Linux模型01 - Kobject驱动模型(图文结合 + 详细的demo),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、概述

最初,kobject在内核中,只负责管理对象的引用计数;然而后来历史变迁,kobject的责任逐渐加重。

如今,它还是一种关系纽带,负责将设备模型及对应的sysfs接口关联在一起。

而且,kobject们对自己并不感兴趣;它们通常嵌入到其他结构中 — 代码真正感兴趣的数据资源中(C语言虽然不能直接使用继承,但“结构体嵌入技术”很优秀),监视这些内容。

kobject在内核中实现管理功能有对应的kobject驱动模型,理解它首先需要了解几个相关的数据结构(kobject,ktype和kset)。

二、主要结构和关系

kobject

kobject是struct kobject类型的对象。

实际上,创建kobject的代码不知道何时释放kobject(引入sysfs后,即使是可预测的对象生命周期也将会很复杂;比如:用户空间程序可以在任意一段时间内保持对kobject的引用【通过保持打开其关联的任何sysfs文件】);如果事先知道何时释放kobject的话,那么最初使用kobject的意义何在?

还有一点很重要,每一个kobject必须对应一个释放它的函数,该函数必须始终保持在恒定的状态等待被调用(如果不是这样的话,代码就会有缺陷)。

kobject的释放函数没有存贮在kobject本身中,而是关联在ktype中(不得不说这个设计也很优秀)。

struct kobject相关代码示例
struct kref {atomic_t refcount;
};struct kobject {const char		*name; //名字struct list_head	entry; //用于kset容器关联同类kobjectstruct kobject		*parent; //父指针,用于构建kobject们的层级关系struct kset		*kset; //指向同类kobject所属的kset容器struct kobj_type	*ktype; //表征特定属性struct sysfs_dirent	*sd; //用于sysfs虚拟文件系统中的惯用方式struct kref		kref; //引用计数unsigned int state_initialized:1;unsigned int state_in_sysfs:1;unsigned int state_add_uevent_sent:1;unsigned int state_remove_uevent_sent:1;unsigned int uevent_suppress:1;
};
ktype

ktype是与kobject关联的类型。ktype表征kobject在sysfs中的默认属性;在kobject创建和销毁时,由ktype决策如何处理kobject。

而创建kobject的代码并不能直接控制引用计数,所以当kobject的引用消失时,应该异步通知一下,以完成对kobject的释放。该通知,由关联在ktype中的release()接口来完成,其形式一般如下:

void my_object_release(struct kobject *kobj)
{/* * 0. 通过container_of(),找到指针kobj指向的,结构体类型为struct my_object的,成员名称为kobj的,所对应的结构体的首地址mine*/struct my_object *mine = container_of(kobj, struct my_object, kobj);/* * 1. 执行对该对象的所有清除、释放操作*///略/** 2. 接着,释放该对象占有的内存空间*/kfree (mine);
}
struct kobj_type相关代码示例
struct kobj_type {void (*release)(struct kobject *); //该类kobject的释放接口函数指针struct sysfs_ops	*sysfs_ops;struct attribute	**default_attrs;
};
kset

kset是kobject集合的基本容器,用来关联容纳一组嵌入在相同结构类型中的kobject;

虽然kset看起来和ktype有几分相似,但二者有一些功能上的差别的:

  • ktype关注对应对象的类型
  • kset 侧重对应对象的聚集

两种不同的理念使同类型的对象可以出现在不同的组中。

kset有以下三种功能:
  • 收容一组同类对象。如:可被内核用来追踪“所有的块设备”或者“所有的PCI设备驱动”
  • 目录级别纽带,把设备模型(和sysfs)关联在一起。每个kset包含一个kobject,可以把它设置为其他kobject的父对象,以这样的方式来建立设备模型的层次结构。
  • kset支持kobject的“热插拔”,并且对如何向用户上报热插拔有影响。
struct kset相关结构代码示例
struct kset {struct list_head list; //属于这个kset的kobject们的链表spinlock_t list_lock;struct kobject kobj; //嵌入到该kset的kobject(递归,是不是有点意思?)const struct kset_uevent_ops *uevent_ops; //处理kobject的请求
};
kset和kobject经典关系图

kset-sm

注意:
  • 在实际中,所有图中的kobject都嵌入在其他的数据类中(甚至可能是其他的kset中)。
  • Linux内核的特殊性,kobject的父对象不一定是包含这个kobject的kset(虽然当前的图片上是的)。

三、使用

0. kobject中对应的ktype和kset的设置
设置ktype
  • 指向ktype的指针可以在kobject初始化时放在kobject的ktype字段中;
  • 当kobject包含的ktype指针为NULL时,则由kobject的包含kset的字段定义。
设置kset(接口类似kobject)
/*** 功能:动态创建一个kset,并添加到sysfs中* 参数:@name: kset的名称@uevent_ops: 属于kset的一个struct kset_uevent_ops@parent_kobj: kset的父对象指针(如果存在的话)* 返回值:创建kset失败,返回NULL* 注意:1. 使用kset_unregister() 将会在不使用kset后动态释放kset。*/
struct kset *kset_create_and_add(const char *name,const struct kset_uevent_ops *uevent_ops,struct kobject *parent_kobj);
1. 动态创建kobject并添加到sysfs中
/*
* 功能:动态创建一个struct kobject, 并注册添加到sysfs中;
* 注意:调用kobject_put()后,该kobject将会在不再使用后自动释放。
* 参数:
* @name: kobject的名子
* @parent: kobject的父对象指针(如果存在的话)
*
*/
struct kobject *kobject_create_and_add(const char *name, struct kobject *parent)
2. 在虚拟文件系统中创建文件
/*
* 功能:在sysfs中创建和kobject相关的文件
*/
int sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp)
拓展补充:
kobject静态初始化和添加(无需sysfs_create_group接口)
/*** 功能:初始化一个kobject并添加它到一个kobject层次关系中* 参数:* @kobj: 指向已经存在的kobject的指针* @ktype: 指向属于该kobject的ktype的ktype指针* @parent: 该kobject的父对象指针* @fmt: kobject的格式化输入名称(类似sprintf(fmt, args...))** 注意:1. 该函数等价于调用 kobject_init() 和 kobject_add(). 2. kobject_add()创建sysfs的入口(显示在/sys目录体系下)3. 从sysfs中移除对应的kobject, 使用 kobject_del()*/
int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype,struct kobject *parent, const char *fmt, ...);
kobject的名称或者和重新设置
//访问kobject名称的正确方法:
const char *kobject_name(const struct kobject * kobj);
//如果你需要修改kobject的名称:
int kobject_rename(struct kobject *kobj, const char *new_name);
kobject的引用计数接口(kset的引用计数接口类似)

kobject的主要职责之一就是对嵌入对象的引用计数,以下是基础的引用计数操作接口:

/* 功能: 增加引用计数。
* 成功:返回 kobject 指针;
* 失败:返回 NULL
*/
struct kobject *kobject_get(struct kobject *kobj);/* 功能: 减少引用计数。
* 1. 当引用需要被释放的时候,就需要调用 kobject_put() 接口。
* 2. 注意:
*    kobject_init()接口增加引用计数为1;
*    所以最后需要调用 kobject_put() 来使得引用计数变为0, kobject才能得以释放
*/
void kobject_put(struct kobject *kobj);

四、使用示例

见内核代码树(或者参考附录):
  • samples/kobject/kobject-example.c
  • samples/kobject/kset-example.c
kobject-example.c 的简单版,译如下:

该例中无ktype的用法,ktype的用法可参考kset-example.c

/** 简单实现kobject驱动模型** Copyright (C) 2004-2007 Greg Kroah-Hartman <greg@kroah.com>* Copyright (C) 2007 Novell Inc.** 当且仅当发布在GPL2下**/
#include <linux/kobject.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include <linux/module.h>
#include <linux/init.h>/** 该驱动模块展示:1. 如何在sysfs中创建一个简单的子目录。2. 在/sys/kernel/kobject-example目录中将会创建一个文件:"foo". 3. 如果向文件写入一些整数,可在写入片刻后可读出。*/static int foo;//文件的"读"接口实现
static ssize_t foo_show(struct kobject *kobj, struct kobj_attribute *attr,char *buf)
{return sprintf(buf, "%d\n", foo);
}//文件的"写"接口实现
static ssize_t foo_store(struct kobject *kobj, struct kobj_attribute *attr,const char *buf, size_t count)
{sscanf(buf, "%du", &foo);return count;
}//文件的属性:读写权限、读写接口的指定
static struct kobj_attribute foo_attribute =__ATTR(foo, 0666, foo_show, foo_store);/** 创建一组属性,以便一次性操作一组属性*/
static struct attribute *attrs[] = {&foo_attribute.attr,NULL,	/* NULL作为结束标志,不可或缺 */
};/** attribute_group没有指定名称的话,所有的属性会全部直接放在kobject目录中;* 指定了名字,就会生成对应的属性子目录,用来容纳相关的属性文件。*/
static struct attribute_group attr_group = {.attrs = attrs,
};static struct kobject *example_kobj;static int __init example_init(void)
{int retval;/** 在/sys/kernel/目录下创建一个简单的kobject对象(目录),名称为"kobject_example",** 因为这是个简单的目录,所以没有uevent发送到用户空间。* 这正是这个函数的局限性(该接口不能用于创建不需要名称和编号的动态kobject)*/example_kobj = kobject_create_and_add("kobject_example", kernel_kobj);if (!example_kobj)return -ENOMEM;/* 创建关联kobject的文件*/retval = sysfs_create_group(example_kobj, &attr_group);if (retval)kobject_put(example_kobj);return retval;
}static void __exit example_exit(void)
{kobject_put(example_kobj);
}module_init(example_init);
module_exit(example_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>");

五、参考附录

网页

1. Documentation/kobject.txt [Posted January 30, 2008 by corbet]

2. The zen of kobjects [Posted October 1, 2003 by corbet]

3. The Linux Kernel documentation [latest]

文件

1. samples\kobject\kobject-example.c

2. samples\kobject\kset-example.c

六、注意:

  • 不足之处还望指正,多多留言
  • 如需转载,请注明出处,谢谢~

这篇关于Linux模型01 - Kobject驱动模型(图文结合 + 详细的demo)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/957322

相关文章

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

linux-基础知识3

打包和压缩 zip 安装zip软件包 yum -y install zip unzip 压缩打包命令: zip -q -r -d -u 压缩包文件名 目录和文件名列表 -q:不显示命令执行过程-r:递归处理,打包各级子目录和文件-u:把文件增加/替换到压缩包中-d:从压缩包中删除指定的文件 解压:unzip 压缩包名 打包文件 把压缩包从服务器下载到本地 把压缩包上传到服务器(zip

Andrej Karpathy最新采访:认知核心模型10亿参数就够了,AI会打破教育不公的僵局

夕小瑶科技说 原创  作者 | 海野 AI圈子的红人,AI大神Andrej Karpathy,曾是OpenAI联合创始人之一,特斯拉AI总监。上一次的动态是官宣创办一家名为 Eureka Labs 的人工智能+教育公司 ,宣布将长期致力于AI原生教育。 近日,Andrej Karpathy接受了No Priors(投资博客)的采访,与硅谷知名投资人 Sara Guo 和 Elad G

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

Retrieval-based-Voice-Conversion-WebUI模型构建指南

一、模型介绍 Retrieval-based-Voice-Conversion-WebUI(简称 RVC)模型是一个基于 VITS(Variational Inference with adversarial learning for end-to-end Text-to-Speech)的简单易用的语音转换框架。 具有以下特点 简单易用:RVC 模型通过简单易用的网页界面,使得用户无需深入了

hdu 2602 and poj 3624(01背包)

01背包的模板题。 hdu2602代码: #include<stdio.h>#include<string.h>const int MaxN = 1001;int max(int a, int b){return a > b ? a : b;}int w[MaxN];int v[MaxN];int dp[MaxN];int main(){int T;int N, V;s

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

图神经网络模型介绍(1)

我们将图神经网络分为基于谱域的模型和基于空域的模型,并按照发展顺序详解每个类别中的重要模型。 1.1基于谱域的图神经网络         谱域上的图卷积在图学习迈向深度学习的发展历程中起到了关键的作用。本节主要介绍三个具有代表性的谱域图神经网络:谱图卷积网络、切比雪夫网络和图卷积网络。 (1)谱图卷积网络 卷积定理:函数卷积的傅里叶变换是函数傅里叶变换的乘积,即F{f*g}