设备模型2

前言

在上一篇中,我们大致描述了LINUX设备模型,我们先来总结一下三要素的关系。

 

Linux设备模型 - 哥哥 - 哥哥

 

从图中可以看出,Linux设备模型就是"总线、设备、驱动、类"这四个概念之前的相互关系;这也是Linux2.6内核抽象出来的用于管理系统中所有设备的模型图;
简单地描述设备模型的层次关系如下:
1、驱动核心中可以注册多种类型的总线(bus_type);
2、每一种类型的总线下面可以挂载许多设备(device);
3、每一种类型的总线可以使用很多设备驱动(device_driver);
4、每一个驱动程序可以管理一组设备;
这种基本关系的建立源于实际系统中各种总线、设备、驱动、类结构的抽象;

 

设备模型之kobject、kset

 

kobject是设备模型中一个很基本的概念,最初支持为了支持引用计数,但是随着时间的转移,它承担了越来越多的任务:

1)对象的引用计数

2)SYS表述

3)数据结构关联

4)热插拔处理

 

 

它的定义如下:

struct kobject {

//名称
 constchar  *name;


 struct list_head entry;

//指向kobject的父对象,以此来在内核中构造一个对象层次结构,并且可以将多个对象之间的关系表现初来,这就是sysfs的真相:一个用户空间的文件系统,用来表示内核中kobject对象的层次结构。
 structkobject  *parent;


 structkset  *kset;
 struct kobj_type *ktype;
 struct sysfs_dirent *sd;


 structkref  kref;
 unsigned int state_initialized:1;
 unsigned int state_in_sysfs:1;
 unsigned int state_add_uevent_sent:1;
 unsigned int state_remove_uevent_sent:1;
 unsigned int uevent_suppress:1;
};

一个kobject存在的意义在于把高级对象连接到设备模型上。kobject正如最顶层的基类,而其他类则是派生物,它实现了一系列方法,对自身并没有额数的作用,但是对其他对象却非常有效。

这句话可以这么理解,在LINUX中,是用C语言实现的,没有对象的概念,但是kobject被包含在各个结构中,就如同面向对象的的基类,根据它描述的父子兄弟关系,把各个结构实例联系起来,想成目录结构。现在回过头去看看总线,设备,驱动的结构定义中其实都有这个KOBJECT的影子,只是在前面我们分析的时候没有把列出来。

kobject的初始化:
1首先使用memest函数将整个kobject清零。
2调用kobject_init()函数。设置结构内部的一些成员。void kobject_init(struct kobject*kobj);kobject_init设置kobject的引用计数为 1。
3设置kobject的名字,这是sysfs入口中使用的名字。int kobject_set_name(struct kobject*kobj, const char *format, ...)

kobject的引用计数:
kobject 的其中一个关键函数是作为一个引用计数器, 给一个它被嵌入的对象. 只要对这个对象的引用存在, 这个对象(和支持它的代码)必须继续存在.
struct kobject *kobject_get(struct kobject *kobj);
void kobject_put(struct kobject *kobj);

释放函数和 kobject 类型:
通知由 kobject 的一个释放函数来完成. 常常地, 这个方法有一个形式如下:
void my_object_release(struct kobject *kobj)
{
    structmy_object *mine = container_of(kobj, struct my_object, kobj);
   kfree(mine);
}
有一点需要注意:每一个kobject都必须有一个release方法,并且kobject在该方法被调用前必须保持不变。
而需要在意一点,release函数并没有包含在kobject自身内,而是与包含kobject的结构类型相关联的kobj_type数据结构负责对该类型进行跟踪。

注意结构中的ktype,以及SYSFS_OPS,见下边SYS相关的分析。
struct kobj_type
{
    void(*release)(struct kobject *);//保存kobject类型的release函数
    structsysfs_ops *sysfs_ops;
    structattribute ** default_attrs;
}


kobject层次结构、kset

内核用kobject结构将各个对象连接起来组成一个分层的结构体系,从而与模型化的子系统相匹配。有两种独立的机制用于连接:parent指针和kset
在kobject结构的parent成员中,保存了另外一个kobject结构的指针,这个结构表示了分层结构中上一层的节点,而parent最重要的用途是在sysfs分层结构中定位对象。

kset是嵌入相同类型结构的kobject集合,但是不同之处在于,kobject在乎的是对象的类型,而kset关心的是对象的集合与聚合。需要注意的是,kset总是在sysfs中出现,一旦设置了kset并把它添加到系统中,将在sysfs中创建一个目录。kobject不必在sysfs中表示,但是kset中的每一个kobject成员都将在sysfs中得到表述。

创建一个对象时,要把一个kobject添加到kset中,要先将kobject的kset成员指向目的的kset,调用extern intkobject_register(struct kobject *kobj);
这个函数仅仅是一个 kobject_init 和 kobject_add 的结合.

struct kset {
 struct list_head list;
 spinlock_t list_lock;
 struct kobject kobj;
 const struct kset_uevent_ops *uevent_ops;
};
对于初始化和设置, kset有一个接口非常类似于 kobjects.
void kset_init(struct kset *kset);
int kset_add(struct kset *kset);
int kset_register(struct kset *kset);
void kset_unregister(struct kset *kset);

为管理 ksets 的引用计数, 情况大概相同:
struct kset *kset_get(struct kset *kset);
void kset_put(struct kset *kset);

一个 kset 还有一个名子, 存储于嵌入的 kobject. 因此, 如果你有一个 kset 称为 my_set,你将设置它的名子用:
kobject_set_name(&my_set->kobj, "Thename");

ksets 还有一个指针( 在 ktye 成员 )指向 kobject_type 结构来描述它包含的 kobject.这个类型优先于在 kobject 自身中的 ktype 成员. 结果, 在典型的应用中, 在 struct kobject 中的ktype 成员被留为 NULL, 因为 kset 中的相同成员是实际使用的那个.

低层sysfs操作
(什么是SYSFS?? 我们就把它先看做设备文件系统,用来管理系统的各种设备,驱动,总线,类的文件系统)。
kobject隐藏在sysfs文件系统之后的机制,对于sysfs每个目录,内核中都会存在一个对应的kobject。每一个kobject都输出一个或者多个属性。在sysfs目录中表现为文件,其中的内容由内核生成。在<linux/sysfs.h>中包含了sysfs工作代码。

使kobject在sysfs出现仅仅是调用kobject_add的事情.kobjects的sysfs入口一直为目录,因此一个对kobject_add的调用导致在sysfs中创建一个目录.常常地, 这个目录包含一个或多个属性;
分配给 kobject 的名子( 用 kobject_set_name ) 是给 sysfs 目录使用的名子. 因此, 出现在sysfs 层次的相同部分的 kobjects 必须有独特的名子. 分配给 kobjects 的名子也应当是合理的文件名子:它们不能包含斜线字符, 并且空白的使用强烈不推荐.
sysfs 入口位于对应 kobject 的 parent 指针的目录中. 如果 parent 是 NULL 当kobject_add 被调用时, 它被设置为嵌在新 kobject 的 kset 中的 kobject;

当被创建时, 每个kobject被给定一套缺省属性. 这些属性通过kobj_type结构来指定.

default_attr 成员列举了对每个这样类型的 kobject 被创建的属性, 并且 sysfs_ops提供方法来实现这些属性.

struct attribute {
 char *name;
 struct module *owner;
 mode_t mode;
};

在这个结构中, name 是属性的名子( 如同它出现在 kobject 的 sysfs 目录中), owner是一个指向模块的指针(如果有一个), 模块负责这个属性的实现, 并且 mode 是应用到这个属性的保护位. mode 常常是S_IRUGO 对于只读属性; 如果这个属性是可写的, 你可以扔出 S_IWUSR 来只给 root 写权限( modes 的宏定义在<linux/stat.h> 中). default_attrs列表中的最后一个入口必须用 0 填充.

实现这些属性则需要kobj_type->sysfs_ops成员, 它指向一个结构, 定义为:

struct sysfs_ops {
 ssize_t (*show)(struct kobject *kobj, structattribute *attr, char *buffer);
 ssize_t (*store)(struct kobject *kobj, structattribute *attr, const char *buffer, size_t size);
};

无论何时一个属性从用户空间读取, show 方法被用一个指向 kobject 的指针和适当的属性结构来调用.这个方法应当将给定属性值编码进缓冲, 要确定没有覆盖它( 它是 PAGE_SIZE 字节), 并且返回实际的被返回数据的长度.sysfs 的惯例表明每个属性应当包含一个单个的, 人可读的值; 如果你有许多消息返回, 你可要考虑将它分为多个属性.

同样的 show 方法用在所有的和给定 kobject 关联的属性. 传递到函数的 attr 指针可用来决定需要哪个属性. 一些show 方法包含对属性名子的一系列测试. 其他的实现将属性结构嵌入另一个结构, 来包含需要返回属性值的信息; 在这种情况下,container_of 可能用在 show 方法中来获得一个指向嵌入结构的指针.

store 方法类似; 它应当将存在缓冲的数据编码( size 包含数据的长度, 这不能超过 PAGE_SIZE ),存储和以任何有意义的的方式响应新数据, 并且返回实际编码的字节数. store 方法只在属性的许可允许写才被调用. 当编写一个store 方法时, 不要忘记你在接收来自用户空间的任意信息; 你应当在采取对应动作之前非常小心地验证它. 如果到数据不匹配期望,返回一个负的错误值, 而不是可能地做一些不想要的和无法恢复的事情. 如果你的设备输出一个自销毁的属性,你应当要求一个特定的字符串写到那里来引发这个功能; 一个偶然的, 随机写应当只产生一个错误.

非默认属性:

多数情况下,kobject类型的default_attrs成员描述了kobject拥有的所有属性。但是我们还可以根据需要对kobject捏的树型进行添加和删除,希望在kobject的sysfs目录中添加新的属性,只需要填写一个个attribute结构,并调用下面的函数:
int sysfs_create_file(struct kobject *kobj, struct attribute*attr);
将用attribute中的名字创建文件,并返回0,否则返回一个错误编码。而下面的函数则是删除属性:
int sysfs_remove_file(struct kobject *kobj, struct attribute*attr);

符号链接:

sysfs 文件系统有通常的树结构, 反映它代表的 kobjects 的层次组织.sysfs 子树 (/sys/devices)代表所有的系统已知的设备, 而其他的子树( 在 /sys/bus 之下)表示设备驱动.这些树,不代表驱动和它们所管理的设备间的关系.展示这些附加关系需要额外的指针,指针在sysfs中通过符号连接实现.

创建符号连接:
int sysfs_create_link(struct kobject *kobj, struct kobject *target,char *name);
这个函数创建一个连接(称为name)指向目标的sysfs入口作为一个kobj的属性.它是一个相对连接,因此它不管sysfs在任何特殊的系统中安装在哪里都可用.
去除符号连接可使用:
void sysfs_remove_link(struct kobject *kobj, char *name);

 

二进制属性:

struct bin_attribute {
 struct attribute attr;
 size_t   size;
 void   *private;
 ssize_t (*read)(struct file *, struct kobject *,struct bin_attribute *,
   char *,loff_t, size_t);
 ssize_t (*write)(struct file *,struct kobject *,struct bin_attribute *,
    char *,loff_t, size_t);
 int (*mmap)(struct file *, struct kobject *,struct bin_attribute *attr,
     struct vm_area_struct *vma);
};

 

int  sysfs_create_bin_file(struct kobject *kobj,struct bin_attribute *attr); 
我们可以显示的定义一个KOBJ的二进制属性,这三个函数指针对应月SYS_***,记住这点就够了。用的地方不是特别多,在我们PROBE一个设备的时候,可以针对该驱动的KOBJ设置二进制属性,然后就可以在用户空间通过VFS来访问这个设备了。以后降到具体的驱动的例子再详细探讨。
 

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

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

相关文章

angular自定义指令详解

指令&#xff08;directive&#xff09;是angular里面最核心也是最难懂的东西&#xff0c;在慕课网看了下大漠穷秋老湿的视频&#xff0c;自己百度半天做了一些小test&#xff0c;总算把一切都搞明白了。 先列出学习来源&#xff1a; 指令中controller和link的区别&#xff1a;…

delphi7aes加密解密与java互转_跨语言(java vs python vs nodejs)的RSA加解密问题探讨

多次被问到这样的问题&#xff1a;java服务端的rsa加密操作已经完成&#xff0c;返回一个16进制的字符串给python平台&#xff0c;但是在python进行私钥解密的时候发现行不通。。。。前端python加密&#xff0c;后端用java解密&#xff0c;解不出来还有诸如nodejs从理论上来说&…

利用dft的定义计算dft的matlab程序_CP2K教程系列之静态计算(Pymatflow篇)

本系列CP2K教程是《CP2K菜根谭》的升级版&#xff0c;在旧版基础上添加了如何结合Pymatflow工具简化计算流程的内容。话不多说&#xff0c;本文将为您带来CP2K系列教程中的静态计算部分。静态计算设置静态计算是大多数人接触第一性原理计算后第一次运行的计算类型。很多其它类型…

微软是如何戏耍程序员们的

2019独角兽企业重金招聘Python工程师标准>>> 别用微软的东西。商业目的性太强&#xff0c;千万别被微软牵着鼻子走&#xff0c;血淋淋的教训。微软推出的垃圾多了去了。它什么都想做&#xff0c;很多都没做好&#xff1a; MFC&#xff1a;Win31时代出生&#xff0c;…

3d立体相册特效html网页代码_新闻类网页正文通用抽取器

项目起源开发这个项目&#xff0c;源自于我在知网发现了一篇关于自动化抽取新闻类网站正文的算法论文——《基于文本及符号密度的网页正文提取方法》这篇论文中描述的算法看起来简洁清晰&#xff0c;并且符合逻辑。但由于论文中只讲了算法原理&#xff0c;并没有具体的语言实现…

字节数组转换为图片_每日一课 | Python 3 TypeError:无法将“字节”对象隐式转换为str...

将Python 2套接字示例转换为Python 3whois.py import sysimport sockets socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.connect(("whois.arin.net", 43))s.send((sys.argv[1] "\r\n").encode())response ""while True: data s.re…

加速度计和陀螺仪数据融合

本帖翻译自 IMU&#xff08;加速度计和陀螺仪设备&#xff09;在嵌入式应用中使用的指南。这篇文章主要介绍加速度计和陀螺仪的数学模型和基本算法&#xff0c;以及如何融合这两者&#xff0c;侧重算法、思想的讨论介绍本指南旨在向兴趣者介绍惯性MEMS&#xff08;微机电系统&a…

循环嵌套练习题

//BOSS://让用户输入一个奇数&#xff0c;打印菱形&#xff0c;最长的行内容个数为用户输入的个数&#xff0c;并且由英文字母拼接而成//比如用户输入了7// A// ABA// ABCBA// ABCDCBA// ABCBA// ABA// A//1、接收并判断用户输入的是不是数字 try{#region 解法一…

python leetcode_leetcode 介绍和 python 数据结构与算法学习资料

for &#xff08;刚入门的编程&#xff09;的高中 or 大学生leetcode 介绍leetcode 可以说是 cs 最核心的一门“课程”了&#xff0c;虽然不是大学开设的&#xff0c;但基本上每一个现代的高水平的程序员都修过这门“课程”&#xff08;或者类似的课程&#xff0c;比如数据结构…

IOS 为UILabel添加长按复制功能

IOS 为UILabel添加长按复制功能 在iOS中下面三个控件&#xff0c;自身就有复制-粘贴的功能&#xff1a; 1、UITextView 2、UITextField 3、UIWebView UIKit framework提供了几个类和协议方便我们在自己的应用程序中实现剪贴板的功能。 1、UIPasteboard&#xff1a;我们可以向其…

navicat 的查询功能

navicat的查询的位置在&#xff1a; 在编辑器界面写代码&#xff0c;代码完成后点左上角的运行。 代码&#xff1a; create&#xff08;创建&#xff09; table&#xff08;一个表&#xff09; <xxx>尖括号内的内容必填——我要创建并查询一个名叫做xxx的表 &#xff08…

c++ sleep函数_Linux 多线程应用中如何编写安全的信号处理函数

关于代码的可重入性&#xff0c;设计开发人员一般只考虑到线程安全&#xff0c;异步信号处理函数的安全却往往被忽略。本文首先介绍如何编写安全的异步信号处理函数&#xff1b;然后举例说明在多线程应用中如何构建模型让异步信号在指定的线程中以同步的方式处理。Linux 多线程…

CoreAnimation (CALayer 动画)

CoreAnimation基本介绍&#xff1a; CoreAnimation动画位于iOS框架的Media层CoreAnimation动画实现需要添加QuartzCore.FrameworkCoreAnimation基本上是LayerAnimationCoreAnimation分类&#xff1a; CoreAnimation作用&#xff1a; CoreAnimation CALayer基本介绍 CALayer的常…

汇编为什么分段执行总是执行不了_iOS汇编教程(六)CPU 指令重排与内存屏障...

系列文章iOS 汇编入门教程(一)ARM64 汇编基础iOS 汇编入门教程(二)在 Xcode 工程中嵌入汇编代码iOS 汇编入门教程(三)汇编中的 Section 与数据存取iOS 汇编教程(四)基于 LLDB 动态调试快速分析系统函数的实现iOS 汇编教程(五)Objc Block 的内存布局和汇编表示前言具有 ARM 体系…

GD32 使用stm32 固件库

1、 系统 1) 晶振起振区别 描述&#xff1a;启动时间&#xff0c;GD32 与STM32 启动时间都是2ms&#xff0c;实际上GD 的执行效率快&#xff0c;所以ST 的HSE_STARTUP_TIMEOUT ((uint16_t)0x0500)是2ms&#xff0c;但是这个宏定义值在GD 上时间就更加短了&#xff0c;所以要加大…

js反混淆还原工具_SATURN反混淆框架

本文为看雪论坛精华文章看雪论坛作者ID&#xff1a;梦野间摘要&#xff1a;近几年&#xff0c;软件的混淆强度一直在不断提升。基于编译器的混淆已经成为业界事实上的标准&#xff0c;最近的一些论文也表明软件的保护方式使用的是编译器级别的混淆。在这篇文章中&#xff0c;我…

python 多线程并发_寻找python大神!!!python如何多线程并发?

不是大神。尝试回答一下。 首先解释下什么叫做线程&#xff0c;什么叫做进程&#xff0c;在解释这两个概念前&#xff0c;我们还需要明白什么叫做GIL全局解释器锁。GIL 全局解释器锁&#xff1a; GIL(全局解释器锁&#xff0c;GIL 只有cpython有)&#xff1a;在同一个时刻&…

Nginx/Apache发大招

导读网站程序的上传目录通常是不需要PHP执行解释权限&#xff0c;通过限制目录的PHP执行权限可以提网站的安全性&#xff0c;减少被攻击的机率。下面和大家一起分享下如何在Apache和Nginx禁止上传目录里PHP的执行权限。 Apache下禁止指定目录运行PHP脚本在虚拟主机配置文件中增…

dmp文件查看表空间_innoDb文件

一&#xff0e;文件总体概述InnoDb文件主要有以下文件1. 参数文件&#xff1a;启动需要的各种参数作2. 日志文件&#xff1a;记录mysql实例某种条件做出的响应而写入的文件&#xff0c;如错误日志、二进制日志、慢查询日志、查询日志等3. Socket文件&#xff1a;连接需要的文件…

论文笔记之:Deep Attention Recurrent Q-Network

Deep Attention Recurrent Q-Network 5vision groups 摘要&#xff1a;本文将 DQN 引入了 Attention 机制&#xff0c;使得学习更具有方向性和指导性。&#xff08;前段时间做一个工作打算就这么干&#xff0c;谁想到&#xff0c;这么快就被这几个孩子给实现了&#xff0c;自愧…