Skip to content

LV065-ktype简介

一、ktype 简介

1. kobj_type 是什么

每个 kobject 对象都有一些属性,这些属性由 kobj_type 表示。kobj_type 就是用于表征 kobject 的的一些属性,指定了删除 kobject 时要调用的函数,kobject 结构体中有 struct kref 字段用于对 kobject 进行引用计数,当计数值为 0 时,就会调用 kobj_type 中的 release 函数对 kobject 进行释放,这个就有点类似于 C++中的智能指针了;它还指定了通过 sysfs 显示或修改有关 kobject 的信息时要处理的操作,实际是调用 show/store 函数。

kobj_type 定义在 struct kobj_type 中:

c
struct kobj_type {
	void (*release)(struct kobject *kobj);
	const struct sysfs_ops *sysfs_ops;
	struct attribute **default_attrs;
	const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);
	const void *(*namespace)(struct kobject *kobj);
	void (*get_ownership)(struct kobject *kobj, kuid_t *uid, kgid_t *gid);
};
  • release:通过该回调函数,可以将包含该类型 kobject 的数据结构的内存空间释放掉。
  • sysfs_ops:struct sysfs_ops 类型,该种类型的 kobject 的 sysfs 文件系统接口(读属性接口 show 及写属性接口 store)。
  • default_attrs:struct attribute 类型,该种类型的 kobject 的 atrribute 列表(所谓 attribute,就是 sysfs 文件系统中的一个文件)。将会在 kobject 添加到内核时,一并注册到 sysfs 中。
  • child_ns_type/namespace:和文件系统(sysfs)的命名空间有关,这里不再详细说明。

2. ktype 与 kobject 的关系

image-20250105200924853
  • kobject 在创建的时候,默认设置 kobj_type 的值为 dynamic_kobj_ktype(在 kobject_create() 函数中设置的),通常 kobject 会嵌入在其他结构中来使用,因此它的初始化跟特定的结构相关,典型的比如 struct device 和 struct device_driver ;
  • 在 /sys 文件系统中,通过 echo/cat 的操作,最终会调用到 show/store 函数,而这两个函数的具体实现可以放置到驱动程序中;

二、ktype demo

1. demo 源码

可以看这里:05_device_model/05_ktype

c
#include <linux/init.h> /* module_init module_exit */
#include <linux/kernel.h>
#include <linux/module.h> /* MODULE_LICENSE */

#include <linux/kobject.h>
#include <linux/slab.h>

#include "./timestamp_autogenerated.h"
#include "./version_autogenerated.h"
#include "./sdrv_common.h"

// #undef PRT
// #undef PRTE
#ifndef PRT
#define PRT printk
#endif
#ifndef PRTE
#define PRTE printk
#endif

struct kobject *skobject1 = NULL; // 定义 kobject 指针变量:skobject1

/**
 * @brief  dynamic_kobj_release()
 * @note   定义 kobject 的释放函数
 * @param [in]
 * @param [out]
 * @retval 
 */
static void dynamic_kobj_release(struct kobject *kobj)
{
    PRT("kobject: %p\n", kobj);
    kfree(kobj);
}

// 定义了一个 kobj_type 结构体变量 stype,用于描述 kobject 的类型。
struct kobj_type stype = {
    .release = dynamic_kobj_release,
};

/**
 * @brief  sdriver_demo_init()
 * @note   
 * @param [in]
 * @param [out]
 * @retval 
 */
static __init int sdriver_demo_init(void)
{
    int ret = 0;
	printk("*** [%s:%d]Build Time: %s %s, git version:%s ***\n", __FUNCTION__,
           __LINE__, KERNEL_KO_DATE, KERNEL_KO_TIME, KERNEL_KO_VERSION);
    PRT("sdriver_demo module init!\n");
    

    // 创建 kobject 的第二种方法
    // 1.使用 kzalloc 函数分配了一个 kobject 对象的内存
    skobject1 = kzalloc(sizeof(struct kobject), GFP_KERNEL);
    // 2.初始化并添加到内核中,名为 "skobject1"。
    ret = kobject_init_and_add(skobject1, &stype, NULL, "%s", "skobject1");
    if(ret < 0)
    {
        PRTE("kobject_init_and_add fail!ret=%d\n", ret);
        goto err_kobject_init_and_add;
    }
    return 0;

err_kobject_init_and_add:
	return ret;
}

/**
 * @brief  sdriver_demo_exit()
 * @note   
 * @param [in]
 * @param [out]
 * @retval 
 */
static __exit void sdriver_demo_exit(void)
{
	
	// 释放之前创建的 kobject 对象
    kobject_put(skobject1);
    PRT("sdriver_demo module exit!\n");
}


module_init(sdriver_demo_init); // 将__init 定义的函数指定为驱动的入口函数
module_exit(sdriver_demo_exit); // 将__exit 定义的函数指定为驱动的出口函数

/* 模块信息(通过 modinfo chrdev_led_demo 查看) */
MODULE_LICENSE("GPL v2");            /* 源码的许可证协议 */
MODULE_AUTHOR("sumu");               /* 字符串常量内容为模块作者说明 */
MODULE_DESCRIPTION("Description");   /* 字符串常量内容为模块功能说明 */
MODULE_ALIAS("module's other name"); /* 字符串常量内容为模块别名 */

3.2 开发板验证

我们拷贝到开发板,然后加载驱动,卸载驱动,这个实验主要是通过 ktype 自定义了 kobject 对象释放的时候的回调函数:

image-20250105224309104

可以看到,当释放的时候,会出现我们的自定义打印信息。

参考资料

【1】linux 驱动开发—— 6、linux 设备驱动模型_什么是 kobject-CSDN 博客

【2】Linux 设备模型剖析系列一(基本概念、kobject、kset、kobj_type)_device 下的 kobj-CSDN 博客

【3】Linux 设备模型(1)_基本概念

【4】一张图掌握 Linux platform 平台设备驱动框架!【建议收藏】-CSDN 博客

【5】关于 kobjects、ksets 和 ktypes 的一切你没想过需要了解的东西 — The Linux Kernel documentation

【6】【原创】linux 设备模型之 kset/kobj/ktype 分析 - LoyenWang - 博客园

【7】kobject / kset / ktype(linux kernel 中的面向对象) - 知乎