kobject所处理的函数清单,都是一些代表其他对象完成的服务。
它存在的意义在于把高级对象连接到设备模型上。
kobject用于控制对大型域(domain)相关对象的访问。
在C语言中使用在一个结构体中嵌入另外一个结构的技术。
container_of宏
对包含在cdev结构中的、名为kp的kobject结构指针进行转换的代码如下:
底层控制kobject引用计数的函数有kobject_get和kobject_put。
kobject_init设置引用计数为1.
创建对cdev结构的引用时,也需要创建包含它的模块的引用。
cdev_get使用try_module_get增加模块的使用计数。
引用计数不为创建kobject的代码所直接控制,因此当kobject的最后一个引用计数不再存在时,必须异步地通知。
通知是使用kobject的release方法实现的。
每个kobject都必须有一个release方法,并且kobject在该方法被调用前必须保持不变(处于稳定状态)。
在kobj_type的release成员中,保存的是这种kobject类型的release函数指针。
每个kobject都需要有一个相应的kobj_type结构。
在两个不同的地方可以找到这个结构的指针。
内核用kobject结构将各个对象连接起来组成一个分层的结构体系,从而与模型化的子系统相匹配。
有两种独立的机制用于连接:parent指针和kset。
parent指针最重要的用途是在sysfs分层结构中定位对象。
kset像是kobj_type的扩充。
这样同种类型的对象可以出现在不同的集合中。
在每个kset内部,包含了自己的kobject,并且可以用多种处理kobject的方法处理kset。
kset总是在sysfs中出现,一旦设置了kset并把它添加到系统中,将在sysfs中创建一个目录。kobject不必在sysfs中表示,但是kset中的每一个kobject成员都将在sysfs中得到表述。
在kset中包含的最重要的内容是对象的引用。
kobject_register是kobject_init和kobject_add的简单组合。
kobject_unregister是kobject_del和kobject_put的组合。
kset中有一个指针指向kobj_type结构,用来描述它所包含的kobject。这类型的使用优先于kobject中的ktype。
kset中包含了一个子系统指针(subsys)。
子系统是对整个内核中一些高级部分的表述。
子系统通常显示在sysfs分层结构中的顶层。
内核中的子系统包括block_subsys(对块设备来说是/sys/block)、devices_subsys(/sys/devices,设备分层结构的核心)以及内核所知晓的用于各种总线的特定子系统。
一个驱动程序的作者几乎不需要创建一个新的子系统。
最终要做的是添加一个新类。
每一个kset都必须属于一个子系统。
子系统的成员将帮助内核在分层结构中定位kset,rwsem信号量被用于串行访问kset内部的链表。
通过kset结构,可以找到包含kset的每一个子系统。
但无法直接从subsystem结构中找到子系统所包含的多个kset。
低层sysfs操作
kobject是隐藏在sysfs虚拟文件系统后的机制,对于sysfs中的每个目录,内核中都会有一个对应的kobject。
每一个kobject都输出一个或者多个属性,它们在kobject的sysfs目录中表现为文件,其中的内容由内核生成。
只要调用Kobject_add,就能在sysfs中显示kobject。
kobject在sysfs中的入口始终是一个目录。
分配给kobject的名字是sysfs中的目录名。
sysfs入口在目录中的位置对应于kobject的parent指针。
如果调用kobject_add时,parent是NULL,它将被设置为嵌入到新kobject的kset中的kobject,这样,sysfs分层结构通常与kset创建的内部结构相匹配。
如果parent和kset都是NULL,则会在最高层创建sysfs目录。
二进制属性
对创建一个可以处理大量二进制数据属性的需求很少发生,当在用户空间和设备之间传递不可改变的数据时,有可能产生这种需求。比如向设备上载固件时。
如果在系统中遇到这样的设备,就可以运行用户空间程序(通过热插拔机制),这些程序使用二进制的sysfs属性将固件代码传递给内核。
sysfs文件系统具有常用的树形结构,以反映kobject之间的组织层次关系。
一个sysfs的子树(/sys/devices)表示了所有系统知晓的设备。
其他的子树(在/sys/bus下)表示了设备的驱动程序。
在sysfs中,通过符号链接来表示驱动程序及其所管理的设备之间的关系。
在sysfs中创建符号链接时使用:
int sysfs_create_link(struct kobject *kobj, struct kobject *target, char *name);
void sysfs_remove_link(struct kobject *kobj, char *name);
一个热插拔事件是从内核空间发送到用户空间的通知,它表明系统配置出现了变化。
无论kobject被创建还是被删除,都会产生这种事件。
热插拔事件会导致对/sbin/hotplug程序的调用,该程序通过加载驱动程序,创建设备节点,挂载分区,或者其他正确的动作来响应事件。
当把kobject传递给kobject_add或者kobject_del时,才会真正产生这些事件。
在事件被传递到用户空间之前,处理kobject的代码能够为用户空间添加信息,或者完全禁止事件的产生。
对热插拔事件的实际控制,是由保存在kset_hotplug_ops结构中的函数完成的。
可以在kset结构的hotplug_ops成员中发现指向这个结构的指针。
当内核要为指定的kobject产生事件时,都要调用filter函数。
在调用用户空间的热插拔程序时,相关子系统的名字将作为唯一的参数传递给它。hotplug方法负责提供这个名字,它将返回一个适合传递给用户空间的字符串。
任何热插拔脚本所需要知道的信息将通过环境变量传递。
最后一个hotplug方法(hotplug)会在调用脚本前,提供添加环境变量的机会。
热插拔事件的创建通常被总线驱动程序级别上的逻辑所控制。
总线、设备和驱动程序
只有很少的驱动程序作者需要添加一个新的总线类型。
总线是处理器与一个或者多个设备之间的通道。
在设备模型中,所有的设备都通过总线相连。(一个USB控制器通常是一个PCI设备)
设备模型展示了总线和它们所控制的设备之间的连接。
在Linux设备模型中,用bus_type结构表示总线。
每个总线都有自己的子系统。然而这些子系统并不在sysfs中的顶层,相反,会在总线子系统下面发现它们。
一个总线包含连个kset,分别代表了总线的驱动程序和插入总线的所有设备。
总线属性
几乎在Linux设备模型的每一层都提供了添加属性的函数。
设备
在最底层,Linux系统中的每一个设备都用device结构的一个实例来表示。
一个实际的总线是一个设备,因此必须被单独注册。
sysfs中的设备入口可以有属性。
device结构中包含了设备模型核心用来模拟系统的信息。
设备模型跟踪所有系统所知道的设备。
进行跟踪的主要原因是让驱动程序核心协调驱动程序与新设备之间的关系。
设备驱动程序可以导出信息和配置变量,而这些东西都是独立于任何特定设备的。
类
类是一个设备的高层视图,它抽象出了低层的实现细节。
类允许用户空间使用设备所提供的功能,而不关心设备时如何连接的,以及如何工作的。
几乎所有的类都显示在/sys/class目录中。
类成员通常被上层代码所控制,而不需要来自驱动程序的明确支持。
当子系统创建一个类时,它将完全拥有这个类,因此不必担心哪个模块拥有那些属性。
为了管理类,驱动程序核心导出了两个不同的接口。
class_simple接口
完整的类接口
在插拔设备时,类会产生热插拔事件。
从用户角度看,热插拔是在内核与用户之间,通过调用/sbin/hotplug程序的交互。
当用户向系统添加或者删除设备时,会产生热插拔事件。这会导致内核调用用户空间程序/sbin/hotplug。它是一个典型的bash脚本程序,只是将执行权传递给其他一系列放置在/etc/hotplug.d/目录树中的程序。
它存在的意义在于把高级对象连接到设备模型上。
kobject用于控制对大型域(domain)相关对象的访问。
在C语言中使用在一个结构体中嵌入另外一个结构的技术。
container_of宏
对包含在cdev结构中的、名为kp的kobject结构指针进行转换的代码如下:
struct cdev *device = container_of(kp, struct cdev, kobj);
底层控制kobject引用计数的函数有kobject_get和kobject_put。
kobject_init设置引用计数为1.
创建对cdev结构的引用时,也需要创建包含它的模块的引用。
cdev_get使用try_module_get增加模块的使用计数。
引用计数不为创建kobject的代码所直接控制,因此当kobject的最后一个引用计数不再存在时,必须异步地通知。
通知是使用kobject的release方法实现的。
每个kobject都必须有一个release方法,并且kobject在该方法被调用前必须保持不变(处于稳定状态)。
在kobj_type的release成员中,保存的是这种kobject类型的release函数指针。
每个kobject都需要有一个相应的kobj_type结构。
在两个不同的地方可以找到这个结构的指针。
内核用kobject结构将各个对象连接起来组成一个分层的结构体系,从而与模型化的子系统相匹配。
有两种独立的机制用于连接:parent指针和kset。
parent指针最重要的用途是在sysfs分层结构中定位对象。
kset像是kobj_type的扩充。
一个kset是嵌入相同类型结构的kobject集合。
kobj_type结构关心的是对象的类型,kset结构关心的是对象的聚集与集合。这样同种类型的对象可以出现在不同的集合中。
在每个kset内部,包含了自己的kobject,并且可以用多种处理kobject的方法处理kset。
kset总是在sysfs中出现,一旦设置了kset并把它添加到系统中,将在sysfs中创建一个目录。kobject不必在sysfs中表示,但是kset中的每一个kobject成员都将在sysfs中得到表述。
把一个kobject添加到kset中去:先把kobject的kset成员指向目的kset,然后将kobject传递给下面的函数:
int kobject_add(struct kobject *kobj);
在kset中包含的最重要的内容是对象的引用。
kobject_register是kobject_init和kobject_add的简单组合。
kobject_unregister是kobject_del和kobject_put的组合。
kset中有一个指针指向kobj_type结构,用来描述它所包含的kobject。这类型的使用优先于kobject中的ktype。
kset中包含了一个子系统指针(subsys)。
子系统是对整个内核中一些高级部分的表述。
子系统通常显示在sysfs分层结构中的顶层。
内核中的子系统包括block_subsys(对块设备来说是/sys/block)、devices_subsys(/sys/devices,设备分层结构的核心)以及内核所知晓的用于各种总线的特定子系统。
一个驱动程序的作者几乎不需要创建一个新的子系统。
最终要做的是添加一个新类。
每一个kset都必须属于一个子系统。
子系统的成员将帮助内核在分层结构中定位kset,rwsem信号量被用于串行访问kset内部的链表。
通过kset结构,可以找到包含kset的每一个子系统。
但无法直接从subsystem结构中找到子系统所包含的多个kset。
低层sysfs操作
kobject是隐藏在sysfs虚拟文件系统后的机制,对于sysfs中的每个目录,内核中都会有一个对应的kobject。
每一个kobject都输出一个或者多个属性,它们在kobject的sysfs目录中表现为文件,其中的内容由内核生成。
只要调用Kobject_add,就能在sysfs中显示kobject。
kobject在sysfs中的入口始终是一个目录。
分配给kobject的名字是sysfs中的目录名。
sysfs入口在目录中的位置对应于kobject的parent指针。
如果调用kobject_add时,parent是NULL,它将被设置为嵌入到新kobject的kset中的kobject,这样,sysfs分层结构通常与kset创建的内部结构相匹配。
如果parent和kset都是NULL,则会在最高层创建sysfs目录。
默认属性
非默认属性二进制属性
对创建一个可以处理大量二进制数据属性的需求很少发生,当在用户空间和设备之间传递不可改变的数据时,有可能产生这种需求。比如向设备上载固件时。
如果在系统中遇到这样的设备,就可以运行用户空间程序(通过热插拔机制),这些程序使用二进制的sysfs属性将固件代码传递给内核。
sysfs文件系统具有常用的树形结构,以反映kobject之间的组织层次关系。
一个sysfs的子树(/sys/devices)表示了所有系统知晓的设备。
其他的子树(在/sys/bus下)表示了设备的驱动程序。
在sysfs中,通过符号链接来表示驱动程序及其所管理的设备之间的关系。
在sysfs中创建符号链接时使用:
int sysfs_create_link(struct kobject *kobj, struct kobject *target, char *name);
void sysfs_remove_link(struct kobject *kobj, char *name);
一个热插拔事件是从内核空间发送到用户空间的通知,它表明系统配置出现了变化。
无论kobject被创建还是被删除,都会产生这种事件。
热插拔事件会导致对/sbin/hotplug程序的调用,该程序通过加载驱动程序,创建设备节点,挂载分区,或者其他正确的动作来响应事件。
当把kobject传递给kobject_add或者kobject_del时,才会真正产生这些事件。
在事件被传递到用户空间之前,处理kobject的代码能够为用户空间添加信息,或者完全禁止事件的产生。
对热插拔事件的实际控制,是由保存在kset_hotplug_ops结构中的函数完成的。
可以在kset结构的hotplug_ops成员中发现指向这个结构的指针。
当内核要为指定的kobject产生事件时,都要调用filter函数。
在调用用户空间的热插拔程序时,相关子系统的名字将作为唯一的参数传递给它。hotplug方法负责提供这个名字,它将返回一个适合传递给用户空间的字符串。
任何热插拔脚本所需要知道的信息将通过环境变量传递。
最后一个hotplug方法(hotplug)会在调用脚本前,提供添加环境变量的机会。
热插拔事件的创建通常被总线驱动程序级别上的逻辑所控制。
总线、设备和驱动程序
只有很少的驱动程序作者需要添加一个新的总线类型。
总线是处理器与一个或者多个设备之间的通道。
在设备模型中,所有的设备都通过总线相连。(一个USB控制器通常是一个PCI设备)
设备模型展示了总线和它们所控制的设备之间的连接。
在Linux设备模型中,用bus_type结构表示总线。
每个总线都有自己的子系统。然而这些子系统并不在sysfs中的顶层,相反,会在总线子系统下面发现它们。
一个总线包含连个kset,分别代表了总线的驱动程序和插入总线的所有设备。
总线属性
几乎在Linux设备模型的每一层都提供了添加属性的函数。
设备
在最底层,Linux系统中的每一个设备都用device结构的一个实例来表示。
一个实际的总线是一个设备,因此必须被单独注册。
sysfs中的设备入口可以有属性。
device结构中包含了设备模型核心用来模拟系统的信息。
设备模型跟踪所有系统所知道的设备。
进行跟踪的主要原因是让驱动程序核心协调驱动程序与新设备之间的关系。
设备驱动程序可以导出信息和配置变量,而这些东西都是独立于任何特定设备的。
类
类是一个设备的高层视图,它抽象出了低层的实现细节。
类允许用户空间使用设备所提供的功能,而不关心设备时如何连接的,以及如何工作的。
几乎所有的类都显示在/sys/class目录中。
类成员通常被上层代码所控制,而不需要来自驱动程序的明确支持。
当子系统创建一个类时,它将完全拥有这个类,因此不必担心哪个模块拥有那些属性。
为了管理类,驱动程序核心导出了两个不同的接口。
class_simple接口
完整的类接口
在插拔设备时,类会产生热插拔事件。
热插拔
从内核角度看,热插拔是在硬件、内核、内核驱动程序之间的交互。从用户角度看,热插拔是在内核与用户之间,通过调用/sbin/hotplug程序的交互。
当用户向系统添加或者删除设备时,会产生热插拔事件。这会导致内核调用用户空间程序/sbin/hotplug。它是一个典型的bash脚本程序,只是将执行权传递给其他一系列放置在/etc/hotplug.d/目录树中的程序。