设备模型基本框架-kobject-kset

设备模型 开篇,先理解基本框架kobject和kset


前言

这里是kobject/kset 基础知识了解,也是设备模型开篇。设备模型可以让大家更好理解前面学习的知识,也可以为后面知识点做铺垫。

参考资料

迅为_RK3568_设备模型

一、Linux设备模型基本框架

Linux设备模型是内核提供的一个抽象层,用于描述系统中设备的层次结构和相互关系。其核心目的是:

  • 统一设备表示和管理
  • 支持设备的热插拔
  • 提供用户空间接口(sysfs)
  • 实现电源管理
  • 支持设备驱动自动加载

设备模型的核心数据结构包括:

  • kobject:基础对象,提供引用计数和sysfs接口
  • kset:kobject的集合
  • ktype:定义kobject的类型行为
  • device:表示具体设备
  • device_driver:表示设备驱动
  • bus_type:表示总线类型
  • class:设备分类

二、kobject详解

kobject 创建

kobject是设备模型中最基础的结构体,定义在<linux/kobject.h>中:

struct kobject {
    const char      *name;          // 对象名称(sysfs中显示)
    struct list_head entry;         // 链表节点
    struct kobject   *parent;       // 父对象
    struct kset      *kset;         // 所属的kset
    struct kobj_type *ktype;        // 对象类型
    struct kernfs_node *sd;         // sysfs目录项
    struct kref      kref;          // 引用计数
    unsigned int state_initialized:1; // 初始化状态
};

看看代码示例:

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

// 定义了三个kobject指针变量:mykobject01、mykobject02、mykobject03
struct kobject *mykobject01;
struct kobject *mykobject02;
struct kobject *mykobject03;

// 定义了一个kobj_type结构体变量mytype,用于描述kobject的类型。
struct kobj_type mytype;
// 模块的初始化函数
static int mykobj_init(void)
{
    int ret;
    // 创建kobject的第一种方法
    // 创建并添加了名为"mykobject01"的kobject对象,父kobject为NULL
    mykobject01 = kobject_create_and_add("mykobject01", NULL);
    // 创建并添加了名为"mykobject02"的kobject对象,父kobject为mykobject01。
    mykobject02 = kobject_create_and_add("mykobject02", mykobject01);

    // 创建kobject的第二种方法
    // 1 使用kzalloc函数分配了一个kobject对象的内存
    mykobject03 = kzalloc(sizeof(struct kobject), GFP_KERNEL);
    // 2 初始化并添加到内核中,名为"mykobject03"。
    ret = kobject_init_and_add(mykobject03, &mytype, NULL, "%s", "mykobject03");

    return 0;
}

// 模块退出函数
static void mykobj_exit(void)
{
    // 释放了之前创建的kobject对象
    kobject_put(mykobject01);
    kobject_put(mykobject02);
    kobject_put(mykobject03);
}

module_init(mykobj_init); // 指定模块的初始化函数
module_exit(mykobj_exit); // 指定模块的退出函数

MODULE_LICENSE("GPL");   // 模块使用的许可证
MODULE_AUTHOR("fangchen"); // 模块的作者

kobject 创建方法

在Linux内核中,kobject_create_and_add和kobject_init_and_add都是用于创建和注册kobject的API,但它们的用途和实现方式有显著区别。以下是两者的对比分析:

kobject_create_and_add 方法

功能

  • 自动分配内存:动态创建一个kobject对象(包括内存分配),并直接将其添加到内核对象层次结构中。
  • 简化流程:适用于不需要自定义kobject初始化的场景,由内核自动完成内存管理和基本初始化。

原型

struct kobject *kobject_create_and_add(const char *name, struct kobject *parent);

特点

  • 内存管理:内部调用kzalloc分配内存,返回的kobject指针由调用者通过kobject_put()释放。
  • 默认初始化:自动设置引用计数(kref_init)、初始化链表、设置默认属性(sysfs_ops)等。
  • 典型用途:快速创建简单的kobject,例如在模块中暴露一个顶层目录或子目录。

示例

struct kobject *kobj = kobject_create_and_add("my_kobj", NULL);
if (!kobj) {
    // 错误处理
}
// 使用后需释放
kobject_put(kobj);

kobject_init_and_add 方法

功能

  • 手动管理内存:对已分配的kobject(通常是嵌入在更大结构体中的成员)进行初始化并注册。
  • 灵活控制:允许调用者完全控制kobject的内存来源和部分初始化参数。

原型

int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype, 
                         struct kobject *parent, const char *fmt, ...);

特点

  • 内存由调用者提供:kobj必须指向已分配的内存(通常是静态变量或嵌入在其他结构体中)。
  • 需指定kobj_type:必须提供ktype参数,定义该kobject的行为(如释放函数、属性操作等)。
  • 典型用途:需要将kobject嵌入到自定义结构体时(如设备驱动中的私有数据)。

示例

struct my_struct {
    struct kobject kobj;
    int data;
};
struct my_struct *obj = kzalloc(sizeof(*obj), GFP_KERNEL);
if (!obj) {
    // 错误处理
}
// 初始化并注册
int ret = kobject_init_and_add(&obj->kobj, &my_ktype, NULL, "my_kobj");
if (ret) {
    kfree(obj);
    // 错误处理
}
// 释放时需通过ktype中的release函数处理
kobject_put(&obj->kobj);

关键区别kobject_create_and_add - kobject_init_and_add

特性kobject_create_and_addkobject_init_and_add
内存分配内部动态分配由调用者预先分配
初始化控制自动完成基础初始化需手动指定kobj_type等参数
适用场景独立kobjectkobject嵌入到其他结构体中
释放方式直接kobject_put()通过ktype->release回调释放外层结构
灵活性较低较高

如何选择kobject_create_and_add - kobject_init_and_add

  • 优先kobject_init_and_add:当kobject是自定义结构体的一部分时(常见于设备驱动)。
  • 使用kobject_create_and_add:当仅需一个独立的kobject且无需复杂控制时(例如创建简单sysfs节点)。

kobject的主要功能

  • 引用计数:通过kref实现,确保对象不再使用时被释放
  • sysfs表示:每个kobject对应sysfs中的一个目录
  • 父子关系:构建设备层次结构
  • 对象关联:通过kset组织相关对象

三、kset详解

kset 是一组 kobject 的集合,提供了:

  • 包含多个 kobject 的容器
  • 在 sysfs 中作为目录出现
  • 管理 kobject 的生命周期

kset的创建

kset是kobject的集合,本身也是一个kobject:

struct kset {
    struct list_head list;       // 包含的kobject链表
    spinlock_t list_lock;        // 保护链表的锁
    struct kobject kobj;         // 内嵌的kobject
    const struct kset_uevent_ops *uevent_ops; // 热插拔操作集
};

创建kset的示例:

struct kset *my_kset;

my_kset = kset_create_and_add("my_kset", NULL, NULL);
if (!my_kset) {
    return -ENOMEM;
}

kset的主要功能

  • 集合管理:将相关的kobject组织在一起
  • uevent支持:处理热插拔事件
  • 引用计数:通过内嵌的kobject实现
  • sysfs表示:作为父目录包含成员kobject

创建kobject并加入kset

static struct kobject *mykobj;
static struct kset *mykset;

static int __init my_init(void)
{
    // 创建kset
    mykset = kset_create_and_add("mykset", NULL, NULL);
    if (!mykset)
        return -ENOMEM;
    
    // 创建kobject并加入kset
    mykobj = kzalloc(sizeof(*mykobj), GFP_KERNEL);
    if (!mykobj) {
        kset_unregister(mykset);
        return -ENOMEM;
    }
    
    kobject_init(mykobj, &my_ktype);
    mykobj->kset = mykset;
    
    int ret = kobject_add(mykobj, NULL, "mykobj");
    if (ret) {
        kobject_put(mykobj);
        kset_unregister(mykset);
        return ret;
    }
    
    return 0;
}

四、 kobject与kset的区别-联系-小结

区别

特性kobjectkset
本质基础对象kobject的集合
功能提供基本对象特性管理一组相关kobject
sysfs表示对应一个目录对应一个目录,包含成员kobject
主要用途构建设备模型的基础元素组织和管理相关kobject
引用计数直接管理通过内嵌kobject管理

联系

  • 包含关系:kset内嵌了一个kobject,因此kset也是一种特殊的kobject
  • 层次结构:kset可以作为kobject的父对象
  • 协同工作:kobject通常属于某个kset,kset管理一组相关的kobject
  • 共用机制:都使用ktype定义对象类型行为

小结
Linux设备模型通过kobject和kset构建了一个灵活的层次结构:

  • kobject是基础构建块,提供核心功能
  • kset组织相关kobject,便于管理和事件处理
  • 两者协同工作,形成了设备模型的骨架
  • 上层结构(device, driver, bus, class)都基于此构建

理解kobject和kset的关系是掌握Linux设备模型的关键,它们共同实现了设备在sysfs中的表示、引用计数管理、热插拔支持等核心功能。

五、创建kobject 和 keyset 示例

keyobjet 示例及分析

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

// 定义了三个kobject指针变量:mykobject01、mykobject02、mykobject03
struct kobject *mykobject01;
struct kobject *mykobject02;
struct kobject *mykobject03;

// 定义了一个kobj_type结构体变量mytype,用于描述kobject的类型。
struct kobj_type mytype;
// 模块的初始化函数
static int mykobj_init(void)
{
    int ret;
    // 创建kobject的第一种方法
    // 创建并添加了名为"mykobject01"的kobject对象,父kobject为NULL
    mykobject01 = kobject_create_and_add("mykobject01", NULL);
    // 创建并添加了名为"mykobject02"的kobject对象,父kobject为mykobject01。
    mykobject02 = kobject_create_and_add("mykobject02", mykobject01);

    // 创建kobject的第二种方法
    // 1 使用kzalloc函数分配了一个kobject对象的内存
    mykobject03 = kzalloc(sizeof(struct kobject), GFP_KERNEL);
    // 2 初始化并添加到内核中,名为"mykobject03"。
    ret = kobject_init_and_add(mykobject03, &mytype, NULL, "%s", "mykobject03");

    return 0;
}

// 模块退出函数
static void mykobj_exit(void)
{
    // 释放了之前创建的kobject对象
    kobject_put(mykobject01);
    kobject_put(mykobject02);
    kobject_put(mykobject03);
}

module_init(mykobj_init); // 指定模块的初始化函数
module_exit(mykobj_exit); // 指定模块的退出函数

MODULE_LICENSE("GPL");   // 模块使用的许可证
MODULE_AUTHOR("fangchen"); // 模块的作者

在这里插入图片描述

kset 示例及分析

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

// 定义kobject结构体指针,用于表示第一个自定义内核对象
struct kobject *mykobject01;
// 定义kobject结构体指针,用于表示第二个自定义内核对象
struct kobject *mykobject02;
// 定义kset结构体指针,用于表示自定义内核对象的集合
struct kset *mykset;
// 定义kobj_type结构体,用于定义自定义内核对象的类型
struct kobj_type mytype;

// 模块的初始化函数
static int mykobj_init(void)
{
    int ret;

    // 创建并添加kset,名称为"mykset",父kobject为NULL,属性为NULL
    mykset = kset_create_and_add("mykset", NULL, NULL);

    // 为mykobject01分配内存空间,大小为struct kobject的大小,标志为GFP_KERNEL
    mykobject01 = kzalloc(sizeof(struct kobject), GFP_KERNEL);
    // 将mykset设置为mykobject01的kset属性
    mykobject01->kset = mykset;
    // 初始化并添加mykobject01,类型为mytype,父kobject为NULL,格式化字符串为"mykobject01"
    ret = kobject_init_and_add(mykobject01, &mytype, NULL, "%s", "mykobject01");

    // 为mykobject02分配内存空间,大小为struct kobject的大小,标志为GFP_KERNEL
    mykobject02 = kzalloc(sizeof(struct kobject), GFP_KERNEL);
    // 将mykset设置为mykobject02的kset属性
    mykobject02->kset = mykset;
    // 初始化并添加mykobject02,类型为mytype,父kobject为NULL,格式化字符串为"mykobject02"
    ret = kobject_init_and_add(mykobject02, &mytype, NULL, "%s", "mykobject02");

    return 0;
}

// 模块退出函数
static void mykobj_exit(void)
{
    // 释放mykobject01的引用计数
    kobject_put(mykobject01);

    // 释放mykobject02的引用计数
    kobject_put(mykobject02);
}

module_init(mykobj_init); // 指定模块的初始化函数
module_exit(mykobj_exit); // 指定模块的退出函数

MODULE_LICENSE("GPL");     // 模块使用的许可证
MODULE_AUTHOR("fangchen"); // 模块的作者

在这里插入图片描述

API 小结

函数内存分配方式初始化方式sysfs添加适用场景
kobject_create_and_add内部分配内部完成快速创建独立kobject
kobject_init_and_add外部分配需指定ktype自定义分配或静态kobject
kset_create_and_add内部分配内部完成创建kobject集合

函数 kobject_put

函数原型

void kobject_put(struct kobject *kobj);

功能:

  • 减少kobject的引用计数,当计数为0时释放资源

函数 kzalloc

函数原型

void *kzalloc(size_t size, gfp_t flags);

功能

  • 内核空间的内存分配函数,分配后自动清零

实际用法举例:
在这里插入图片描述

总结

了解设备模型基础知识

【四轴飞行器】非线性三自由度四轴飞行器模拟器研究(Matlab代码实现)内容概要:本文围绕非线性三自由度四轴飞行器模拟器的研究展开,重点介绍基于Matlab代码实现的四轴飞行器动力学建模与仿真方法。研究构建了考虑非线性特性的飞行器数学模型,涵盖姿态动力学与运动学方程,实现了三自由度(滚转、俯仰、偏航)的精确模拟。文中详细阐述了系统建模过程、控制算法设计思路及仿真结果分析,帮助读者深入理解四轴飞行器的飞行动力学特性与控制机制;同时,该模拟器可用于算法验证、控制器设计与教学实验。; 适合人群:具备一定自动控制理论基础和Matlab编程能力的高校学生、科研人员及无人机相关领域的工程技术人员,尤其适合从事飞行器建模、控制算法开发的研究生和初级研究人员。; 使用场景及目标:①用于四轴飞行器非线性动力学特性的学习与仿真验证;②作为控制器(如PID、LQR、MPC等)设计与测试的仿真平台;③支持无人机控制系统教学与科研项目开发,提升对姿态控制与系统仿真的理解。; 阅读建议:建议读者结合Matlab代码逐模块分析,重点关注动力学方程的推导与实现方式,动手运行并调试仿真程序,以加深对飞行器姿态控制过程的理解。同时可扩展为六自由度模型或加入外部干扰以增强仿真真实性。
基于分布式模型预测控制DMPC的多智能体点对点过渡轨迹生成研究(Matlab代码实现)内容概要:本文围绕“基于分布式模型预测控制(DMPC)的多智能体点对点过渡轨迹生成研究”展开,重点介绍如何利用DMPC方法实现多智能体系统在复杂环境下的协同轨迹规划与控制。文中结合Matlab代码实现,详细阐述了DMPC的基本原理、数学建模过程以及在多智能体系统中的具体应用,涵盖点对点转移、避障处理、状态约束与通信拓扑等关键技术环节。研究强调算法的分布式特性,提升系统的可扩展性与鲁棒性,适用于多无人机、无人车编队等场景。同时,文档列举了大量相关科研方向与代码资源,展示了DMPC在路径规划、协同控制、电力系统、信号处理等多领域的广泛应用。; 适合人群:具备一定自动化、控制理论或机器人学基础的研究生、科研人员及从事智能系统开发的工程技术人员;熟悉Matlab/Simulink仿真环境,对多智能体协同控制、优化算法有一定兴趣或研究需求的人员。; 使用场景及目标:①用于多智能体系统的轨迹生成与协同控制研究,如无人机集群、无人驾驶车队等;②作为DMPC算法学习与仿真实践的参考资料,帮助理解分布式优化与模型预测控制的结合机制;③支撑科研论文复现、毕业设计或项目开发中的算法验证与性能对比。; 阅读建议:建议读者结合提供的Matlab代码进行实践操作,重点关注DMPC的优化建模、约束处理与信息交互机制;按文档结构逐步学习,同时参考文中提及的路径规划、协同控制等相关案例,加深对分布式控制系统的整体理解。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

野火少年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值