网站域名解绑,唐山哪个公司可以建网站,网站建立的连接不安全怎么解决,网站建设的技术指标前言
在上一篇中#xff0c;我们大致描述了LINUX设备模型#xff0c;我们先来总结一下三要素的关系。 从图中可以看出,Linux设备模型就是总线、设备、驱动、类这四个概念之前的相互关系;这也是Linux2.6内核抽象出来的用于管理系统中所有设备的模型图; 简单地描述…前言
在上一篇中我们大致描述了LINUX设备模型我们先来总结一下三要素的关系。 从图中可以看出,Linux设备模型就是总线、设备、驱动、类这四个概念之前的相互关系;这也是Linux2.6内核抽象出来的用于管理系统中所有设备的模型图; 简单地描述设备模型的层次关系如下: 1、驱动核心中可以注册多种类型的总线(bus_type); 2、每一种类型的总线下面可以挂载许多设备(device); 3、每一种类型的总线可以使用很多设备驱动(device_driver); 4、每一个驱动程序可以管理一组设备; 这种基本关系的建立源于实际系统中各种总线、设备、驱动、类结构的抽象; 设备模型之kobject、kset kobject是设备模型中一个很基本的概念最初支持为了支持引用计数但是随着时间的转移它承担了越来越多的任务
1对象的引用计数
2SYS表述
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来访问这个设备了。以后降到具体的驱动的例子再详细探讨。