首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

ok6410学习笔记(12.kset学习记录)

ok6410学习笔记(12.kset学习记录)

本节知识点:基础知识:1.最重要的是弄清楚kobject和kset之间的关系:首先kobject是在sys目录下创建一个目录,这个目录里面只有属性文件。而kset也是创建一个目录,这个目录里面还可以创建目录(包括kset内嵌的kobject,和kobject)。kset里面可以有其他好多kset,其实这些kset都是内嵌的kobject,然后把kobject.kset赋值为父目录的kset的值。如图


上面的图很明显了,补充一下,其实下面的kobj也可以是kset内嵌的那个kobj。
2.kset的结构体说明:

3.要想在kset的目录下面,利用kset创建目录,就必须用内嵌的kobject。
4.热插拔事件:当注册的kset目录下的kobject发生变化,移动,加入,删除等。内核空间就会把信息发送到用户空间来,这就是热插拔事件。但是在试验中,只有利用kset内嵌kobject的目录,才能发生热插拔事件,仅仅是利用kobject_init_and_add创建的目录,挂接父目录kobj.set和父对象kobj.parent,也不能产生热插拔事件,也许是因为没有在那个kset中kobject链表之中的原因。
重点函数:1.int kset_register(struct kset *kset)内核中注册一个kset
2.int kset_unregister(struct kset *kset)内核中注销一个kset3.kobject_set_name(&kset_c.kobj, "kset_c")给kobject赋值个名字
4.kset_create_and_add("kset_p", &uevent_ops, NULL)  创建并注册一个kset  此函数返回*kset指针。 kset.kobj.kset不赋值就是在sys目录下。
5.热插拔处理函数:



int kset_filter(struct kset *kset, struct kobject *kobj)  函数功能是决定是否将事件传递到用户空间,kset是发生热插拔事件的那个目录的父目录,kobj是发生热插拔事件的目录,注意,如果return 0后面两个函数则不起作用,只有return 1,内核才将事件传递到用户空间。

const char *kset_name(struct kset *kset, struct kobject *kobj) 将字符串传递到用户空间的热插拔处理程序

int kset_uevent(struct kset *kset, struct kobject *kobj,struct kobj_uevent_env *env)将用户空间需要的参数添加到环境变量中

驱动结构:第一种方式:
1.定义一个struct kset *kset_p;
2.填写uevent_ops结构
3.kset_p = kset_create_and_add("kset_p", &uevent_ops, NULL);  //创建并注册一个kset  此函数返回kset指针  NULL应该是parent父对象
第二种方式:
1.定义一个struct kset  kset_c;
2.kobject_set_name(&kset_c.kobj, "kset_c");  //给kset中内嵌的kobject赋值名字
   kset_c.kobj.kset = kset_p; //kset_c的父目录是kset_p
   kset_c.kobj.ktype = &my_ktype;//ktype里面包含那三个重要的结构体
   kset_c.uevent_ops= &uevent_ops;//热插拔事件处理函数

   填写各种kset需要的结构
3.kset_register(&kset_c); //注册kset_c

本节代码:[cpp] view plaincopy


  • #include <linux/device.h>
  • #include <linux/module.h>
  • #include <linux/kernel.h>
  • #include <linux/init.h>
  • #include <linux/string.h>
  • #include <linux/sysfs.h>
  • #include <linux/stat.h>
  • #include <linux/kobject.h>

  • MODULE_AUTHOR("Hao");  
  • MODULE_LICENSE("Dual BSD/GPL");  

  • struct kset *kset_p;  
  • struct kset kset_c;  
  • struct kset kset_a;  
  • struct kobject my_kobj;  

  • void my_release(struct kobject *kobject)  
  • {  
  •         printk("[call obj_test_release]\n");  
  • }  

  • ssize_t my_show(struct kobject *kobject,struct attribute *attr,char *buf)  
  • {  
  •         printk(KERN_EMERG"IN my_show\n");  
  •         strcpy(buf,"you are reading!!!");  //在sys文件系统中读属性文件的时候应该读出 you are reading!!!
  •         return strlen(buf); //注意返回值
  • }  
  • ssize_t my_store(struct kobject *kobject,struct attribute *attr,char *buf,size_t size)  
  • {  
  •         printk(KERN_EMERG"write : %s\n",buf); //在写属性文件的时候   应该在这里打印出来
  •         return size;   //注意返回值
  • }  


  • struct sysfs_ops my_kobject_ops={  //对sys文件夹下面sys_my_kobject文件夹的文件进行操作的函数集

  •         .show=my_show,  
  •         .store=my_store,  
  • };  

  • struct attribute attr_str = {  
  •     .name = "attr_str",  
  •     .mode = S_IRWXU,  
  • };  

  • struct attribute attr_name = {  
  •     .name = "attr_name",  
  •     .mode = S_IRUSR,  
  • };  

  • static
    struct attribute *def_attrs[] = {  //kobject和kset_c中有两个文件
  •                 &attr_str,  
  •                 &attr_name,  
  •                 NULL,  
  • };  

  • struct kobj_type my_ktype =   
  • {  
  •     .release   = my_release,  
  •     .sysfs_ops = &my_kobject_ops,  
  •     .default_attrs = def_attrs,  
  • };  





  • //kset  uevent_ops 热插拔事件
  • int kset_filter(struct kset *kset, struct kobject *kobj)  //struct kobject 就是当前发生热插拔的目录
  • {  
  •             printk("[call kset_filter (kobj->name=%s)]\n", kobj->name);  
  •             return 1;  //只有返回1  剩下的两个函数才有作用
  • }  
  • const
    char *kset_name(struct kset *kset, struct kobject *kobj)  
  • {  
  •     static
    char buf[20];  
  •     printk("[call kset_name (kobj->name=%s)]\n", kobj->name);  
  •     sprintf(buf, "%s", "New Kset Name");  //返回这个字符串给用户空间的热插拔处理程序

  •     return buf;  
  • }  
  • int kset_uevent(struct kset *kset, struct kobject *kobj,struct kobj_uevent_env *env)  
  • {  
  •     int i = 0;  
  •     printk("[uevent: %s]\n", kobj->name);  

  •     while( i < env->envp_idx){  //将所有的环境变量打印出来
  •         printk("[envp[%d]: %s]\n", i, env->envp);  
  •         i++;  
  •     }  

  •     return 0;  
  • }  

  • struct kset_uevent_ops uevent_ops =   
  • {  
  •     .filter = kset_filter,  //决定是否把事件传递给用户空间
  •     .name   = kset_name,    //将字符串返回给用户空间
  •     .uevent = kset_uevent,  //添加环境变量
  • };  


  • int __init my_kset_init(void)  
  • {  
  •                 int ret=0;  
  •             kset_p = kset_create_and_add("kset_p", &uevent_ops, NULL);  //创建并注册一个kset 这个kset没有内嵌kobject

  •             /*一个kset里面可以有好多个kset  但是方法是用内嵌kobject的方式  只有kobj.kset可以确定kset父目录*/
  •             /*如果直接创建kobject 也可以但是就是在这个kobject里面只能有文件 不能有目录了*/
  •             kobject_set_name(&kset_c.kobj, "kset_c");  //给kset中内嵌的kobject赋值名字
  •             kset_c.kobj.kset = kset_p; //kset_c的父目录是kset_p
  •             kset_c.kobj.ktype = &my_ktype;//ktype里面包含那三个重要的结构体
  •             kset_c.uevent_ops= &uevent_ops;  
  •                 ret = kset_register(&kset_c); //注册kset_c
  •                 if (ret)  
  •                     goto err1;  
  •                 /*直接创建一个kobject  把他的父目录写成kset_p*/

  •                 kobject_set_name(&kset_a.kobj, "kset_a");  //给kset中内嵌的kobject赋值名字
  •             kset_a.kobj.kset = &kset_c; //kset_c的父目录是kset_p
  •             kset_a.kobj.ktype = &my_ktype;//ktype里面包含那三个重要的结构体
  •                 ret = kset_register(&kset_a); //注册kset_c


  •                 my_kobj.parent=&(kset_p->kobj);  
  •                 my_kobj.kset = kset_p;   
  •                 ret = kobject_init_and_add(&my_kobj, &my_ktype, NULL, "my_kobject");  
  •                 if (ret)  
  •                     goto err;  
  •                 return 0;  
  • err:   //如果没有注册成功则把注册的 从内核中删除        
  •     kset_unregister(&kset_c);  
  • err1:  
  •     kset_unregister(kset_p);  
  •     return ret;  
  • }  

  • void __exit my_kset_exit(void)  //先卸载谁  后卸载谁 都没关系的  都会出现热插拔事件
  • {  
  •         kset_unregister(kset_p);  //卸载所有kset和kobject
  •         kset_unregister(&kset_c);  
  •         kset_unregister(&kset_a);  
  •         kobject_del(&my_kobj);  
  • }  

  • module_init(my_kset_init);  
  • module_exit(my_kset_exit);  

返回列表