当前位置: 首页 > news >正文

I.MX6ULL内核开发9:kobject-驱动的基石

目录

一、摘要

二、重点

三、驱动结构模型

四、关键函数分析

kobject_create_and_add()函数

kobject_create()函数

kobject_init()函数

kobject_init_internal()函数

kobject_add()函数

kobject_add_varg()函数

kobject_set_name_vargs()函数

kobject_add_internal()函数

create_dir()函数

sysfs_create_dir_ns()函数


一、摘要

  • 构建一个kobject对象
  • 构建一个sysfs中的目录项(kernfs_node)
  • 把他们关联起来

二、重点

  • 关注sysfs目录项与kobject对象的关联过程
  • 关注kobject对象默认的属性文件接口

三、驱动结构模型

 

四、关键函数分析

kobject_create_and_add()函数

/home/geralt/linux_driver/kernel/ebf_linux_kernel_6ull_depth1/lib/kobject.c

struct kobject *kobject_create_and_add(const char *name, struct kobject *parent)
{struct kobject *kobj;int retval;// 创建并初始化kobj = kobject_create();if (!kobj)return NULL;// sysfs创建一个目录项并与kobject对象关联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()函数

/home/geralt/linux_driver/kernel/ebf_linux_kernel_6ull_depth1/lib/kobject.c

struct kobject *kobject_create(void)
{struct kobject *kobj;// 动态申请内存,存放kobject对象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,
};
const struct sysfs_ops kobj_sysfs_ops = {.show	= kobj_attr_show,.store	= kobj_attr_store,
};

kobject_init()函数

/home/geralt/linux_driver/kernel/ebf_linux_kernel_6ull_depth1/lib/kobject.c

void kobject_init(struct kobject *kobj, struct kobj_type *ktype)
{char *err_str;if (!kobj) {err_str = "invalid kobject pointer!";goto error;}if (!ktype) {err_str = "must have a ktype to be initialized properly!\n";goto error;}if (kobj->state_initialized) {/* do not error out as sometimes we can recover */pr_err("kobject (%p): tried to init an initialized object, something is seriously wrong.\n",kobj);dump_stack();}kobject_init_internal(kobj);kobj->ktype = ktype;return;error:pr_err("kobject (%p): %s\n", kobj, err_str);dump_stack();
}

kobject_init_internal()函数

home/geralt/linux_driver/kernel/ebf_linux_kernel_6ull_depth1/lib/kobject.c

static void kobject_init_internal(struct kobject *kobj)
{if (!kobj)return;// 将kobject的引用计数设置为1kref_init(&kobj->kref);// 初始化链表节点INIT_LIST_HEAD(&kobj->entry);// 该kobject对象还没和sysfs目录项关联kobj->state_in_sysfs = 0;kobj->state_add_uevent_sent = 0;kobj->state_remove_uevent_sent = 0;// kobject对象的初始化标志kobj->state_initialized = 1;
}

kobject_add()函数

home/geralt/linux_driver/kernel/ebf_linux_kernel_6ull_depth1/lib/kobject.c

int kobject_add(struct kobject *kobj, struct kobject *parent,const char *fmt, ...)
{va_list args;int retval;if (!kobj)return -EINVAL;if (!kobj->state_initialized) {pr_err("kobject '%s' (%p): tried to add an uninitialized object, something is seriously wrong.\n",kobject_name(kobj), kobj);dump_stack();return -EINVAL;}// 获取第一个可变参数,可变参数函数的实现与函数传参的栈结构有关va_start(args, fmt);retval = kobject_add_varg(kobj, parent, fmt, args);va_end(args);return retval;
}

kobject_add_varg()函数

home/geralt/linux_driver/kernel/ebf_linux_kernel_6ull_depth1/lib/kobject.c

static __printf(3, 0) int kobject_add_varg(struct kobject *kobj,struct kobject *parent,const char *fmt, va_list vargs)
{int retval;retval = kobject_set_name_vargs(kobj, fmt, vargs);if (retval) {pr_err("kobject: can not set name properly!\n");return retval;}// 第一次设置的kobj的parent指针kobj->parent = parent;return kobject_add_internal(kobj);
}

kobject_set_name_vargs()函数

int kobject_set_name_vargs(struct kobject *kobj, const char *fmt,va_list vargs)`
{const char *s;if (kobj->name && !fmt)return 0;// 参数格式化打印到s字符串中s = kvasprintf_const(GFP_KERNEL, fmt, vargs);if (!s)return -ENOMEM;/** ewww... some of these buggers have '/' in the name ... If* that's the case, we need to make sure we have an actual* allocated copy to modify, since kvasprintf_const may have* returned something from .rodata.*/if (strchr(s, '/')) {char *t;t = kstrdup(s, GFP_KERNEL);kfree_const(s);if (!t)return -ENOMEM;strreplace(t, '/', '!');s = t;}kfree_const(kobj->name);// 设置kobject对象的名称kobj->name = s;return 0;
}

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);kobj->parent = parent;}pr_debug("kobject: '%s' (%p): %s: parent: '%s', set: '%s'\n",kobject_name(kobj), kobj, __func__,parent ? kobject_name(parent) : "<NULL>",kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>");error = create_dir(kobj);if (error) {kobj_kset_leave(kobj);kobject_put(parent);kobj->parent = NULL;/* be noisy on error issues */if (error == -EEXIST)pr_err("%s failed for %s with -EEXIST, don't try to register things with the same name in the same directory.\n",__func__, kobject_name(kobj));elsepr_err("%s failed for %s (error: %d parent: %s)\n",__func__, kobject_name(kobj), error,parent ? kobject_name(parent) : "'none'");} elsekobj->state_in_sysfs = 1;return error;
}

create_dir()函数

static int create_dir(struct kobject *kobj)
{const struct kobj_ns_type_operations *ops;int error;error = sysfs_create_dir_ns(kobj, kobject_namespace(kobj));if (error)return error;error = populate_dir(kobj);if (error) {sysfs_remove_dir(kobj);return error;}/** @kobj->sd may be deleted by an ancestor going away.  Hold an* extra reference so that it stays until @kobj is gone.*/sysfs_get(kobj->sd);/** If @kobj has ns_ops, its children need to be filtered based on* their namespace tags.  Enable namespace support on @kobj->sd.*/ops = kobj_child_ns_ops(kobj);if (ops) {BUG_ON(ops->type <= KOBJ_NS_TYPE_NONE);BUG_ON(ops->type >= KOBJ_NS_TYPES);BUG_ON(!kobj_ns_type_registered(ops->type));sysfs_enable_ns(kobj->sd);}return 0;
}

sysfs_create_dir_ns()函数


文件:/home/geralt/linux_driver/kernel/ebf_linux_kernel_6ull_depth1/fs/sysfs

int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
{struct kernfs_node *parent, *kn;kuid_t uid;kgid_t gid;BUG_ON(!kobj);if (kobj->parent)// 获取上一层节点的目录项parent = kobj->parent->sd;else// 设置上一层节点的目录项sysfsparent = sysfs_root_kn;if (!parent)return -ENOENT;kobject_get_ownership(kobj, &uid, &gid);kn = kernfs_create_dir_ns(parent, kobject_name(kobj),S_IRWXU | S_IRUGO | S_IXUGO, uid, gid,kobj, ns);if (IS_ERR(kn)) {if (PTR_ERR(kn) == -EEXIST)sysfs_warn_dup(parent, kobject_name(kobj));return PTR_ERR(kn);}// kobj对象关联sysfs目录项kobj->sd = kn;return 0;
}

相关文章:

I.MX6ULL内核开发9:kobject-驱动的基石

目录 一、摘要 二、重点 三、驱动结构模型 四、关键函数分析 kobject_create_and_add()函数 kobject_create()函数 kobject_init&#xff08;&#xff09;函数 kobject_init_internal(&#xff09;函数 kobject_add&#xff08;&#xff09;函数 kobject_add_varg&am…...

Docker-harbor私有仓库

一、Harbor概述 1、Harbor的概念 • Harbor是VMware公司开源的企业级Docker Registry项目&#xff0c;其目标是帮助用户迅速搭建一个企业级的Docker Registry服务 • Harbor以 Docker 公司开源的Registry 为基础&#xff0c;提供了图形管理UI、基于角色的访问控制(Role Base…...

Java之动态规划之子序列问题

目录 0.动态规划问题 一.最长递增子序列 1.题目描述 2.问题分析 3.代码实现 二.最长递增子序列 1.题目描述 2.问题分析 3.代码实现 三.最长重复子数组 1.题目描述 2.问题分析 3.代码实现 4.代码的优化(滚动数组) 四.最长公共子序列 1.题目描述 2.问题分析 3.代…...

java ArrayList

目录 一.简单介绍 二.ArrayList的底层结构 2.1ArrayList的底层结构和操作分析 2.ArrayList 底层源码分析 三.ArrayList 方法 四.代码使用方法 一.简单介绍 ArrayList 类是一个可以动态修改的数组&#xff0c;与普通数组的区别就是它是没有固定大小的限制&#xff0c;我们…...

前端——周总结系列四

1 JS变量与常量 概述 变量&#xff1a;在后续编码过程中会被重新赋值&#xff0c;是不断变化的。常量&#xff1a;固定不变的数据&#xff0c;日常生活比如性别男&#xff0c;代码层面是在编码过程中不会变化的固定数据。 命名规则 变量 可以包含数字&#xff0c;字母&…...

Linux重定向符、管道符讲解

目录 重定向 将命令与文件进行互动 输出重定向 输入重定向 管道符 将命令与命令互动起来 重定向 将命令与文件进行互动 重定向分类 一般情况下&#xff0c;Linux命令运行时都会打开一下三个文件 标准输入文件&#xff1a;stdin文件&#xff0c;文件描述符为0&#xff0c;Li…...

【C++】多态

多态一、多态的概念及定义1.1 虚函数1.2 虚函数重写的特殊情况1.3 override 和 final二、抽象类2.1 概念2.2 用处三、多态的原理3.1 虚函数表3.1.1 虚函数与虚表的位置3.2 多态的原理3.3 静态绑定和动态绑定四、单/多继承的虚函数表4.1 单继承的虚函数表4.2 多继承的虚函数表一…...

分布式项目-品牌管理(5、6)

【今日成果】&#xff1a; //使用阿里云OSS服务&#xff1a; //使用v-if如果地址没有就不显示 &#xff0c; 如果地址错误图片就显示不出来&#xff1b; 【快速回顾】&#xff1a; 任何数据的删除都不要使用物理上的删除&#xff0c;应当使用逻辑上的删除&#xff01;&…...

自定义ESLint规则开发与使用

自定义eslint及使用 项目结构 |-eslint-plugin-demo //自定义eslint插件项目 | |-demo-app // 使用自定义eslint的测试应用 |-README.md 项目效果&#xff1a; github项目地址 自定义ESLint环境准备 安装脚手架 执行下列命令来安装开发eslint的脚手架。 yo(y…...

【JavaScript】35_包装类与垃圾回收机制

10、包装类 在JS中&#xff0c;除了直接创建原始值外&#xff0c;也可以创建原始值的对象 通过 new String() 可以创建String类型的对象 通过 new Number() 可以创建Number类型的对象 通过 new Boolean() 可以创建Boolean类型的对象 但是千万不要这么做 包装类&#xff1…...

【CS224W】(task3)NetworkX工具包实践

note 节点可以为任意可哈希的对象&#xff0c;比如字符串、图像、XML对象&#xff0c;甚至另一个Graph、自定义的节点对象。通过这种方式可以自由灵活地构建&#xff1a;图为节点、文件为节点、函数为节点&#xff0c;等灵活的图形式。暂时省略&#xff1a;【B5】计算机网络图…...

ansible的模块详解

ansible 的概述 什么是ansible Ansible是一款为类Unix系统开发的自由开源的配置和自动化工具。 它用Python写成&#xff0c;类似于saltstack和Puppet&#xff0c;但是有一个不同和优点是我们不需要在节点中安装任何客户端。 它使用SSH来和节点进行通信。Ansible基于 Python…...

《Terraform 101 从入门到实践》 Functions函数

《Terraform 101 从入门到实践》这本小册在南瓜慢说官方网站和GitHub两个地方同步更新&#xff0c;书中的示例代码也是放在GitHub上&#xff0c;方便大家参考查看。 Terraform的函数 Terraform为了让大家在表达式上可以更加灵活方便地进行计算&#xff0c;提供了大量的内置函数…...

使用kubeadm快速部署一个K8s集群

wkubeadm是官方社区推出的一个用于快速部署kubernetes集群的工具。 这个工具能通过两条指令完成一个kubernetes集群的部署&#xff1a; # 创建一个 Master 节点 $ kubeadm init# 将一个 Node 节点加入到当前集群中 $ kubeadm join <Master节点的IP和端口 >1. 安装要求 …...

初探富文本之CRDT协同算法

初探富文本之CRDT协同算法 CRDT的英文全称是Conflict-free Replicated Data Type&#xff0c;最初是由协同文本编辑和移动计算而发展的&#xff0c;现在还被用作在线聊天系统、音频分发平台等等。当前CRDT算法在富文本编辑器领域的协同依旧是典型的场景&#xff0c;常用于作为…...

Dubbo和Zookeeper集成分布式系统快速入门

文件结构 代码部分 1、新建provider-server导入pom依赖 <dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-spring-boot-starter</artifactId><version>2.7.3</version></dependency><dependency>&l…...

大数据工具Maxwell的使用

1.Maxwell简介 Maxwell 是由美国Zendesk公司开源&#xff0c;用Java编写的MySQL变更数据抓取软件。它会实时监控Mysql数据库的数据变更操作&#xff08;包括insert、update、delete&#xff09;&#xff0c;并将变更数据以 JSON 格式发送给 Kafka、Kinesi等流数据处理平台。 官…...

freesurfer如何将组模板投影到个体空间——如投影 Schaefer2018 到个体空间

freesurfer如何将组模板投影到个体空间——如投影 Schaefer2018 到个体空间 freesurfer如何将组模板投影到个体空间? freesurfer如何将组模板投影到个体空间——如投影 Schaefer2018 到个体空间freesurfer的整理流程freesurfer的安装freesurfer对结构像分割流程及批处理代码fr…...

Matlab傅里叶谱方法求解二维波动方程

傅里叶谱方法求解基本偏微分方程—二维波动方程 二维波动方程 将一维波动方程中的一维无界弦自由振动方程推广到二维空间上, 就得到了描述无界 (−∞<x,y<∞)(-\infty<x, y<\infty)(−∞<x,y<∞) 弹性薄膜的波动方程: ∂2u∂t2a2(∂2∂x2∂2∂y2)u(1)\frac…...

【深度学习】卷积神经网络

1 卷积神经网络&#xff08;CNN&#xff09;可以做什么&#xff1f; 检测任务分类与检索超分辨率重构&#xff1a;将图像训练的更清晰医学任务等无人驾驶人脸识别 2 用GPU&#xff1a;图像处理单元 比CPU块一百倍以上 3 卷积神经网络与传统神经网络的区别 传统神经网络&…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外&#xff0c;K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案&#xff0c;全安装在K8S群集中。 具体可参…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​&#xff1a; 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​&#xff1a; File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成

厌倦手动写WordPress文章&#xff1f;AI自动生成&#xff0c;效率提升10倍&#xff01; 支持多语言、自动配图、定时发布&#xff0c;让内容创作更轻松&#xff01; AI内容生成 → 不想每天写文章&#xff1f;AI一键生成高质量内容&#xff01;多语言支持 → 跨境电商必备&am…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

Fabric V2.5 通用溯源系统——增加图片上传与下载功能

fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...

Web中间件--tomcat学习

Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机&#xff0c;它可以执行Java字节码。Java虚拟机是Java平台的一部分&#xff0c;Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

k8s从入门到放弃之HPA控制器

k8s从入门到放弃之HPA控制器 Kubernetes中的Horizontal Pod Autoscaler (HPA)控制器是一种用于自动扩展部署、副本集或复制控制器中Pod数量的机制。它可以根据观察到的CPU利用率&#xff08;或其他自定义指标&#xff09;来调整这些对象的规模&#xff0c;从而帮助应用程序在负…...