Chinaunix首页 | 论坛 | 博客
  • 博客访问: 184391
  • 博文数量: 80
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 83
  • 用 户 组: 普通用户
  • 注册时间: 2016-03-23 13:37
文章分类

全部博文(80)

文章存档

2016年(80)

我的朋友

分类: LINUX

2016-03-24 17:42:51

原文地址:linux设备驱动之kset 作者:_ChinaUnix

    kset是具有相同类型的kobject的集合,在sysfs体系中体现为一个目录,在内核中有一个网上有一个非常经典的图,反应出kobject和kset的关系。

    kobject对应于sysfs文件系统的一个目录,该目录可以有一些设备属性相关的文件。
    kset相同类型的kobject的集合,也是对应于sysfs文件系统的一个目录,其子目录,也就是kobject的目录。

点击(此处)折叠或打开

  1. struct kset {
  2.     struct list_head list;       //连接kset中所有的kobject的链表
  3.     spinlock_t list_lock;       //访问时候加锁
  4.     struct kobject kobj;        //连接kobject
  5.     const struct kset_uevent_ops *uevent_ops;//主要是热插拔事件
  6. };
     由上面的数据类型和图可以看出,kset和kobject的基本关系。

点击(此处)折叠或打开

  1. int kset_register(struct kset *k)
  2. {
  3.     int err;

  4.     if (!k)
  5.         return -EINVAL;

  6.     kset_init(k);                             //kset一些初始化
  7.     err = kobject_add_internal(&k->kobj);     //添加kobject到kset中
  8.     if (err)
  9.         return err;
  10.     kobject_uevent(&k->kobj, KOBJ_ADD);      //初始化evnet
  11.     return 0;
  12. }
可以看出,它只是把kset中的kobject连到系统中,向用户空间发一个KOBJ_ADD。

点击(此处)折叠或打开

  1. void kset_init(struct kset *k)
  2. {
  3.     kobject_init_internal(&k->kobj);
  4.     INIT_LIST_HEAD(&k->list);
  5.     spin_lock_init(&k->list_lock);
  6. }
向内核注销kset函数

点击(此处)折叠或打开

  1. void kset_unregister(struct kset *k)
  2. {
  3.     if (!k)
  4.         return;
  5.     kobject_put(&k->kobj);
  6. }
    在linux系统中,当系统的环境发生变化时,如添加kset到系统,移动kobject都会从内核空间发送到用户控件,这个是热插拔事件,那么相应的处理程序会被调用,这个处理程序会调用加载驱动,创建设备节点等来响应。

点击(此处)折叠或打开

  1. struct kset_uevent_ops {
  2.     int (* const filter)(struct kset *kset, struct kobject *kobj);
  3.     const char *(* const name)(struct kset *kset, struct kobject *kobj);
  4.     int (* const uevent)(struct kset *kset, struct kobject *kobj,
  5.          struct kobj_uevent_env *env);
  6. };
这三个函数有什么作用
1、filter:决定了是否会将热插拔事件传递到用户控件。返回0,不传递,返回1,传递
2、name:用于将字符串传递给用户控件的热插拔处理程序
3、uevent:将用户空间需要的参数添加到环境变量中。
下面是一个kset和kobject结合的例子

点击(此处)折叠或打开

  1. struct kset kset_p;
  2. struct kset kset_c;

  3. int kset_filter(struct kset *kset, struct kobject *kobj)
  4. {
  5.         printk("Filter: kobj %s.\n",kobj->name);
  6.         return 1;
  7. }
  8.  
  9. const char *kset_name(struct kset *kset, struct kobject *kobj)
  10. {
  11.         static char buf[20];
  12.         printk("Name: kobj %s.\n",kobj->name);
  13.         sprintf(buf,"%s","kset_name");
  14.         return buf;
  15. }
  16.  
  17. int kset_uevent(struct kset *kset, struct kobject *kobj,struct kobj_uevent_env *env)
  18. {
  19.         int i = 0;
  20.         printk("uevent: kobj %s.\n",kobj->name);

  21.         while( i < env->envp_idx){
  22.                 printk("%s.\n",env->envp[i]);
  23.                 i++;
  24.         }

  25.         return 0;
  26. }

  27. struct kset_uevent_ops uevent_ops =
  28. {
  29.         .filter = kset_filter,
  30.         .name = kset_name,
  31.         .uevent = kset_uevent,
  32. };
  33.  
  34. int kset_test_init()
  35. {
  36.         printk("kset test init.\n");
  37.         kobject_set_name(&kset_p.kobj,"kset_p");
  38.         kset_p.uevent_ops = &uevent_ops;
  39.         kset_register(&kset_p);
  40.  
  41.         kobject_set_name(&kset_c.kobj,"kset_c");
  42.         kset_c.kobj.kset = &kset_p;//指向父目录,由于有结构的变化会触发热插拔事件
  43.         kset_register(&kset_c);
  44.         return 0;
  45. }
  46.  
  47. int kset_test_exit()
  48. {
  49.         printk("kset test exit.\n");
  50.         kset_unregister(&kset_p);
  51.         kset_unregister(&kset_c);
  52.         return 0;
  53. }
  54.  
  55. module_init(kset_test_init);
  56. module_exit(kset_test_exit);


阅读(1346) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~