3.ktype& Kset

3.1  ktype

l  用来描述一组kobject所具有的共同特性,用structkobj_type结构体来表示

struct kobj_type{

         void (*release)(struct kobject *kobj);

         const struct sysfs_ops *sysfs_ops;

         struct attribute **default_attrs;

         const struct kobj_ns_type_operations*(*child_ns_type)(struct kobject *kobj);

         const void *(*namespace)(struct kobject*kobj);

};

n  Release 函数当引用计数(kref)减到0时调用,完成销毁工作

n  Sysfs_ops定义属性的操作方法

struct sysfs_ops {

ssize_t     (*show)(struct kobject *, struct attribute *,char *);

ssize_t     (*store)(struct kobject *,struct attribute *,const char *,size_t);

constvoid *(*namespace)(struct kobject *, const struct attribute *);

};

Show方法用户空间读取属性时调用

Store方法用户空间写入属性时调用

n  Default_attrs 默认属性

struct attribute {

constchar                  *name;  /* 属性名,对应在sysfs中为文件名 */

mode_t                       mode;   /* 权限 */

};

 

3.2  kset

l  Kset是kobject对象的集合体。把它看成是一个容器,可将所有相关的kobject对象放到同一位置,比如块设备在/sys/block下。

struct kset {

         struct list_head list;  /* 链表头,把包含所有的kobject组成一个链表 */

         spinlock_t list_lock;  /*  */

         struct kobject kobj;   /* 内嵌的kobject */

         const struct kset_uevent_ops*uevent_ops;   /* uevent操作 */

};

因为内嵌一个kobject,所以在sysfs中也表现为一个目录

l  Kset的操作函数

n  初始化

void kset_init(struct kset *kset);

n  注册/注销

int __must_check kset_register(struct kset *kset);

void kset_unregister(struct kset *kset);

n  引用计数加一

struct kset *kset_get(struct kset *k)

n  引用计数减一

void kset_put(struct kset *k)

 

3.3  sysfs

l  Sysfs是一个处于内存中的虚拟文件系统,它为我们提供了kobject对象层次结构视图。

 

l  Sysfs操作

n  创建属性,在sys下创建一个属性文件

int sysfs_create_file(struct kobject * kobj, const structattribute * attr)

n  删除属性

void sysfs_remove_file(struct kobject * kobj, const structattribute * attr)

n  创建二进制属性

int sysfs_create_bin_file(struct kobject *kobj, const structbin_attribute *attr)

n  删除二进制属性

void sysfs_remove_bin_file(struct kobject *kobj, const structbin_attribute *attr)

at24.c(eeprom)驱动就是使用这两个函数在sys目录下产生bin文件,此bin文件其实就是对eeprom的映射,可以通过读写这个bin文件来操作eeprom。

 

 

3.4  内核事件层

l  内核事件层实现了内核到用户的消息通知系统,是建立在kobject上的。通过kobject_uevent函数向用户空间发送uevent,来实现热插拔机制。

 

l  内核事件向用户空间的传递方式

n  在PC上,经由netlink传递,netlink是一个用于传送网络信息的多点传送套接字。用户空间使用udev来监听内核发送来的uevent并执行相应的热插拔操作

n  在嵌入式里,使用mdev来实现。

 

Kobject_uevent,向用户空间发送消息uevent

intkobject_uevent(struct kobject *kobj, enum kobject_action action)

n  kobj:指定发送该信号的koject对象

n  action:描述该信号的动作

         KOBJ_ADD,           添加

         KOBJ_REMOVE,       移除

                   Andso on…

 

3.5  实例解析

/*

* for learn kobject, kset, ktype

*/

#include <linux/kobject.h>

#include <linux/string.h>

#include <linux/sysfs.h>

#include <linux/slab.h>

#include <linux/module.h>

#include <linux/init.h>

 

struct foo_obj {

         structkobject kobj;

         intfoo;

         intsoo;

         intcoo;

};

#define to_foo_obj(x)       container_of(x, struct foo_obj, kobj)

 

struct foo_attribute {

         structattribute attr;

         ssize_t(*show)(struct foo_obj *foo, struct foo_attribute *attr, char *buf);

         ssize_t(*store)(struct foo_obj *foo, struct foo_attribute *attr,

                                     constchar *buf, size_t count);

};

#define to_foo_attr(x)     container_of(x, struct foo_attribute, attr)

 

/* 公共的属性操作方法 */

static ssize_t foo_attr_show(struct kobject*kobj, struct attribute *attr,

                                               char*buf)

{

         structfoo_attribute *attribute;

         structfoo_obj *foo;

 

         attribute= to_foo_attr(attr);

         foo= to_foo_obj(kobj);

 

         if(!attribute->show)

                   return-EIO;

 

         returnattribute->show(foo, attribute, buf);

}

 

static ssize_t foo_attr_store(structkobject *kobj, struct attribute *attr,

                                               constchar *buf, size_t len)

{

         structfoo_attribute *attribute;

         structfoo_obj *foo;

 

         attribute= to_foo_attr(attr);

         foo= to_foo_obj(kobj);

 

         if(!attribute->store)

                   return-EIO;

        

         returnattribute->store(foo, attribute, buf, len);

}

 

static const struct sysfs_ops foo_sysfs_ops= {

         .show       = foo_attr_show,

         .store       = foo_attr_store,

};

 

/* 销毁函数,当引用计数(kref)减为0时调用 */

static void foo_release(struct kobject*kobj)

{

         structfoo_obj *foo;

         foo= to_foo_obj(kobj);

         kfree(foo);

}

 

/* 属性操作方法 */

static ssize_t foo_show(struct foo_obj*foo_obj, struct foo_attribute *attr,

                                               char*buf)

{

         returnsprintf(buf, "%d\n", foo_obj->foo);

}

 

static ssize_t foo_store(struct foo_obj*foo_obj, struct foo_attribute *attr,

                                               constchar *buf, size_t count)

{

         sscanf(buf,"%du", &foo_obj->foo);

         returncount;

}

 

static ssize_t soo_show(struct foo_obj*foo_obj, struct foo_attribute *attr,

                                               char*buf)

{

         returnsprintf(buf, "%d\n", foo_obj->soo);

}

 

static ssize_t soo_store(struct foo_obj*foo_obj, struct foo_attribute *attr,

                                               constchar *buf, size_t count)

{

         sscanf(buf,"%du", &foo_obj->soo);

         returncount;

}

 

/*

*构造文件属性

*/

static struct foo_attribute foo_attribute =

         __ATTR(foo,0666, foo_show, foo_store);

 

static struct foo_attribute soo_attribute =

         __ATTR(soo,0666, soo_show, soo_store);

 

static struct foo_attribute coo_attribute =

         __ATTR(coo,0666, soo_show, soo_store);

 

/*

*添加foo_attribute.attr和soo_attribute.attr为foo_obj的默认属性

*/

static struct attribute*foo_default_attrs[] = {

         &foo_attribute.attr,

         &soo_attribute.attr,

         NULL,

};

 

/*

*定义foo_obj公共属性和操作

*/

static struct kobj_type foo_ktype = {

         .sysfs_ops        = &foo_sysfs_ops,

         .release   = foo_release,

         .default_attrs= foo_default_attrs,

};

 

static struct kset *kset_example;

static struct foo_obj *foo_obj;

static struct foo_obj *soo_obj;

 

static struct foo_obj *create_foo_obj(constchar *name)

{

         structfoo_obj *foo;

         intret;

 

         foo= kzalloc(sizeof(*foo), GFP_KERNEL);

         if(!foo)

                   returnNULL;

        

         foo->kobj.kset= kset_example;

         foo->foo= 6;

         foo->soo= 7;

 

         ret= kobject_init_and_add(&foo->kobj, &foo_ktype, NULL, "%s",name);

         if(ret) {

                   kobject_put(&foo->kobj);

                   returnNULL;

         }

 

         /*通知用户空间 */

         kobject_uevent(&foo->kobj,KOBJ_ADD);

        

         returnfoo;

}

 

static void destroy_foo_obj(struct foo_obj*foo)

{

         kobject_put(&foo->kobj);

}

 

static int __init example_init(void)

{

         kset_example= kset_create_and_add("kset_example", NULL, NULL);

         if(!kset_example)

                   return-ENOMEM;

        

         foo_obj= create_foo_obj("foo");

         if(!foo_obj)

                   gotofoo_error;

        

         soo_obj= create_foo_obj("soo");

         if(!soo_obj)

                   gotosoo_error;

        

         /*添加新的属性 */

         sysfs_create_file(&foo_obj->kobj,&coo_attribute.attr);

 

         return0;

 

soo_error:

         destroy_foo_obj(foo_obj);

foo_error:

         kset_unregister(kset_example);

        

         return-EINVAL;

}

 

static void __exit example_exit(void)

{

         sysfs_remove_file(&foo_obj->kobj,&coo_attribute.attr);

         destroy_foo_obj(soo_obj);

         destroy_foo_obj(foo_obj);

         kset_unregister(kset_example);

}

 

module_init(example_init);

module_exit(example_exit);

 

MODULE_LICENSE("GPL");

MODULE_AUTHOR("CJOK<cjok.liao@gmail.com>");

 

试验结果:



Logo

更多推荐