2.5 kobject编程模式
在sysfs中创建一个简单的子目录/sys/kernel/foo/,在这个目录下,还创建了1个文件:value。如果往这些文件中写入一个整数,随后可以读出。
kobject编程模式包括以下几个步骤。
1.定义内核对象结构
我们将这个内核对象结构命名为foo,前面提到,应该将struct kobject作为它的一个域,此外,定义另一个整型域对应于要读/写的属性。
2.定义属性类型
由于内核对象有属性,需要定义一个新的属性类型foo_attribute。它以struct attribute作为一个域,show和store是对属性的操作方法。
3.声明属性
接下来,我们用宏FOO_ATTR来声明要用到的value属性,它的访问权限为0666,show和store回调函数实现分别为value_show和value_store,它们将对sysfs文件系统中value文件的读/写操作转变为对foo_obj内核对象的value域的操作。
4.实现内核对象的sysfs操作
内核对象foo_obj的sysfs操作表(实际上是它所属设备类型的操作表)为foo_sysfs_op,对应的show和store回调函数分别实例化为foo_attr_show和foo_attr_store。
foo_attr_show和foo_attr_store的代码已经在前面给出。它们负责将kobject和attribute结构转换为具体的内核对象(foo_obj)和对象属性(foo_attribute),然后调用对象属性的相应方法。就这个例子来讲,它最终调用的是value_show和value_store函数。
5.定义内核对象释放方法
除了sysfs操作表,对象类型还应该定义释放内核对象的方法。对于内核对象foo_obj,释放方法被定义为foo_release。它在内核对象的引用计数递减到零时,释放内核对象占用的内存空间。
6.声明内核对象类型
为内核对象foo_obj定义专门的对象类型(foo_ktype),其中指定对象释放方法和sysfs操作方法。我们假设这个对象类型没有默认的对象属性,例子中的value属性是另外添加的。
7.封装对象属性添加和删除方法
我们需要将value属性添加到内核对象,或从内核对象删除,当然可以直接调用sysfs_create_file和sysfs_remove_file方法。但是大多数情况下,我们选择将这两个方法做一层封装。为此,定义了为具体内核对象foo_obj创建和删除sysfs属性的两个辅助函数:foo_create_file和foo_remove_file,它们的代码已经在前面给出。
8.定义对象创建和销毁方法
在创建时,需要为内核对象分配内存,初始化内核对象并添加到sysfs树。因为没有为kobject指定kset和设置parent,这个内核对象将自动被放在kset下边。
创建内核对象的方法被定义为create_foo_obj,它调用kobject_init_and_add,以foo_obj的内嵌kobject和foo_ktype为参数,并将其父对象设为kernel_kobj,这是内核中的一个全局变量,对应sysfs文件系统的目录/sys/kernel/,最终创建一个内核对象,并添加到sysfs文件系统。
销毁内核对象的方法被定义为destroy_foo_obj,它针对foo_obj的内嵌kboject调用kobject_put释放内核对象的引用计数,当减到0时,最终释放内核对象的内存空间。
9.实现模块加载和卸载方法
最后,需要实现模块加载和卸载方法。在模块加载方法中调用create_foo_obj创建内核对象,开始它的生命历程。在模块卸载方法中调用destroy_foo_obj,最终结束这个内核对象。