Linux2.6设备模型(一)——对象和集合

来源:互联网 发布:mac虚拟机蓝屏 编辑:程序博客网 时间:2024/06/06 07:14

由于各种热插拔设备的大量使用以及设备之间复杂的依赖关系,Linux2.6内核提出了全新的设备模型,新设备模型的核心概念是内核对象内核集合,并以此为契机,扩展出许多新的数据类型,如设备、总线等

新的设备模型仅用于设备的管理,与Linux传统的字符设备驱动等并不冲突。

1 对象与集合

         在驱动程序的编写中一般不会直接用到对象和集合,但是对了解新的设备模型会有很大的帮助。

1.1引用计数

         新设备模型的一个突出特点就是各种数据类型都支持引用计数。这样做的好处是:可以避免将其他模块正在使用的数据对象销毁的现象。

1.1.1引用计数类型

         struct kref{

                   atomic_t  refcount;/*用于计数的原子性变量*/

          };

1.1.2引用计数的基本操作

         1)设置引用计数的值

                   void  kref_set(struct kref *kref,int num);

          注解:kref指向要设置的引用计数变量,num为要设置的值。

         2)初始化(默认设置为1)

                  void kref_init(struct kref *kref);

         3)获取引用计数(+1)

                  void kref_get(struct kref *kref);

          4)释放引用计数(-1)

                   int kref_put(struct kref *kref,void (*release) (struct kref *kref));

           注解:release:当引用计数的值为0时,这个函数被调用

                        返回值:1表示引用计数的值降为0,0表示没有降为0.

1.2内核对象

           内核对象是设备模型中最基本的数据类型,有名称,支持引用计数,可以有父子关系,可以属于某个内核集合。内核对象与sysfs文件系统中的目录一一对应,其父子关系对应着目录的层次关系,其属性随影这目录中的文件。

1.2.1内核对象数据类型

        struct kobject{

            const char *name;//内核对象的名称

            struct list_head entry;//链表节点,用于把属于同一个集合的多个内核对象组成链表

            struct kobject *parent;//指向父对象

            struct kset *kset;//指向所属内核集合

           struct kobj_type *ktype;//指向一个描述内核对象类型的结构体

           struct kref kref;//引用计数

            unisigned int uevent_suppress:1;//表示用户态事件是否被抑制

           ......

        };

1.2.2内核对象的名称

      1) 由于涉及到内存的动态分配和释放,不能直接给内核对象的name成员赋值。由于内核对象的名称在注册后将作为目录名,所以不要包含斜杠("/").

       int kobject_set_name(struct kobject *kobj,const char *fmt ,...);

       注解:kobj:指向要设置名称的内核对象

                  fmt:与后面的可变参数结合,构造内核对象的名称。

        2)上面的函数不能用来设置已注册的内核对象的名称,此种情况下可用:

        int kobject_rename(struct kobject *kobj,const char *name);

        3)获取内核对象的名称

        const char * kobject_name(const struct kobject *kobj);

1.2.3内核对象的初始化和注册

       1)初始化函数

             void kobject_init(struct kobject *kobj,struct kobj_type *ktype);

        注解:

             ktype:用于设置内核对象的类型

         初始化后的内核对象可以向内核注册,注册的结果是在sysfs文件系统中出现一个以对象名称命名的目录

         2)注册接口函数

               int kobject_add(struct kobject *kobj,struct kobject *parent,const char *fmt,...);

           注解:

               parent:指定内核对象的父对象,可以为NULL

             注册时可以指定内核对象的父对象,对应的目录会建立在父对象的目录中,如果指定为NULL,则它的父对象会被设为其kset成员指向的内核集合中嵌套的内核对象,如果kset也指向NULL,则对应的目录会建立在sysfs系统得根目录下。

            注册时还会增加对父对象的引用计数。

         3)注销函数

               void kobject_del(struct kobject *kobj);

1.2.4内核对象的引用计数

        由于内核对象内嵌了一个引用计数成员,所以会很容易实现引用计数的相关操作。

         1)内核对象的获取操作定义

             struct kobject *kobkect_get(struct kobject *kobj)

             {

                     if(kobj)   kref_get(&kobj->kref);

                     return kobj;

              }

         2)内核对象的释放操作定义

                void kobject_put(struct kobject *kobj)

               {

                             if(kobj)     kref_put(&kobj->kref,kobject_release);

               }

              注解:kobject_release是内核为对象内嵌的kref成员定义的释放函数。

1.3内核对象的类型

         这里的类型指的是内核对象内嵌的(struct kobj_type*)型指针,这个指针指向的结构体所描述的是这个内核对象的类型。其定义为:

            struct kobj_type{

                   void (*release)   (struct kobject *kobj);//内核对象的释放函数

                   struct sysfs_ops   *sysfs_ops;//sysfs文件操作

                    struct attribute   **default_attrs;//内核对象的默认属性

              };

          注解:release会在函数kobject_release里被回调。

                       sysfs_ops和default_attrs成员组合起来用于实现内核对象的属性。

                       default_attrs指向的数组的最后一个元素必须是NULL。内核据此来判断默认的属性已描述完毕。

1.3.1内核对象的属性

          default_attrs指向一个指针数组,这个数组中的每个指针指向一个用于描述对象属性的数据,该数据的类型定义为:

          struct attribute{

                const char *name//属性的名称

                mode_t      mode//属性的访问权限mode_t实则为unsigned short类型。

            };

         内核对象注册以后,每个属性将呈现为内核对象目录下的一个文件,文件名就是属性名,文件的访问权限就是属性的访问权限。

          当应用程序读写属性所对应的文件时,内核将回调由成员sysfs_ops指向的操作,它的定义为:

                   struct sysfs_ops{

                          sszie_t  (*show) (struct kobject *kobj,struct attribute *attr,char *buf);

                          sszie_t  (*store) (struct kobject *kobj,struct attribute *attr,const char *buf,size_t size);

                     };

1.3.2动态创建属性

          int sysfs_create_file(struct kobject *kobj,const attribute *attr);

         注解:

              attr:指向要创建的新属性(文件)

         动态创建的属性可以被删除

          void sysfs_remove_file(struct kobject *kobj,const struct attribute *attr);

 

注:本文主要参考何永琪先生主编的《嵌入式Linux系统实用开发》

0 0