kobject创建文件夹和文件测试。

2023-10-22 15:59

本文主要是介绍kobject创建文件夹和文件测试。,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 kobject创建目录。的本质是通过sysfs创建的。通过kernfs_node *ns来建立关系。

kobject_create_and_add 

最简单方式创建kobject。内部创建对象。参数为名字,如果parent为空,则创建在/sys/目录下。否则为parent的子目录


struct kobject *kobject_create_and_add(const char *name, struct kobject *parent)
{struct kobject *kobj;int retval;kobj = kobject_create(); //kobject_initif (!kobj)return NULL;retval = kobject_add(kobj, parent, "%s", name);if (retval) {pr_warn("%s: kobject_add error: %d\n", __func__, retval);kobject_put(kobj);kobj = NULL;}return kobj;
}

kobject_create:内部自动关联dynamic_kobj_type,有代码可以看出,sysfs_ops的show/store函数会将动态将attribute转换成kobj_attribute。并找到show/store方法运行,方便调用用户的函数。

struct sysfs_ops {ssize_t	(*show)(struct kobject *, struct attribute *, char *);ssize_t	(*store)(struct kobject *, struct attribute *, const char *, size_t);
};

 继续

struct kobject *kobject_create(void)
{struct kobject *kobj;kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);if (!kobj)return NULL;kobject_init(kobj, &dynamic_kobj_ktype);return kobj;
}static struct kobj_type dynamic_kobj_ktype = {.release	= dynamic_kobj_release,.sysfs_ops	= &kobj_sysfs_ops,
};

 继续

结构体:attr后面是show/store函数指针
struct kobj_attribute {struct attribute attr;ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr,char *buf);ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr,const char *buf, size_t count);
};/* default kobject attribute operations */
static ssize_t kobj_attr_show(struct kobject *kobj, struct attribute *attr,char *buf)
{struct kobj_attribute *kattr;ssize_t ret = -EIO;kattr = container_of(attr, struct kobj_attribute, attr);if (kattr->show)ret = kattr->show(kobj, kattr, buf);return ret;
}static ssize_t kobj_attr_store(struct kobject *kobj, struct attribute *attr,const char *buf, size_t count)
{struct kobj_attribute *kattr;ssize_t ret = -EIO;kattr = container_of(attr, struct kobj_attribute, attr);if (kattr->store)ret = kattr->store(kobj, kattr, buf, count);return ret;
}const struct sysfs_ops kobj_sysfs_ops = {.show	= kobj_attr_show,.store	= kobj_attr_store,
};

kobject_init_and_add

方式二:自己创建kobject和kobj_type 等。这种方式给用户自由,比如用户自己定义了attribute结果。那么如果用户需要自定义类似kobj_attribute的结构体就需要自己实现sysfs_os中的show/store函数。


int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype,struct kobject *parent, const char *fmt, ...)
{va_list args;int retval;kobject_init(kobj, ktype);va_start(args, fmt);retval = kobject_add_varg(kobj, parent, fmt, args);va_end(args);return retval;
}

例子:

#include <linux/init.h>
#include <linux/module.h>MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("colorfulshark@hotmail.com");static struct kobject mykobj;//自己创建的show函数,简单实使用没有再调用自己的类attri后面的其他方法。
static ssize_t fw_cfg_sysfs_attr_show(struct kobject *kobj, struct attribute *a,char *buf)
{dump_stack();return sprintf(buf, "fw_cfg_sysfs_attr_show\n");
}//自己创建的sysfs_ops
static const struct sysfs_ops fw_cfg_sysfs_attr_ops = {.show = fw_cfg_sysfs_attr_show,
};//自创建的kobj_type
static struct kobj_type fw_cfg_sysfs_entry_ktype = {// .default_attrs = fw_cfg_sysfs_entry_attrs,.sysfs_ops = &fw_cfg_sysfs_attr_ops,//.release = fw_cfg_sysfs_release_entry,
};static struct kobject *fw_cfg_top_ko;static ssize_t fw_cfg_showrev(struct kobject *k, struct attribute *a, char *buf)
{dump_stack();return sprintf(buf, "hello jaon\n");
}static const struct {struct attribute attr;ssize_t (*show)(struct kobject *k, struct attribute *a, char *buf);
} fw_cfg_rev_attr = {.attr = { .name = "rev", .mode = S_IRUSR },.show = fw_cfg_showrev,
};
static int xxx_init(void)
{      dump_stack();	fw_cfg_top_ko = kobject_create_and_add("test1", NULL);sysfs_create_file(fw_cfg_top_ko, &fw_cfg_rev_attr.attr);       kobject_init_and_add(&mykobj, &fw_cfg_sysfs_entry_ktype,NULL, "subxx1");sysfs_create_file(&mykobj,&fw_cfg_rev_attr.attr); //这里我复用了fw_cfg_rev_attr.attr 这个attribute。当然也可以自定义一个,在show中用container_of 找到自己定义的show函数指针。printk(KERN_ALERT "module xxx init\n");return 0;
}       static void xxx_exit(void)
{       printk(KERN_ALERT "module xxx exit\n");
}       
module_init(xxx_init);
module_exit(xxx_exit);

方式1:

[root@localhost ~]# cat /sys/kernel/kexec_crash_size 
[ 1406.506644] CPU: 4 PID: 1218 Comm: cat Not tainted 4.19.0-fix-full-10+ #18
[ 1406.517365] Hardware name: PHYTIUM LTD D2000/D2000, BIOS  
[ 1406.526003] Call trace:
[ 1406.531549]  dump_backtrace+0x0/0x1b8
[ 1406.538233]  show_stack+0x24/0x30
[ 1406.544511]  dump_stack+0x90/0xb4
[ 1406.550767]  kexec_crash_size_show+0x1c/0x48
[ 1406.557975]  kobj_attr_show+0x14/0x28
[ 1406.564573]  sysfs_kf_seq_show+0x9c/0x138
[ 1406.571518]  kernfs_seq_show+0x44/0x50
[ 1406.578210]  seq_read+0xd4/0x4a8
[ 1406.584379]  kernfs_fop_read+0x16c/0x218
[ 1406.591254]  __vfs_read+0x60/0x188
[ 1406.597612]  vfs_read+0x94/0x150
[ 1406.603770]  ksys_read+0x6c/0xd8
[ 1406.609957]  __arm64_sys_read+0x24/0x30
[ 1406.616751]  el0_svc_handler+0x84/0x140
[ 1406.623552]  el0_svc+0x8/0xc

方式2:

[217963.967082]  show_stack+0x52/0x58
[217963.967086]  dump_stack_lvl+0x4a/0x5f
[217963.967089]  dump_stack+0x10/0x12
[217963.967093]  fw_cfg_sysfs_attr_show+0x13/0x2b [test]  //这里直接调用
[217963.967095]  sysfs_kf_seq_show+0xa1/0x100

[217963.967098]  kernfs_seq_show+0x27/0x30
[217963.967100]  seq_read_iter+0x120/0x4b0
[217963.967117]  ? do_anonymous_page+0x1f5/0x3b0
[217963.967119]  kernfs_fop_read_iter+0x2c/0x30
[217963.967121]  new_sync_read+0x110/0x190
[217963.967124]  vfs_read+0xff/0x1a0
[217963.967126]  ksys_read+0x67/0xe0
[217963.967128]  __x64_sys_read+0x19/0x20
[217963.967129]  do_syscall_64+0x5c/0xc0
[217963.967130]  ? exit_to_user_mode_prepare+0x37/0xb0
[217963.967133]  ? irqentry_exit_to_user_mode+0x9/0x20
[217963.967135]  ? irqentry_exit+0x19/0x30
[217963.967136]  ? exc_page_fault+0x89/0x160
[217963.967138]  ? asm_exc_page_fault+0x8/0x30
[217963.967623]  entry_SYSCALL_64_after_hwframe+0x44/0xae
 

kset_create_and_add

kset结构体:包含一个kobject,也会创建目录,将相同类型的kobject进行关联。

//struct kset - a set of kobjects of a specific type, belonging to a specific subsystem.
struct kset {struct list_head list;  //链表,spinlock_t list_lock;struct kobject kobj; //包含一个完整kobjectconst struct kset_uevent_ops *uevent_ops;
} __randomize_layout;
struct kset *kset_create_and_add(const char *name,const struct kset_uevent_ops *uevent_ops,struct kobject *parent_kobj)
{struct kset *kset;int error;kset = kset_create(name, uevent_ops, parent_kobj);if (!kset)return NULL;error = kset_register(kset);if (error) {kfree(kset);return NULL;}return kset;
}static struct kset *kset_create(const char *name,const struct kset_uevent_ops *uevent_ops,struct kobject *parent_kobj)
{struct kset *kset;int retval;kset = kzalloc(sizeof(*kset), GFP_KERNEL);if (!kset)return NULL;retval = kobject_set_name(&kset->kobj, "%s", name);if (retval) {kfree(kset);return NULL;}kset->uevent_ops = uevent_ops;kset->kobj.parent = parent_kobj;/** The kobject of this kset will have a type of kset_ktype and belong to* no kset itself.  That way we can properly free it when it is* finished being used.*/kset->kobj.ktype = &kset_ktype;kset->kobj.kset = NULL;return kset;
}

如果自己创建的kobject中的kset非NULL,那么在初始化接口kobject_init_and_add->kobject_add_internal:

static int kobject_add_internal(struct kobject *kobj)
{int error = 0;struct kobject *parent;if (!kobj)return -ENOENT;if (!kobj->name || !kobj->name[0]) {WARN(1,"kobject: (%p): attempted to be registered with empty name!\n",kobj);return -EINVAL;}parent = kobject_get(kobj->parent);/* join kset if set, use it as parent if we do not already have one */if (kobj->kset) {if (!parent)parent = kobject_get(&kobj->kset->kobj);kobj_kset_join(kobj);  //加入kset的链表kobj->parent = parent;}................
}static void kobj_kset_leave(struct kobject *kobj)
{if (!kobj->kset)return;spin_lock(&kobj->kset->list_lock);list_del_init(&kobj->entry);spin_unlock(&kobj->kset->list_lock);kset_put(kobj->kset);
}

后续通过kset_find_obj函数查找:

struct kobject *kset_find_obj(struct kset *kset, const char *name)
{struct kobject *k;struct kobject *ret = NULL;spin_lock(&kset->list_lock);list_for_each_entry(k, &kset->list, entry) {if (kobject_name(k) && !strcmp(kobject_name(k), name)) {ret = kobject_get_unless_zero(k);break;}}spin_unlock(&kset->list_lock);return ret;
}

创建文件目录和文件(attribute)的本质:

 kobject_add_internalcreate_dir(kobj)sysfs_create_dir_ns(kobj, kobject_namespace(kobj));   //fs/sysfs/dir.c kernfs_create_dir_ns              //fs/kernfs/dir.c 创建 kernfs_node * kn目录,union配置为kernfs_elem_dirkernfs_new_node    kernfs_add_one 设置kobject->sd为kn populate_dir(kobj);  //为默认的default_attrs[]创建文件属性sysfs_create_file(kobj, attr); //循环调用sysfs_create_file_ns(kobj, attr, NULL);sysfs_add_file_mode_ns    //fs/sysfs/file.c__kernfs_create_file  //fs/kernfs/file.c  设置union的kernfs_elem_attrkernfs_new_node //创建kernfs_node *kn ,以kobject->sd为parentkernfs_add_one

amdgpu驱动中在/sys/bus/pci/devices/0000:0f:00.0/下面创建vram相关的属性文件:

root@wzm-phytium-d2000:/sys/bus/pci/devices/0000:0f:00.0# ls mem_info_*
mem_info_gtt_total  mem_info_preempt_used    mem_info_vis_vram_used  mem_info_vram_used
mem_info_gtt_used   mem_info_vis_vram_total  mem_info_vram_total     mem_info_vram_vendor

drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c 

/*** DOC: mem_info_vram_total** The amdgpu driver provides a sysfs API for reporting current total VRAM* available on the device* The file mem_info_vram_total is used for this and returns the total* amount of VRAM in bytes*/
static ssize_t amdgpu_mem_info_vram_total_show(struct device *dev,struct device_attribute *attr, char *buf)
{struct drm_device *ddev = dev_get_drvdata(dev);struct amdgpu_device *adev = drm_to_adev(ddev);return snprintf(buf, PAGE_SIZE, "%llu\n", adev->gmc.real_vram_size);
}/*** DOC: mem_info_vis_vram_total** The amdgpu driver provides a sysfs API for reporting current total* visible VRAM available on the device* The file mem_info_vis_vram_total is used for this and returns the total* amount of visible VRAM in bytes*/
static ssize_t amdgpu_mem_info_vis_vram_total_show(struct device *dev,struct device_attribute *attr, char *buf)
{struct drm_device *ddev = dev_get_drvdata(dev);struct amdgpu_device *adev = drm_to_adev(ddev);return snprintf(buf, PAGE_SIZE, "%llu\n", adev->gmc.visible_vram_size);
}static DEVICE_ATTR(mem_info_vram_total, S_IRUGO,amdgpu_mem_info_vram_total_show, NULL);
static DEVICE_ATTR(mem_info_vis_vram_total, S_IRUGO,amdgpu_mem_info_vis_vram_total_show,NULL);
static DEVICE_ATTR(mem_info_vram_used, S_IRUGO,amdgpu_mem_info_vram_used_show, NULL);
static DEVICE_ATTR(mem_info_vis_vram_used, S_IRUGO,amdgpu_mem_info_vis_vram_used_show, NULL);
static DEVICE_ATTR(mem_info_vram_vendor, S_IRUGO,amdgpu_mem_info_vram_vendor, NULL);static const struct attribute *amdgpu_vram_mgr_attributes[] = {&dev_attr_mem_info_vram_total.attr,&dev_attr_mem_info_vis_vram_total.attr,&dev_attr_mem_info_vram_used.attr,&dev_attr_mem_info_vis_vram_used.attr,&dev_attr_mem_info_vram_vendor.attr,NULL
};int amdgpu_vram_mgr_init(struct amdgpu_device *adev)
{struct amdgpu_vram_mgr *mgr = &adev->mman.vram_mgr;struct ttm_resource_manager *man = &mgr->manager;int ret;ttm_resource_manager_init(man, adev->gmc.real_vram_size >> PAGE_SHIFT);man->func = &amdgpu_vram_mgr_func;drm_mm_init(&mgr->mm, 0, man->size);spin_lock_init(&mgr->lock);/* Add the two VRAM-related sysfs files */ret = sysfs_create_files(&adev->dev->kobj, amdgpu_vram_mgr_attributes);if (ret)DRM_ERROR("Failed to register sysfs\n");ttm_set_driver_manager(&adev->mman.bdev, TTM_PL_VRAM, &mgr->manager);ttm_resource_manager_set_used(man, true);return 0;
}

这篇关于kobject创建文件夹和文件测试。的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

JAVA中整型数组、字符串数组、整型数和字符串 的创建与转换的方法

《JAVA中整型数组、字符串数组、整型数和字符串的创建与转换的方法》本文介绍了Java中字符串、字符数组和整型数组的创建方法,以及它们之间的转换方法,还详细讲解了字符串中的一些常用方法,如index... 目录一、字符串、字符数组和整型数组的创建1、字符串的创建方法1.1 通过引用字符数组来创建字符串1.2

手把手教你idea中创建一个javaweb(webapp)项目详细图文教程

《手把手教你idea中创建一个javaweb(webapp)项目详细图文教程》:本文主要介绍如何使用IntelliJIDEA创建一个Maven项目,并配置Tomcat服务器进行运行,过程包括创建... 1.启动idea2.创建项目模板点击项目-新建项目-选择maven,显示如下页面输入项目名称,选择

如何测试计算机的内存是否存在问题? 判断电脑内存故障的多种方法

《如何测试计算机的内存是否存在问题?判断电脑内存故障的多种方法》内存是电脑中非常重要的组件之一,如果内存出现故障,可能会导致电脑出现各种问题,如蓝屏、死机、程序崩溃等,如何判断内存是否出现故障呢?下... 如果你的电脑是崩溃、冻结还是不稳定,那么它的内存可能有问题。要进行检查,你可以使用Windows 11

Python使用pysmb库访问Windows共享文件夹的详细教程

《Python使用pysmb库访问Windows共享文件夹的详细教程》本教程旨在帮助您使用pysmb库,通过SMB(ServerMessageBlock)协议,轻松连接到Windows共享文件夹,并列... 目录前置条件步骤一:导入必要的模块步骤二:配置连接参数步骤三:实例化SMB连接对象并尝试连接步骤四:

性能测试介绍

性能测试是一种测试方法,旨在评估系统、应用程序或组件在现实场景中的性能表现和可靠性。它通常用于衡量系统在不同负载条件下的响应时间、吞吐量、资源利用率、稳定性和可扩展性等关键指标。 为什么要进行性能测试 通过性能测试,可以确定系统是否能够满足预期的性能要求,找出性能瓶颈和潜在的问题,并进行优化和调整。 发现性能瓶颈:性能测试可以帮助发现系统的性能瓶颈,即系统在高负载或高并发情况下可能出现的问题

字节面试 | 如何测试RocketMQ、RocketMQ?

字节面试:RocketMQ是怎么测试的呢? 答: 首先保证消息的消费正确、设计逆向用例,在验证消息内容为空等情况时的消费正确性; 推送大批量MQ,通过Admin控制台查看MQ消费的情况,是否出现消费假死、TPS是否正常等等问题。(上述都是临场发挥,但是RocketMQ真正的测试点,还真的需要探讨) 01 先了解RocketMQ 作为测试也是要简单了解RocketMQ。简单来说,就是一个分

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

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

【测试】输入正确用户名和密码,点击登录没有响应的可能性原因

目录 一、前端问题 1. 界面交互问题 2. 输入数据校验问题 二、网络问题 1. 网络连接中断 2. 代理设置问题 三、后端问题 1. 服务器故障 2. 数据库问题 3. 权限问题: 四、其他问题 1. 缓存问题 2. 第三方服务问题 3. 配置问题 一、前端问题 1. 界面交互问题 登录按钮的点击事件未正确绑定,导致点击后无法触发登录操作。 页面可能存在

在cscode中通过maven创建java项目

在cscode中创建java项目 可以通过博客完成maven的导入 建立maven项目 使用快捷键 Ctrl + Shift + P 建立一个 Maven 项目 1 Ctrl + Shift + P 打开输入框2 输入 "> java create"3 选择 maven4 选择 No Archetype5 输入 域名6 输入项目名称7 建立一个文件目录存放项目,文件名一般为项目名8 确定

业务中14个需要进行A/B测试的时刻[信息图]

在本指南中,我们将全面了解有关 A/B测试 的所有内容。 我们将介绍不同类型的A/B测试,如何有效地规划和启动测试,如何评估测试是否成功,您应该关注哪些指标,多年来我们发现的常见错误等等。 什么是A/B测试? A/B测试(有时称为“分割测试”)是一种实验类型,其中您创建两种或多种内容变体——如登录页面、电子邮件或广告——并将它们显示给不同的受众群体,以查看哪一种效果最好。 本质上,A/B测