当前位置: 首页 > 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 卷积神经网络与传统神经网络的区别 传统神经网络&…...

Unity Shader 中 ShadowCaster的作用和疑问

1. ShadowCaster&#xff08;核心 —— 让物体能投影&#xff09;LightMode ShadowCaster&#xff1a;URP 渲染 Shadow Map 时会调用此 PassColorMask 0&#xff1a;不输出颜色&#xff0c;只写深度顶点关键步骤&#xff1a;TransformObjectToWorld / TransformObjectToWorldN…...

【智能代码生成×代码度量双引擎实战指南】:20年架构师亲授如何用AI写代码+量化质量,规避97%的交付返工风险

第一章&#xff1a;智能代码生成代码度量双引擎协同范式 2026奇点智能技术大会(https://ml-summit.org) 传统AI编程辅助工具常将代码生成与质量评估割裂为独立流程&#xff1a;生成模型输出后&#xff0c;再由静态分析器进行滞后性度量。双引擎协同范式则打破这一时序壁垒&…...

Bilibili视频下载器:高效下载大会员4K超清内容的专业解决方案

Bilibili视频下载器&#xff1a;高效下载大会员4K超清内容的专业解决方案 【免费下载链接】bilibili-downloader B站视频下载&#xff0c;支持下载大会员清晰度4K&#xff0c;持续更新中 项目地址: https://gitcode.com/gh_mirrors/bil/bilibili-downloader 在当今数字化…...

FANUC 0i-F系统数据备份时,除了全数据,PMC和SRAM文件还有必要单独备份吗?

&#x1f4a1; 学习者 FAQ 解答 Q1: FANUC 0i-F系统数据备份时&#xff0c;除了全数据&#xff0c;PMC和SRAM文件还有必要单独备份吗&#xff1f; A1: 很有必要&#xff01;全数据备份虽然包含了大部分信息&#xff0c;但PMC和SRAM文件是控制器个性化配置和用户程序的关键&…...

Python实现基于DD驱动的键盘R键连发功能

Python实现基于DD驱动的键盘R键连发功能 一、引言 1.1 项目背景 在游戏开发、自动化测试、辅助工具等领域,实现键盘按键的连发功能是一项常见需求。所谓“连发”,指的是当用户按住某个按键时,系统自动以一定的频率持续触发该按键的按下和释放事件,从而模拟极快的手动按键…...

FSA-Net轻量化实战:在Android端实现实时头部姿态估计

1. 为什么要在Android端实现头部姿态估计&#xff1f; 想象一下这样的场景&#xff1a;你正在用手机视频通话&#xff0c;当你转头时&#xff0c;屏幕上的虚拟形象也能同步转动头部&#xff1b;或者玩AR游戏时&#xff0c;游戏角色能实时模仿你的表情和头部动作。这些酷炫功能的…...

芯片ESD防护设计避坑指南:从失效案例看如何优化你的电路

芯片ESD防护设计避坑指南&#xff1a;从失效案例看如何优化你的电路 静电放电&#xff08;ESD&#xff09;是芯片设计中最隐蔽的"隐形杀手"。据统计&#xff0c;超过60%的芯片早期失效与ESD事件相关&#xff0c;但大多数损伤在显微镜下才能被发现。我曾参与过一个智能…...

SPI DMA 高效数据搬运实战:从原理到调试避坑指南

1. SPI与DMA的黄金搭档&#xff1a;为什么需要它们&#xff1f; 在嵌入式开发中&#xff0c;SPI&#xff08;Serial Peripheral Interface&#xff09;是一种非常常见的同步串行通信协议&#xff0c;它被广泛用于芯片间的数据交换。但当你需要传输大量数据时&#xff0c;传统的…...

保姆级教程:在Ubuntu 20.04上搭建高通Camx源码阅读与调试环境(含Source Insight配置)

高通Camx开发环境搭建实战&#xff1a;从源码获取到调试全流程指南 如果你正在阅读这篇文章&#xff0c;大概率是因为你刚接触高通Camera驱动开发&#xff0c;面对庞大的Camx代码库感到无从下手。Camx作为高通Spectra ISP的核心驱动框架&#xff0c;其复杂性和深度确实会让初学…...

深入PyTorch源码:手把手调试grid_sample,搞懂-1到1的坐标映射与双线性插值细节

深入PyTorch源码&#xff1a;手把手调试grid_sample&#xff0c;搞懂-1到1的坐标映射与双线性插值细节 在计算机视觉和深度学习领域&#xff0c;图像变形和采样是许多任务的基础操作。PyTorch作为主流深度学习框架&#xff0c;提供了grid_sample这一强大但常被低估的函数。不同…...