2.6内核增加了一个引人注目的新特性---统一设备模型(device model)。设备模型提供了一个独立的机制专门来表示设备,并描述其在系统中的拓扑结构,使系统具有以下优点:
代码重复最小化
提供诸如引用计数这样的统一机制
可以列举系统宏所有的设备,观察它们的状态,并且查看它们连接的总线
可以将系统中的全部设备结构以树的形式完整有效地展现出来,包括所有的总线和内部连接
可以将设备和其对应的驱动程序联系起来,反之亦然
可以将设备按照其类型加以归类,如分类为输入设备,而无需理解物理设备的拓扑结构
可以沿设备树的叶子向其根的方向依次遍历,以保证能以正确顺序关闭各设备的电源
- kobject
设备模型的核心部分就是kobject。它由struct kobject结构体表示,提供了诸如引用计数、名称和父指针等字段:
- 在include/linux/Kobject.h中
- struct kobject {
- const char * k_name; //指向kobject名称的起始位置
- /*如果名称长度小于KOBJ_NAME_LEN那么该kobject的名称存放在该数组中
- * 如果名称长度大于KOBJ_NAME_LEN则动态分配一个足够大的缓冲区来存放该kobject的名称
- */
- char name[KOBJ_NAME_LEN];
- struct kref kref;
- struct list_head entry;
- /*指向kobject的父对象。kobject在内核中构造一个对象层次结构,并将多个对象的间的关
- *系表现出来。这便是sysfs的真正面目:一个用户空间的文件系统,用来表示内核中kobject对象的层次结构
- */
- struct kobject * parent;
- struct kset * kset;
- struct kobj_type * ktype;
- struct dentry * dentry; //在sysfs中该结构体表示这个kobject,当然该kobject已经成功以你敢说在sysfs中了
- wait_queue_head_t poll;
- };
kobject通常是嵌入到其他结构中,单独的意义不大。struct cdev结构体中就嵌入了kobject结构体:
- 在include/linux/Cdev.h中
- struct file_operations;
- struct inode;
- struct module;
- struct cdev {
- struct kobject kobj;
- struct module *owner;
- const struct file_operations *ops;
- struct list_head list;
- dev_t dev;
- unsigned int count;
- };
- 在fs.h中
- /*
- * NOTE:
- * read, write, poll, fsync, readv, writev, unlocked_ioctl and compat_ioctl
- * can be called without the big kernel lock held in all filesystems.
- */
- struct file_operations {
- struct module *owner;
- loff_t (*llseek) (struct file *, loff_t, int);
- ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
- ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
- ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
- ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
- int (*readdir) (struct file *, void *, filldir_t);
- unsigned int (*poll) (struct file *, struct poll_table_struct *);
- int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
- long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
- long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
- int (*mmap) (struct file *, struct vm_area_struct *);
- int (*open) (struct inode *, struct file *);
- int (*flush) (struct file *, fl_owner_t id);
- int (*release) (struct inode *, struct file *);
- int (*fsync) (struct file *, struct dentry *, int datasync);
- int (*aio_fsync) (struct kiocb *, int datasync);
- int (*fasync) (int, struct file *, int);
- int (*lock) (struct file *, int, struct file_lock *);
- ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
- ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
- unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
- int (*check_flags)(int);
- int (*dir_notify)(struct file *filp, unsigned long arg);
- int (*flock) (struct file *, int, struct file_lock *);
- ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
- ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
- };
当kobject结构体被嵌入到其他结构中,该结构便拥有了kobject提供的标准功能。更重要的是,嵌入kobject的结构体可以成为对象层次架构中饿一部分。比如cdev结构体就可以通过其父指针cdev->kobj->parent和链表cdev->kobj->entry来插入到对象的层次结构中。
- ktype
kobject对象被关联到一种特殊的类型,即ktype。ktype由kobj_type结构体表示:
- 在kobject.h中
- struct kobj_type {
- void (*release)(struct kobject *); //指向在kobjcet引用计数减至零时要被调用的析构函数
- struct sysfs_ops * sysfs_ops; //描述了sysfs文件读写时的特性
- struct attribute ** default_attrs; //定义了该kobject相关默认属性,属性描述了给定对象的特征,如果该kobject被导出到sysfs中,那么这些属性都将相应地作为文件而导出。数组中的最后一项必须为NULL
- };
- 在Sysfs.h中
- struct sysfs_ops {
- ssize_t (*show)(struct kobject *, struct attribute *,char *);
- ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);
- };
- struct attribute {
- const char * name;
- struct module * owner;
- mode_t mode;
- };
ktype结构是为了描述一族kobject所具有的普遍特定。因此,不再需要每个kobject都分别定义自己的特性,而将这些普遍的特性在ktype结构中一次定义,然后同类的kobject能共享一样的特性。
- kset
kset是kobject对象的集合体。把它看成是一个容器,可将所有相关的kobject对象置于同一个位置。ksets可把kobject集中到一个集合中,而ktype描述相关类型kobject所共有的特性,它们的区别在于:具有相同ktype的kobject可以分组到不同的ksets中。
kobject的kset指针指向相应的kset集合,kset集合由kset结构体表示:
在kobject.h中:
-
- /**
- * kset - a set of kobjects of a specific type, belonging
- * to a specific subsystem.
- *
- * All kobjects of a kset should be embedded in an identical
- * type. This type may have a descriptor, which the kset points
- * to. This allows there to exist sets of objects of the same
- * type in different subsystems.
- *
- * A subsystem does not have to be a list of only one type
- * of object; multiple ksets can belong to one subsystem. All
- * ksets of a subsystem share the subsystem's lock.
- *
- * Each kset can support specific event variables; it can
- * supress the event generation or add subsystem specific
- * variables carried with the event.
- */
- 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, char **envp,
- int num_envp, char *buffer, int buffer_size);
- };
- struct kset {
- struct subsystem * subsys; //指向 该结构体相关的subsystem结构体
- struct kobj_type * ktype; //指向集合中kobject对象的类型
- struct list_head list;
- spinlock_t list_lock;
- struct kobject kobj; //指向的kobject对象代表了该集合的基类
- struct kset_uevent_ops * uevent_ops;
- };
- subsystem
subsystem在内核中代表高层概念,它是一个或多个ksets的大集合。虽然kset包含kobject,而subsystem包含kset,但是subsystem中kset之间的关联比kset中kobject之间的关联要弱很多。subsystem中的kset只可以共享一些较宏观的普遍属性。
- 在kobject.h中
- struct subsystem {
- struct kset kset; //指向的是subsystem中默认的kset,它在对象层次结构中祈祷了粘合剂的作用
- struct rw_semaphore rwsem; //对subsystem和它的所有kset进行并发访问保护
- };
subsystem结构体只指向一个kset,但是多个kset可以通过其subsys指针指向一个subsystem。这种单向关系意味着不可能仅仅通过一个subsystem结构体就找到所有的kset。
- 结构之间的关系
这里最重要的是kobject,它由struct kobject表示。kobject为我们引入了诸如引用计数(reference counting)、父子关系和对象名称等基本对象道具,并且是以一个统一方式提供这些功能。
kobject与一个特别的ktype对象关联,ktype由struct kobj_type结构体表示,在kobject中的ktype字段指向该对象。
kobject又被归入了称作kset的集合,kset集合由struct kset结构体表示。kset提供了两个功能:其中嵌入的kobject作为kobject组的基类;kset将相关的kobject集合在一起。在sysfs中,这些相关的kobject将以独立的目录出现在文件系统中。这些相关的目录,可能处在同一个kset折哦你哦个。
subsystem包含kset的集合,有struct subsystem结构体表示。sysfs中的根级目录映射的便是subsystem。