自学内容网 自学内容网

RK3568驱动指南|第十篇 热插拔-第115章 完善kset_uevent_ops结构体实验

瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工智能应用。RK3568 支持安卓 11 和 linux 系统,主要面向物联网网关、NVR 存储、工控平板、工业检测、工控盒、卡拉 OK、云终端、车载中控等行业。


【公众号】迅为电子

【粉丝群】824412014(加群获取驱动文档+例程)

【视频观看】嵌入式学习之Linux驱动(第十期_热插拔_全新升级)_基于RK3568

【购买链接】迅为RK3568开发板瑞芯微Linux安卓鸿蒙ARM核心板人工智能AI主板


第115章 完善kset_uevent_ops结构体实验

在前面的章节中,我们了解了Linux内核是如何发送uevent事件到用户空间的。通过分析代码,我们知道在内核中,通过kset数据结构来组织kobject,并通过kset_uevent_ops结构体来定义uevent事件的处理函数。这些函数可以在接收到特定事件时执行自定义的操作。

为了完善这个机制,我们需要对kset_uevent_ops结构体进行实验和定制。通过填充这个结构体中的字段,我们可以定义自己的事件处理函数,从而响应特定的事件。让我们开始做实验吧!

115.1实验程序的编写

115.1.1 驱动程序编写

本实验对应的网盘路径为:iTOP-RK3568开发板【底板V1.7版本】\03_【iTOP-RK3568开发板】指南教程\02_Linux驱动配套资料\04_Linux驱动例程\79_uevent_ops\module

我们编写驱动程序,首先,需要创建一个自定义的kset对象,并将其与相应的kobject关联起来。然后,我们可以定义一个包含所需事件处理逻辑的函数,并将其赋值给uevent字段,这样当事件发生时,内核就会调用我们定义的处理函数。在处理函数中,可以根据特定的事件类型执行我们想要的操作,例如读取设备信息、处理设备状态变化等。我们还可以使用add_uevent_var函数向uevent环境中添加自定义的键值对,以提供额外的信息给用户空间。通过这种方式,我们可以定制内核中的uevent事件处理机制,使其适应特定需求。这种定制化的事件处理机制可以用于各种场景,例如设备驱动程序、模块加载和卸载等。

总结起来,通过实验和完善`kset_uevent_ops`结构体,我们可以扩展内核的uevent事件处理能力,使其更加灵活和适应各种应用场景。这为我们提供了在内核和用户空间之间进行通信和交互的强大工具。编写完成的uevent_ops.c代码如下所示:

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

struct kobject *mykobject01;
struct kobject *mykobject02;
struct kset *mykset;
struct kobj_type mytype;

// 定义一个回调函数,返回kset的名称
const char *myname(struct kset *kset, struct kobject *kobj)
{
    return "my_kset";
};

// 定义一个回调函数,处理kset的uevent事件
int myevent(struct kset *kset, struct kobject *kobj, struct kobj_uevent_env *env)
{
    add_uevent_var(env, "MYDEVICE=%s", "TOPEET");
    return 0;
};

// 定义一个回调函数,用于过滤kset中的kobject
int myfilter(struct kset *kset, struct kobject *kobj)
{
    if (strcmp(kobj->name, "mykobject01") == 0){
        return 0; // 返回0表示通过过滤
    }else{
        return 1; // 返回1表示过滤掉
    }
};

struct kset_uevent_ops my_uevent_ops = {
    .filter = myfilter,
    .uevent = myevent,
    .name = myname,
};

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

    // 创建并添加一个kset
    mykset = kset_create_and_add("mykset", &my_uevent_ops, NULL);

    // 分配并初始化一个kobject
    mykobject01 = kzalloc(sizeof(struct kobject), GFP_KERNEL);
    mykobject01->kset = mykset;

    // 初始化并添加kobject到kset
    ret = kobject_init_and_add(mykobject01, &mytype, NULL, "%s", "mykobject01");

    // 分配并初始化一个kobject
    mykobject02 = kzalloc(sizeof(struct kobject), GFP_KERNEL);
    mykobject02->kset = mykset;

    // 初始化并添加kobject到kset
    ret = kobject_init_and_add(mykobject02, &mytype, NULL, "%s", "mykobject02");

    // 触发一个uevent事件,表示mykobject01的属性发生了变化
    ret = kobject_uevent(mykobject01, KOBJ_CHANGE);
    // 触发一个uevent事件,表示mykobject02被添加
    ret = kobject_uevent(mykobject02, KOBJ_ADD);

    return 0;
}

// 模块退出函数
static void mykobj_exit(void)
{
    // 释放kobject
    kobject_put(mykobject01);
    kobject_put(mykobject02);
    kset_unregister(mykset);
}

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

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

115.2 运行测试

115.2.1 编译驱动程序

在上一小节中的uevent_ops.c代码同一目录下创建 Makefile 文件,Makefile 文件内容如下所示:

export ARCH=arm64#设置平台架构
export CROSS_COMPILE=aarch64-linux-gnu-#交叉编译器前缀
obj-m +=uevent_ops.o    #此处要和你的驱动源文件同名
KDIR :=/home/topeet/Linux/linux_sdk/kernel    #这里是你的内核目录                                                                                                                            
PWD ?= $(shell pwd)
all:
    make -C $(KDIR) M=$(PWD) modules    #make操作
clean:
    make -C $(KDIR) M=$(PWD) clean    #make clean操作

对于Makefile的内容注释已在上图添加,保存退出之后,来到存放uevent_ops.c和Makefile文件目录下,如下图(图115-1)所示:

图 115-1

然后使用命令“make”进行驱动的编译,编译完成如下图(图115-2)所示:

图 115-2

编译完生成uevent_ops.ko目标文件,如下图(图115-3)所示:

图 115-3

至此驱动模块就编译成功了,接下来进行测试。

115.2.2 运行测试

开发板启动之后,使用命令“udevadm monitor &”监视和显示当前系统中的uevent事件。然后使用以下命令进行驱动模块的加载,如下图(图115-4)所示:

insmod uevent_ops.ko

图 115-4 

图115-5

驱动加载之后,如上图所示udev接收到add动作,说明uevent事件已经发送成功了。

/mykset/mykobject02 是kobject在根目录/sys/下的路径。

最后可以使用以下命令进行驱动的卸载,如下图(图115-6)所示:

  rmmod uevent_ops

图 115-6

至此,完善kset_uevent_ops实验就完成了。



原文地址:https://blog.csdn.net/BeiJingXunWei/article/details/135505440

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!