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()函数 kobject_init_internal()函数 kobject_add()函数 kobject_add_varg&am…...
Docker-harbor私有仓库
一、Harbor概述 1、Harbor的概念 • Harbor是VMware公司开源的企业级Docker Registry项目,其目标是帮助用户迅速搭建一个企业级的Docker Registry服务 • Harbor以 Docker 公司开源的Registry 为基础,提供了图形管理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 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们…...
前端——周总结系列四
1 JS变量与常量 概述 变量:在后续编码过程中会被重新赋值,是不断变化的。常量:固定不变的数据,日常生活比如性别男,代码层面是在编码过程中不会变化的固定数据。 命名规则 变量 可以包含数字,字母&…...
Linux重定向符、管道符讲解
目录 重定向 将命令与文件进行互动 输出重定向 输入重定向 管道符 将命令与命令互动起来 重定向 将命令与文件进行互动 重定向分类 一般情况下,Linux命令运行时都会打开一下三个文件 标准输入文件:stdin文件,文件描述符为0,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)
【今日成果】: //使用阿里云OSS服务: //使用v-if如果地址没有就不显示 , 如果地址错误图片就显示不出来; 【快速回顾】: 任何数据的删除都不要使用物理上的删除,应当使用逻辑上的删除!&…...
自定义ESLint规则开发与使用
自定义eslint及使用 项目结构 |-eslint-plugin-demo //自定义eslint插件项目 | |-demo-app // 使用自定义eslint的测试应用 |-README.md 项目效果: github项目地址 自定义ESLint环境准备 安装脚手架 执行下列命令来安装开发eslint的脚手架。 yo(y…...
【JavaScript】35_包装类与垃圾回收机制
10、包装类 在JS中,除了直接创建原始值外,也可以创建原始值的对象 通过 new String() 可以创建String类型的对象 通过 new Number() 可以创建Number类型的对象 通过 new Boolean() 可以创建Boolean类型的对象 但是千万不要这么做 包装类࿱…...
【CS224W】(task3)NetworkX工具包实践
note 节点可以为任意可哈希的对象,比如字符串、图像、XML对象,甚至另一个Graph、自定义的节点对象。通过这种方式可以自由灵活地构建:图为节点、文件为节点、函数为节点,等灵活的图形式。暂时省略:【B5】计算机网络图…...
ansible的模块详解
ansible 的概述 什么是ansible Ansible是一款为类Unix系统开发的自由开源的配置和自动化工具。 它用Python写成,类似于saltstack和Puppet,但是有一个不同和优点是我们不需要在节点中安装任何客户端。 它使用SSH来和节点进行通信。Ansible基于 Python…...
《Terraform 101 从入门到实践》 Functions函数
《Terraform 101 从入门到实践》这本小册在南瓜慢说官方网站和GitHub两个地方同步更新,书中的示例代码也是放在GitHub上,方便大家参考查看。 Terraform的函数 Terraform为了让大家在表达式上可以更加灵活方便地进行计算,提供了大量的内置函数…...
使用kubeadm快速部署一个K8s集群
wkubeadm是官方社区推出的一个用于快速部署kubernetes集群的工具。 这个工具能通过两条指令完成一个kubernetes集群的部署: # 创建一个 Master 节点 $ kubeadm init# 将一个 Node 节点加入到当前集群中 $ kubeadm join <Master节点的IP和端口 >1. 安装要求 …...
初探富文本之CRDT协同算法
初探富文本之CRDT协同算法 CRDT的英文全称是Conflict-free Replicated Data Type,最初是由协同文本编辑和移动计算而发展的,现在还被用作在线聊天系统、音频分发平台等等。当前CRDT算法在富文本编辑器领域的协同依旧是典型的场景,常用于作为…...
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公司开源,用Java编写的MySQL变更数据抓取软件。它会实时监控Mysql数据库的数据变更操作(包括insert、update、delete),并将变更数据以 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 卷积神经网络(CNN)可以做什么? 检测任务分类与检索超分辨率重构:将图像训练的更清晰医学任务等无人驾驶人脸识别 2 用GPU:图像处理单元 比CPU块一百倍以上 3 卷积神经网络与传统神经网络的区别 传统神经网络&…...
破解隧道定位多径效应难题:基于实测数据的第一代与第二代UWB定位效果对比
在隧道环境中,定位效果会受到多种环境因素的显著影响。 其封闭结构、复杂材质和严重的多径效应这些因素共同作用,往往容易导致定位轨迹发生漂移、精度下降和稳定性不足,从而难以满足隧道环境下对高精度定位、区域安全动态管理、施工安全管控…...
深度解析:如何利用Gemini百万级长上下文处理复杂文档?技术原理与实战指南
在众多AI模型中,Gemini 1.5 Pro的百万级上下文窗口堪称技术突破。这项能力让AI从“对话工具”跃升为“深度分析师”。本文将从技术原理入手,结合实战案例,拆解如何利用这一能力处理长篇文档、复杂财报、代码库等任务,并介绍国内用…...
资源加速通道:百度网盘高效下载解决方案与实践指南
资源加速通道:百度网盘高效下载解决方案与实践指南 【免费下载链接】baidu-wangpan-parse 获取百度网盘分享文件的下载地址 项目地址: https://gitcode.com/gh_mirrors/ba/baidu-wangpan-parse 在数字化协作日益频繁的今天,云存储服务已成为信息传…...
推荐一款开源利器:Linux Router
推荐一款开源利器:Linux Router 【免费下载链接】linux-router Set Linux as router in one command. Support Internet sharing, redsocks, Wifi hotspot, IPv6. Can also be used for routing VM/containers 🛰️ (也欢迎关注B站 https://space.bilibi…...
分组密码设计实战:为什么AES选择SPN而DES用Feistel?从硬件到安全的深度解析
分组密码设计的十字路口:为何AES与DES走向了不同的架构? 在嵌入式设备里为一个加密算法选择硬件方案时,工程师们常常面临一个根本性的抉择:是采用结构规整、加解密相似的Feistel网络,还是拥抱混淆扩散效率更高、但实现…...
OpenVR相机追踪开发终极指南:实现VR视频捕捉与处理的完整教程
OpenVR相机追踪开发终极指南:实现VR视频捕捉与处理的完整教程 【免费下载链接】openvr OpenVR SDK 项目地址: https://gitcode.com/gh_mirrors/op/openvr OpenVR SDK是一款强大的虚拟现实开发工具包,它提供了丰富的API和工具,帮助开发…...
保姆级教程:用Docker一键部署CloudBeaver并完美解决中文乱码问题
从零到精通:在Docker中部署CloudBeaver并彻底驯服中文环境 如果你正在寻找一个能通过浏览器管理多种数据库的利器,CloudBeaver绝对是一个令人兴奋的选择。作为DBeaver的Web版本,它继承了强大的多数据库支持能力,却将使用场景从桌面…...
ECS架构实战:从理论到2D游戏开发的完整实现
1. 为什么你的游戏代码总是一团乱麻?试试ECS吧! 如果你写过游戏,尤其是那种有很多角色、怪物、道具在屏幕上跑来跑去的2D游戏,你肯定有过这种体验:一开始代码结构还挺清晰,但随着功能越加越多,比…...
【C语言实战】从零构建:滑动窗口与增量计算在嵌入式RMS实时处理中的工程抉择
1. 项目启动:当电机电流监测遇上资源捉襟见肘的MCU 大家好,我是老李,一个在嵌入式坑里摸爬滚打了十多年的工程师。最近刚接了个新项目,客户要求我们做一套电机运行状态的实时监测系统,核心指标之一就是电机电流的有效…...
说好淘汰外卖小哥的,先把我淘汰成了外卖小哥
2024 年的时候,我还觉得 AI 写代码就是个玩具,生成点 hello world、写点 CRUD 还行,真正复杂的业务逻辑它搞不定。2025 年初的时候,我开始有点慌了。到了 2026 年,我直接不说话了。现在的 AI 写代码是什么水平呢&#…...
