设备模型的基础是kobject,kset,kobj_type。
kobject本身并没有什么意义,真正有用的地方在于嵌入了kobject的结构体(对象),kobject可以看成是一个最小单元,sysfs的层次结构中的元素都是由kobject构成。
kset与kobject的关系:
kset会包含一类的kobject对象(内核链表串起来),而这些对象对应在sysfs中就是同一级的各个子目录,每一个kobject对象有自己的属性,这些属性就对应于各自子目录的文件。
如此,就会构成一个有层次的组织结构。
kset本身也包含一个kobject,但这个kobject与kset内核链表list中的kobjects并没有什么关系。
kobject的两个主要作用:
1.引用计数
2.事件上报(kobject不加入某个kset是不会上报uevent的 http://www.cnblogs.com/black-mamba/p/5055683.html)
相关文档:
linux/Documentation/kobject.txt
Documentation/filesystems/sysfs.txt
Documentation/filesystems/sysfs-pci.txt
linux/include/linux/kobject.h struct kset { struct list_head list;//所有属于当前集合的kobject对象的链表 spinlock_t list_lock; struct kobject kobj; //与集合中包含的各个kobject无关,只是用来管理kset对象本身 const struct kset_uevent_ops *uevent_ops;//用于将集合的状态信息传递给用户层。该机制有驱动程序的核心使用。 }; //描述内核对象的共同特性 struct kobj_type { void (*release)(struct kobject *kobj); 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); }; //kobject直接嵌入到其他数据结构中,通过管理kobject即可以对包含kobject的对象进行管理。 //kobject包含在一个层次化的组织中。 struct kobject { const char *name;//对象名称 struct list_head entry; struct kobject *parent; //决定kobject出现在sysfs层次结构中的位置:如果存在父对象,那么需要在父对象对应的目录中新建一项;否则,将其放置到kobject所在的kset所属的kobject对应的目录中 struct kset *kset;//集合指针 struct kobj_type *ktype; struct sysfs_dirent *sd; struct kref kref; //引用计数 unsigned int state_initialized:1; unsigned int state_in_sysfs:1; unsigned int state_add_uevent_sent:1; unsigned int state_remove_uevent_sent:1; unsigned int uevent_suppress:1; }; struct kobj_attribute { struct attribute attr; ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr,//用户空间读属性时,内核会调用该函数 char *buf); ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr,//用户空间写属性时,内核会调用该函数 const char *buf, size_t count); }; /disk/A9/linux-3.5/include/linux/sysfs.h struct attribute { const char *name;//显示的文件名 umode_t mode;//文件的权限 #ifdef CONFIG_DEBUG_LOCK_ALLOC bool ignore_lockdep:1; struct lock_class_key *key; struct lock_class_key skey; #endif }; #define __ATTR(_name,_mode,_show,_store) { .attr = {.name = __stringify(_name), .mode = _mode }, .show = _show, .store = _store, } struct attribute_group { const char *name; umode_t (*is_visible)(struct kobject *, struct attribute *, int); struct attribute **attrs; }; struct kobject *kobject_get(struct kobject *kobj) //引用+1 void kobject_put(struct kobject *kobj)//引用-1 void kobject_init(struct kobject *kobj, struct kobj_type *ktype) 初始化kobeject结构体 struct kobject *kobject_create(void)//非导出函数 创建一个kobject结构体,并用kobject_init初始化 int kobject_add(struct kobject *kobj, struct kobject *parent, const char *fmt, ...) 注册一个kobject,在sysfs中生成相应的目录。 如果parent为空,则kobject的parent指向其kset的kobject;如果kset也没有分配,则kobject位于/sys下 struct kobject *kobject_create_and_add(const char *name, struct kobject *parent) 创建一个kobject并注册到sysfs,失败返回空。 int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype, struct kobject *parent, const char *fmt, ...) 初始化一个kobject并注册到sysfs,属性文件会自动生成。
Q1:用户空间调用什么接口是与show、store是相对应的?
linux/include/linux/kobject.h /** * struct kset - a set of kobjects of a specific type, belonging to a specific subsystem. * * A kset defines a group of kobjects. They can be individually * different "types" but overall these kobjects all want to be grouped * together and operated on in the same manner. ksets are used to * define the attribute callbacks and other common events that happen to * a kobject. * * @list: the list of all kobjects for this kset * @list_lock: a lock for iterating over the kobjects * @kobj: the embedded kobject for this kset (recursion, isn't it fun...) * @uevent_ops: the set of uevent operations for this kset. These are * called whenever a kobject has something happen to it so that the kset * can add new environment variables, or filter out the uevents if so * desired. */ struct kset { struct list_head list;//所有属于当前集合的kobject对象的链表 spinlock_t list_lock; struct kobject kobj; //与集合中包含的各个kobject无关,只是用来管理kset对象本身 const struct kset_uevent_ops *uevent_ops;//用于将集合的状态信息传递给用户层。该机制由驱动程序的核心使用。 }; /** * kset_create - create a struct kset dynamically * * @name: the name for the kset * @uevent_ops: a struct kset_uevent_ops for the kset * @parent_kobj: the parent kobject of this kset, if any. * * This function creates a kset structure dynamically. This structure can * then be registered with the system and show up in sysfs with a call to * kset_register(). When you are finished with this structure, if * kset_register() has been called, call kset_unregister() and the * structure will be dynamically freed when it is no longer being used. * * If the kset was not able to be created, NULL will be returned. */ //非导出函数 static struct kset *kset_create(const char *name, const struct kset_uevent_ops *uevent_ops, struct kobject *parent_kobj) /** * kset_init - initialize a kset for use * @k: kset */ void kset_init(struct kset *k) /** * kset_register - initialize and add a kset. * @k: kset. */ int kset_register(struct kset *k) /** * kset_unregister - remove a kset. * @k: kset. */ void kset_unregister(struct kset *k) /** * kobject_uevent - notify userspace by sending an uevent * * @action: action that is happening * @kobj: struct kobject that the action is happening to * * Returns 0 if kobject_uevent() is completed with success or the * corresponding error when it fails. */ int kobject_uevent(struct kobject *kobj, enum kobject_action action) /** * kset_create_and_add - create a struct kset dynamically and add it to sysfs * * @name: the name for the kset * @uevent_ops: a struct kset_uevent_ops for the kset * @parent_kobj: the parent kobject of this kset, if any. * * This function creates a kset structure dynamically and registers it * with sysfs. When you are finished with this structure, call * kset_unregister() and the structure will be dynamically freed when it * is no longer being used. * * If the kset was not able to be created, NULL will be returned. */ struct kset *kset_create_and_add(const char *name, const struct kset_uevent_ops *uevent_ops, struct kobject *parent_kobj)