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 卷积神经网络与传统神经网络的区别 传统神经网络&…...
超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散
前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说,在叠衣服的过程中,我会带着团队对比各种模型、方法、策略,毕竟针对各个场景始终寻找更优的解决方案,是我个人和我司「七月在线」的职责之一 且个人认为,…...
热门Chrome扩展程序存在明文传输风险,用户隐私安全受威胁
赛门铁克威胁猎手团队最新报告披露,数款拥有数百万活跃用户的Chrome扩展程序正在通过未加密的HTTP连接静默泄露用户敏感数据,严重威胁用户隐私安全。 知名扩展程序存在明文传输风险 尽管宣称提供安全浏览、数据分析或便捷界面等功能,但SEMR…...
AD学习(3)
1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…...
