Chinaunix首页 | 论坛 | 博客
  • 博客访问: 844544
  • 博文数量: 489
  • 博客积分: 475
  • 博客等级: 下士
  • 技术积分: 3087
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-08 16:28
文章分类

全部博文(489)

文章存档

2013年(7)

2012年(301)

2011年(181)

分类:

2012-01-12 13:47:16

2.6内核增加了一个引人注目的新特性——统一设备模型(device model)。设备模型提供一个独立的机制专门来表示设备,并描述了其在系统中的拓扑结构。

17.1   kobject

       设备模型的核心部分就是kobject,它由struct kobject结构表示,定义于头文件(linux/kobject)中。kobject类似于C#或java这些面向对象语言中的object对象类, 提供了诸如引用计数、名称和父指针等字段,可以创建对象的层次结构。

struct kobject {
              char                          * k_name;
             char                           name[KOBJ_NAME_LEN];
               struct kref                  kref;
              struct list_head          entry;
              struct kobject              * parent;
              struct kset                  * kset;
              struct kobj_type         * ktype;
             struct dentry               * dentry;
};
k_name指针指向kobject名称的起始位置,如果名称长度小于KOBJ_NAME_LEN——当前为20个字节,那么该kobject的名称便存 放到name数组中,k_name指向数组头;如果名称大于20,则动态分配以讹足够大的缓冲区来存放kobject的名称,这时k_name指向缓冲 区。

       parent指针指向kobject的父对象。因此,kobject就会在内核中构造一个对象层次结构,并且可以将对各对象间的关系表现出来,就如你看到 的,这便是sysfs的真正面目:一个用户空间的文件系统,用来表示内核中kobject对象的层次结构。

       dentry指针指向dentry结构体,在sysfs中该结构体就表示这个kobject,当然假设该kobject已反映在sysfs中。

        kobject通常是嵌入到其他结构中的,其单独意义其实并不大。相反,那些更为重要的结构体才真正需要用到kobject结构。比如struct   cdev。

struct    cdev   {

              struct     kobject               kobj;

              struct      module             *owner;

             struct     file_operations    *ops;

             struct     list_head           list;

             dev_t                             dev

              unsigned    int               count;

};

       当kobject被嵌入到其他结构体中时,该结构体便拥有了kobject提供的标准功能。更重要的一点是,嵌入kobject接结构体可以成为对象层次 架构中的一部分。比如cdev结构体就可以通过其父进程指针cdev->kobj->parent和链表 cdev->kobj->entry来插入到对象层次结构中。

17.2   ktype

       kobject对象被关联到一种特殊的类型,即ktype。ktype由kobj_type结构体表示,定义于中:

struct kobj_type {
                  void                                 (*release)(struct kobject *);
                    struct     sysfs_ops          * sysfs_ops;
                    struct      attribute             ** default_attrs;
};
ktype是为了描述一族kobject所具有的普遍特性。因此,不再需要每个kobject都分别定义自己的特性,而是将这些普遍的特性在ktype结 构体中一次定义,然后所有“同类”的kobject都能共享一样的特性。release指针指向在kobject引用计数减至0时要被调用的析构函数。该 函数负责释放所有kobject使用的内存和其它相关清理工作。sysfs_ops变量指向sysfs_ops结构体。该结构体描述了sysfs文件读写 时的特性。default_attrs指向一个attribute结构体数组。这些结构体定义了该kobject相关的默认属性。属性给定了对象的特征, 如果该kobject被导出到sysfs中,那么这些属性都将相应的作为文件而导出。

17.3   kset

       kset是kobject对象的集合体。把它看成一个容器,可将所有相关的kobject对象,比如“全部的块设备”置于同一位置。kset可把 kobject集中到一个集合中,而ktype描述相关类型kobject所共有的特性,它们之间的重要区别在于:具有相同ktype的kobject可 以分到不同的kset中(同一个kset中的kobject是否具有相同的ktype吗???)。kobject的kset指针指向相应的kset集合。

struct kset {
          struct    subsystem              * subsys;
          struct     kobj_type                * ktype;
          struct     list_head                 list;
          struct   kobject                    kobj;
         struct    kset_hotplug_ops       * hotplug_ops;
};
        其中ktype指针指向集合(kset)中的kobject对象的类型(ktype),list连接该集合(kset)中所有的kobject对象。 kobj指向的kobject对象代表了该集合的基类。hotplug_ops指向一个用于处理集合中kobject对象的热拔插操作的结构体。 subsys指针指向该结构体相关的struct subsystem结构体。

17.4   subsystem

       subsystem在内核中代表高层概念,它是一个或多个kset的大集合。

struct subsystem {
struct kset   kset;
struct rw_semaphore rwsem;
};
        虽然subsystem结构体只指向一个kset,但是多个kset可以通过其subsys指针指向一个subsystem这种单向关系意味着不可能仅仅 通过一个subsystem结构体就找到所有的ksets。subsystem中的kset字段指向的是subsystem中的默认kset,它在对象层 次结构中起到了粘合剂的作用。rwsem是一个读写信号量,它用来对subsystem和它的所有kset进行并发访问保护。

17.6    管理和操作kobject

17.7    引用计数

kobject的主要功能之一就是为我们提供了一个统一的引用计数系统。初始化后,kobject的引用计数设置为1。只要引用计数不为0,那么该 对象就会继续保留在内存中,也可以说是被“钉”住了,任何包含对象引用的代码首先要增加该对象的引用计数,当代码结束后则减少它的引用计数。当引用计数减 为0时,对象便可以被销毁,同时相关内存也都被释放。

       增加一个引用计数可通过kobject_get()函数完成:

struct   kobject    * kobject_get(struct kobject   *kobj);

该函数正常情况下返回一个指向kobject的指针,如果失败,则返回NULL指针。

减少引用计数通过kobject_put()完成:

void   kobject_put(struct kobject    *kobj);

17.8    sysfs

       sysfs文件系统是一个处于内存中的虚拟文件系统,它为我们提供了kobject对象层次结构的视图。帮助用户可以一个简单文件系统的方式来观察系统中 各种设备的拓扑结构。借助属性对象,kobject可用导出文件的方式,将内核变量提供给用户读取或写入。

      sysfs的诀窍是把kobject对象与目录项紧密联系起来,这点是通过kobject中的dentry(directory entry)字段实现的。回忆一下12章,dentry结构体表示目录项,通过连接kobject到指定的目录项上,无疑方便的将kobject映射到该 目录上。好了,kobject其实已经形成了一棵树了——就是我们心爱的对象模型体系。

       sysfs的根目录下包含了七个子目录:block、bus、class、devices、firmware、module和power。block目录 下的每个子目录都对应着系统中的一个块设备。反过来,每个目录下又都包含了该块设备的所有分区。bus目录提供了一个系统总线视图。class目录包含了 以高层功能逻辑组织起来的系统设备视图。devices目录是系统中设备拓扑结构视图,它直接映射出了内核中设备结构体的组织层次。firmware目录 包含一些诸如ACPI、EDD、EFI等低层子系统的特殊树。power目录包含了系统范围的电源管理数据。

17.8.1   sysfs中添加和删除kobject

       仅仅初始化一个kobject是不能自动将其导出到sysfs中的,想要把kobject导入sysfs,需要用到函数kobject_add():

int   kobject_add(struct   kobject   *kobj);

       kobject在sysfs中的位置取决于kobject在对象层次结构中的位置。如果kobject的父指针被设置,那么在sysfs中kobject 将被映射为其父目录下的子目录,如果parent没有设置,那么kobject将被映射到kset->kobj中的子目录。两者都未设置,映射为 sysfs下的根级目录。

17.8.2   向sysfs中添加文件

       我们已经看到kobject被映射为文件目录,而且所有的对象层次结构都优雅的、一个不少的映射成为sys下的目录结构。但是里面的文件是什么?sysfs仅仅是一个漂亮的树,但是没有提供实际数据的文件。

       默认属性

       默认的文件集合是通过kobject和kset中的ktype字段提供的。因此所有具有相同类型的kobject在它们对应的sysfs目录下都拥有相同 的默认文件集合。kobj_type字段含有一个字段——default_attrs,它是看一个attribute结构体数组。这些属性负责将内核数据 映射成sysfs中的文件。

struct attribute {
            char                         * name;
             struct    module       * owner;
           mode_t                     mode;
};
其中name字段提供了该属性的名称,最终出现在sysfs中的文件名就是它。owner字段在存在所属模块的情况下指向其所属的module结构体。如果一个模块没有该属性,那么该字段为NULL。mode字段类型为mode_t,他表示sysfs中该文件的权限。

       虽然default_attrs列出了默认的属性,sysfs_ops字段则描述了如何使用它们。sysfs_ops字段指向了一个定义与文件的同名结构体:

struct sysfs_ops {
ssize_t (*show)(struct kobject *,     struct attribute *,       char *);
ssize_t (*store)(struct kobject *,     struct attribute *,       const char *, size_t);
};
      show()方法在读操作时被调用。它会拷贝由attr提供的属性值到buffer指定的缓冲区,缓冲区大小为PAGE_SIZE字节;该函数若执行成功,返回写入buffer的字节数,失败,返回负的错误码。

     store()方法在写操作时调用,它会从buffer中读取size大小的字节,并将其放入attr表示的属性结构体变量中。

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