Linux 下注册分析(4)

在这里插入图片描述

系列文章目录


Linux 设备树
Linux 下注册分析(1)
Linux 下注册分析(2)
Linux 下注册分析(3)
Linux 下注册分析(4)


文章目录

  • 系列文章目录
  • 1、device_create
    • 简介
    • device_create
      • device_create_groups_vargs
  • 2、class_register
    • 简介
    • struct class
    • class_register
  • 3、class_create
  • 4、class_interface_register


1、device_create

简介

    device_create 用于创建设备并在 sysfs 中注册指向该设备应该注册到的结构类的指针。这个函数可以被 char 设备类使用。

device_create

device_create
device_create_groups_vargs
// drivers/base/core.c
struct device *device_create(const struct class *class, struct device *parent,dev_t devt, void *drvdata, const char *fmt, ...)
{va_list vargs;struct device *dev;va_start(vargs, fmt);dev = device_create_groups_vargs(class, parent, devt, drvdata, NULL,fmt, vargs);va_end(vargs);return dev;
}
EXPORT_SYMBOL_GPL(device_create);

device_create_groups_vargs

device_create
device_create_groups_vargs
kzalloc(sizeof(*dev), GFP_KERNEL)
device_initialize
device_add
// drivers/base/core.c
static __printf(6, 0) struct device *
device_create_groups_vargs(const struct class *class, struct device *parent,dev_t devt, void *drvdata,const struct attribute_group **groups,const char *fmt, va_list args)
{struct device *dev = NULL;int retval = -ENODEV;if (IS_ERR_OR_NULL(class))goto error;dev = kzalloc(sizeof(*dev), GFP_KERNEL);	// 为设备分配空间if (!dev) {retval = -ENOMEM;goto error;}device_initialize(dev);		// 初始化设备结构体dev->devt = devt;dev->class = class;dev->parent = parent;dev->groups = groups;dev->release = device_create_release;dev_set_drvdata(dev, drvdata);retval = kobject_set_name_vargs(&dev->kobj, fmt, args);if (retval)goto error;retval = device_add(dev);	// 把设备加入到总线上if (retval)goto error;return dev;error:put_device(dev);return ERR_PTR(retval);
}

device_register 函数

// drivers/base/core.c
int device_register(struct device *dev)
{device_initialize(dev);return device_add(dev);
}

    从上可以看出,device_create() 调用了 device_initializedevice_add 两个函数,而这恰恰是 device_register() 做的工作,因此其等效于 device_register()

device_register 函数分析见 Linux 下注册分析(4)# device_register
device_add 函数分析见 Linux 下注册分析(4)# device_add


device_create()、device_register()、deivce_add()区别

2、class_register

简介

    在 Linux 系统中,class_register 是一个非常重要的概念。它是 Linux 内核中用来管理设备驱动程序的一种机制,通过对设备进行分类注册,实现设备间的协作和管理。在 Linux 系统中,设备驱动程序是连接硬件设备和操作系统内核的桥梁,而 class_register 机制可以帮助内核更好地管理这些设备驱动程序,并且提供一种灵活的方式来处理设备的注册和注销。

struct class

// include/linux/device/class.h
struct class {const char		*name;const struct attribute_group	**class_groups;const struct attribute_group	**dev_groups;int (*dev_uevent)(const struct device *dev, struct kobj_uevent_env *env);char *(*devnode)(const struct device *dev, umode_t *mode);void (*class_release)(const struct class *class);void (*dev_release)(struct device *dev);int (*shutdown_pre)(struct device *dev);const struct kobj_ns_type_operations *ns_type;const void *(*namespace)(const struct device *dev);void (*get_ownership)(const struct device *dev, kuid_t *uid, kgid_t *gid);const struct dev_pm_ops *pm;
};

class_register

class_register
kzalloc(sizeof(*cp), GFP_KERNEL)
kset_register(&cp->subsys)
sysfs_create_groups(&cp->subsys.kobj, cls->class_groups)
// drivers/base/class.c
int class_register(const struct class *cls)
{struct subsys_private *cp;struct lock_class_key *key;int error;pr_debug("device class '%s': registering\n", cls->name);if (cls->ns_type && !cls->namespace) {pr_err("%s: class '%s' does not have namespace\n",__func__, cls->name);return -EINVAL;}if (!cls->ns_type && cls->namespace) {pr_err("%s: class '%s' does not have ns_type\n",__func__, cls->name);return -EINVAL;}cp = kzalloc(sizeof(*cp), GFP_KERNEL);if (!cp)return -ENOMEM;klist_init(&cp->klist_devices, klist_class_dev_get, klist_class_dev_put);INIT_LIST_HEAD(&cp->interfaces);kset_init(&cp->glue_dirs);key = &cp->lock_key;lockdep_register_key(key);__mutex_init(&cp->mutex, "subsys mutex", key);error = kobject_set_name(&cp->subsys.kobj, "%s", cls->name);if (error)goto err_out;cp->subsys.kobj.kset = class_kset;cp->subsys.kobj.ktype = &class_ktype;cp->class = cls;error = kset_register(&cp->subsys);if (error)goto err_out;error = sysfs_create_groups(&cp->subsys.kobj, cls->class_groups);if (error) {kobject_del(&cp->subsys.kobj);kfree_const(cp->subsys.kobj.name);goto err_out;}return 0;err_out:lockdep_unregister_key(key);kfree(cp);return error;
}

kset_register 详细分析见 Linux 下注册分析(1)# kset_register

sysfs_create_groups 详细分析见 Linux 下注册分析(1)# sysfs_create_groups

3、class_create

class_create
kzalloc(sizeof(*cp), GFP_KERNEL)
class_register(cls)
struct class *class_create(const char *name)
{struct class *cls;int retval;cls = kzalloc(sizeof(*cls), GFP_KERNEL);	// 分配 class 空间if (!cls) {retval = -ENOMEM;goto error;}cls->name = name;cls->class_release = class_create_release;retval = class_register(cls);		// 注册 class,见上面 class_registerif (retval)goto error;return cls;error:kfree(cls);return ERR_PTR(retval);
}

    由上可以看出 class_create 在分配 class 结构体后,然后再调用 class_register 函数。

4、class_interface_register

// drivers/base/class.c
int class_interface_register(struct class_interface *class_intf)
{struct subsys_private *sp;const struct class *parent;struct class_dev_iter iter;struct device *dev;if (!class_intf || !class_intf->class)return -ENODEV;parent = class_intf->class;sp = class_to_subsys(parent);	// 获取 class 的 subsys_private if (!sp)return -EINVAL;/** Reference in sp is now incremented and will be dropped when* the interface is removed in the call to class_interface_unregister()*/mutex_lock(&sp->mutex);// 把 class_interface 链到 sp->interfaces 上list_add_tail(&class_intf->node, &sp->interfaces);if (class_intf->add_dev) {class_dev_iter_init(&iter, parent, NULL, NULL);while ((dev = class_dev_iter_next(&iter)))class_intf->add_dev(dev);class_dev_iter_exit(&iter);}mutex_unlock(&sp->mutex);return 0;
}

【Linux内核|驱动模型】bus/class/device/driver


   
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/68074.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

环境安装与配置:全面了解 Go 语言的安装与设置

在学习 Go 语言之前,首先需要确保开发环境已正确安装和配置。本部分将详细介绍如何在不同平台(Windows、macOS 和 Linux)上安装 Go 语言,以及如何进行环境变量配置和工作空间的设置。 一、安装 Go 语言 1. Windows 安装方法 下载…

快速排序:一种高效的排序算法

前言 排序是最基本和最常用的操作之一。无论是数据处理、搜索优化,还是各种应用程序的内部逻辑,排序算法的选择都直接影响到程序的性能。快速排序(Quick Sort)作为一种典型的分治算法,以其平均时间复杂度 O(n log n) 和优越的实际表现,成为了现代编程中最常用的排序算法…

第十五届蓝桥杯大赛软件赛省赛Java 大学 B 组(1、2题)

1.报数游戏 问题描述 小蓝和朋友们在玩一个报数游戏。由于今年是 2024 年,他们决定要从小到大轮流报出是 20或 24 倍数的正整数。前 10 个被报出的数是:20,24,40,48,60,72,80,96,100,120。请问第 202420242024个被报出的数是多少? 答案提交 这是一道结果…

批量修改图片资源的属性。

Unity版本2022.3 如图,比如我们想要修改图片的属性的时候,大部分都是 TextureImporter importer (TextureImporter)AssetImporter.GetAtPath("Assets/1.png"); // 获取文件 importer.xxxxxxx xxxxxxx; // 修改属性到这里没什么问题&#xf…

WebSocket异步导出

WebSocket异步导出 1、安装sockjs-client和stompjs2、连接后台3、vite.config.ts 配置反向代理4、导出并实时通信5、 封装WebSocket 文件注册登录(城通网盘) 1、安装sockjs-client和stompjs import SockJS from sockjs-client/dist/sockjs.min.js import Stomp from stompjs2、…

基于神经网络的视频编码NNVC(1):帧内预测

在H.266/VVC发布后,基于传统编码框架提升压缩率越来越难,随着深度学习的发展,研究人员开始尝试将神经网络引入编码器。为此,JVET工作组在2020年成立AHG11小组来专门进行基于神经网络的视频编码的研究。 为了方便研究,工…

C语言初阶牛客网刷题—— HJ97 记负均正【难度:简单】

1. 题目描述 牛客网在线OJ题 1、首先输入要输入的整数个数 n ,然后输入 n 个整数。输出为 n 个整数中负数的个数,和所有正整数的平均值, 结果保留一位小数。 注意: 0 即不是正整数,也不是负数,不计入计算&…

算法基础 -- 算法竞赛基础学习指南

算法竞赛基础学习指南 算法竞赛(如 ACM-ICPC、CCPC、NOI、LeetCode 周赛、Codeforces 等)是一项考察编程能力、算法知识和逻辑思维的综合性竞赛。要在竞赛中取得优异成绩,需要打下扎实的基础,积累丰富的经验。本文将从多个方面整…

蒙操作系统(HarmonyOS)

鸿蒙操作系统(HarmonyOS)是由华为技术有限公司开发的面向未来、面向全场景的分布式操作系统。它旨在为各种不同类型的设备提供统一的操作系统和无缝的智能体验,从智能手机到可穿戴设备,再到智能家居产品等。在鸿蒙的应用生态中&am…

【Web开发】一步一步详细分析使用Bolt.new生成的简单的VUE项目

https://bolt.new/ 这是一个bolt.new生成的Vue小项目,让我们来一步一步了解其架构,学习Vue开发,并美化它。 框架: Vue 3: 用于构建用户界面。 TypeScript: 提供类型安全和更好的开发体验。 Vite: 用于快速构建和开发 主界面如下&#xff1a…

Rabbitmq高级特性之消费方确认

背景: 发送方发送消息之后,到达消费端之后,可能会有以下情况:消息处理成功,消息处理异常。RabbitMQ在向消费者发送消息之后,就会把这条消息给删除掉,那么第二种情况,就会造成消息丢…

基于微信小程序的健身管理系统设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…

Couchbase UI: Server

在 Couchbase UI 中的 Server(服务器)标签页主要用于管理和监控集群中的各个节点。以下是 Server 标签页的主要内容和功能介绍: 1. 节点列表 显示集群中所有节点的列表,每个节点的详细信息包括: 节点地址&#xff1…

Spark Streaming编程基础

文章目录 1. 流式词频统计1.1 Spark Streaming编程步骤1.2 流式词频统计项目1.2.1 创建项目1.2.2 添加项目依赖1.2.3 修改源目录1.2.4 添加scala-sdk库1.2.5 创建日志属性文件 1.3 创建词频统计对象1.4 利用nc发送数据1.5 启动应用,查看结果 2. 编程模型的基本概念3…

git和idea重新安装后提交异常

场景:我重装了系统,idea装了2024.3版本的,git也重新装了,但是项目中还是有.git文件夹的,下载了idea的码云插件后,提交报错如下: 异常:Error updating changes: detected dubious ow…

Pix2Pix:图像到图像转换的条件生成对抗网络深度解析

在深度学习的广阔领域中,图像到图像的转换任务一直是研究者和开发者们关注的热点。Pix2Pix,作为一种基于条件生成对抗网络(Conditional Generative Adversarial Networks, CGANs)的模型,自2017年由Phillip Isola等人提…

OpenCV imread函数读取图像__实例详解

OpenCV imread函数读取图像__实例详解 本文目录: 零、时光宝盒 一、imread函数定义 二、imread函数支持的文件格式 三、imread函数flags参数详解 (3.1)、Flags-1时,样返回加载的图像(使用alpha通道,否…

Spring 框架基础:IOC 与 AOP 原理剖析及面试要点

在上一篇中,我们深入探讨了 Java 反射机制,了解了它在运行时动态操作类和对象的强大能力。而今天,我们将进入 Spring 框架的世界。Spring 框架作为 Java 企业级开发中最流行的框架之一,极大地简化了企业级应用的开发过程。对于春招…

ssm基于HTML5的红酒信息分享系统

SSM基于HTML5的红酒信息分享系统是一个专注于红酒领域的综合性信息平台,旨在为红酒爱好者、从业者以及普通消费者提供一个便捷的交流与获取红酒相关信息的空间。 一、系统背景与意义 随着人们生活水平的提高和消费观念的转变,红酒作为一种高雅的饮品&a…

【python】subprocess.Popen执行adb shell指令进入linux系统后连续使用指令,出现cmd窗口阻塞问题

问题描述 subprocess.Popen执行adb shell指令进入linux系统后出现cmd窗口阻塞问题,需要手动关闭cmd才会继续执行其他指令。 解决方案 1、cmd指令后面加入exit\n关闭exe进程 2、subprocess.Popen()添加内置参数creationflagssubprocess.CREATE_NO_WINDOW隐藏窗口弹…