zoukankan      html  css  js  c++  java
  • linux设备驱动模型(kobject与kset)

    Linux设备模型的目的:为内核建立一个统一的设备模型,从而又一个对系统结构的一般性抽象描述。换句话说,Linux设备模型提取了设备操作的共同属性,进行抽象,并将这部分共同的属性在内核中实现,而为需要新添加设备或驱动提供一般性的统一接口,这使得驱动程序的开发变得更简单了,而程序员只需要去学习接口就行了。

                                         kobject                                                                                                                                   

    1.sysfs文件系统

      1.1 sysfs文件系统与内核结构的关系

    linux内核中的结构 sysfs中的结构             
    kobject (内核对象) 目录  
    kobj_type (属性)  属性文件
    对象之间的关系 符号链接

      1.2 sysfs文件系统的目录结构

    block:所有块设备

    devices:系统所有设备(块设备特殊),对应struct device的层次结构

    bus:系统中所有总线类型(指总线类型而不是总线设备,总线设备在devices下),bus的每个子目录都包含

        --devices:包含到devices目录中设备的软链接

        --drivers:与bus类型匹配的驱动程序

    class:系统中设备类型(如声卡、网卡、显卡等)

    fs:一些文件系统,具体可参考filesystems /fuse.txt中例子

    dev:包含2个子目录

    --char:字符设备链接,链接到devices目录,以<major>:<minor>命名

    --block:块设备链接

    2.设备驱动模型的核心数据结构

    2.1 kobject结构体

      

      name 将显示在sysfs文件系统中,作为一个目录的名字;

      struct kobj_type *ktype 代表kobject的属性,对于sysfs中的普通文件读写操作都是kobjetc->ktype->sysfs_ops指针来完成的,即对default_attrs数组的操作

      kobject始终是sysfs文件系统中的一个目录而不是文件。

    2.2设备属性kobj_type

      下图是kobject与kobj_type的关系:

      

      kobj_type结构体的定义如下:

    struct kobj_type {
        void (*release)(struct kobject *kobj);//释放kobject和其他占用资源的函数
        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);
    };

      【1】attribute结构体如下:

    struct attribute {
        const char        *name;//属性名字
        struct module        *owner;//
        mode_t            mode;//属性的读写权限
    #ifdef CONFIG_DEBUG_LOCK_ALLOC
        struct lock_class_key    *key;
        struct lock_class_key    skey;
    #endif
    };

      【2】sysfs_ops 属性操作结构体: 

    struct sysfs_ops {
        ssize_t    (*show)(struct kobject *, struct attribute *,char *);//读属性
        ssize_t    (*store)(struct kobject *,struct attribute *,const char *, size_t);//写属性
    };

      【3】release()函数

        当kobject的引用计数为0时,系统自动会调用自定义的release()来释放kobject对象。

        e.g.

          

    3.实例:

    #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>
     
    MODULE_AUTHOR("David Xie");
    MODULE_LICENSE("Dual BSD/GPL");
     
    void obj_test_release(struct kobject *kobject);
    ssize_t kobj_test_show(struct kobject *kobject, struct attribute *attr,char *buf);
    ssize_t kobj_test_store(struct kobject *kobject,struct attribute *attr,const char *buf, size_t count);
     
    struct attribute test_attr = {
            .name = "kobj_config",
            .mode = S_IRWXUGO,
    };
     
    static struct attribute *def_attrs[] = {
            &test_attr,
            NULL,
    };
     
     
    struct sysfs_ops obj_test_sysops =
    {
            .show = kobj_test_show,
            .store = kobj_test_store,
    };
     
    struct kobj_type ktype = 
    {
            .release = obj_test_release,
            .sysfs_ops=&obj_test_sysops,
            .default_attrs=def_attrs,
    };
     
    void obj_test_release(struct kobject *kobject)
    {
            printk("eric_test: release .
    ");
    }
     
    ssize_t kobj_test_show(struct kobject *kobject, struct attribute *attr,char *buf)
    {
            printk("have show.
    ");
            printk("attrname:%s.
    ", attr->name);
            sprintf(buf,"%s
    ",attr->name);
            return strlen(attr->name)+2;
    }
     
    ssize_t kobj_test_store(struct kobject *kobject,struct attribute *attr,const char *buf, size_t count)
    {
            printk("havestore
    ");
            printk("write: %s
    ",buf);
            return count;
    }
     
    struct kobject kobj;
    static int kobj_test_init()
    {
            printk("kboject test init.
    ");
            kobject_init_and_add(&kobj,&ktype,NULL,"kobject_test");
            return 0;
    }
     
    static int kobj_test_exit()
    {
            printk("kobject test exit.
    ");
            kobject_del(&kobj);
            return 0;
    }
     
    module_init(kobj_test_init);
    module_exit(kobj_test_exit);

                                     kset                                                                                                                                             

     

    kset是具有相同类型的kobject的集合,在sysfs中体现成一个目录;kobject不能包含目录,而kset可以包含目录。kobject通过kset组织成层次化的结构,kset将一系列相同类型的kobject使用(双向)链表连接起来,可以这样 认为,kset充当链表头作用,kset内部内嵌了一个kobject结构。

      1. #include <linux/kobject.h>
      2. struct kset {
      3.     struct list_head list; /* 用于连接kset中所有kobject的链表头 */
      4.     spinlock_t list_lock; /* 扫描kobject组成的链表时使用的锁 */
      5.     struct kobject kobj; /* 嵌入的kobject */
      6.     const struct kset_uevent_ops *uevent_ops; /* kset的uevent操作 */
      7. };

    实例:

    #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("David Xie");
    MODULE_LICENSE("Dual BSD/GPL");
     
    struct kset kset_p;
    struct kset kset_c;
    
    int kset_filter(struct kset *kset, struct kobject *kobj)
    {
            printk("Filter: kobj %s.
    ",kobj->name);
            return 1;
    }
     
    const char *kset_name(struct kset *kset, struct kobject *kobj)
    {
            static char buf[20];
            printk("Name: kobj %s.
    ",kobj->name);
            sprintf(buf,"%s","kset_name");
            return buf;
    }
     
    int kset_uevent(struct kset *kset, struct kobject *kobj,struct kobj_uevent_env *env)
    {
            int i = 0;
            printk("uevent: kobj %s.
    ",kobj->name);
    
            while( i < env->envp_idx){
                    printk("%s.
    ",env->envp[i]);
                    i++;
            }
    
            return 0;
    }
    
    struct kset_uevent_ops uevent_ops = 
    {
            .filter = kset_filter,
            .name   = kset_name,
            .uevent = kset_uevent,
    };
     
    int kset_test_init()
    {
            printk("kset test init.
    ");
            kobject_set_name(&kset_p.kobj,"kset_p");
            kset_p.uevent_ops = &uevent_ops;
            kset_register(&kset_p);
            printk("kset_p finish
    ");
    
            /*下面会调用热插拔函数*/
            kobject_set_name(&kset_c.kobj,"kset_c");
            kset_c.kobj.kset = &kset_p;
            kset_register(&kset_c);
            return 0;
    }
     
    int kset_test_exit()
    {
            printk("kset test exit.
    ");
            kset_unregister(&kset_p);
            kset_unregister(&kset_c);
            return 0;
    }
     
    module_init(kset_test_init);
    module_exit(kset_test_exit);

    热插拔事件kset_uevent_ops

    在Linux系统中,当系统配置发生变化时,如:添加kset到系统;移动kobject, 一个通知会从内核空间发送到用户空间,这就是热插拔事件。热插拔事件会导致用户空间中相应的处理程序(如udev,mdev)被调用, 这些处理程序会通过加载驱动程序, 创建设备节点等来响应热插拔事件。

    Struct kset_uevent_ops {
    int (*filter)(struct kset *kset, struct kobject *kobj);
    const char *(*name)(struct kset *kset, struct kobject *kobj);
    int (*uevent)(struct kset *kset, struct kobject *kobj,
    struct kobj_uevent_env *env);
    }

    当该kset所管理的kobject和kset状态发生变化时(如被加入,移动),这三个函数将被调用。

                         kobject与kset的关系                                                                                                                               

    参考:http://blog.csdn.net/xiahouzuoxin/article/details/8943863 

  • 相关阅读:
    博客园 投放 谷歌广告(google adsense) 且不被屏蔽掉
    JAVA与C#程序调用DOS命令
    redhat 5 安装apache 2.2
    解决"Windows 安装程序不允许从远程桌面连接安装"
    测试使用windows live writer的adsense coder发布文章
    解决:apache 整合redmine 启动报错 mod_passenger.so: failed to map segment from shared object: Permission denied
    企业级安全服务权限控制 Acegi安装系统介绍 Spring Framework安全系统
    解决Rails升级问题
    解决MyEclipse 7开发EXTJS 每次保存都要编译js的导致开发效率很低的问题
    解决:redmine 安装 rake db:migrate encoding: utf8
  • 原文地址:https://www.cnblogs.com/hello2mhb/p/3365204.html
Copyright © 2011-2022 走看看