1 sysfs文件系统:
作用: 用于向用户描述内核的驱动组织关系和内部结构。
其中kobject 和 kset是这个文件系统的组成“砖瓦”
2 sysfs文件系统在linux内核启动的初级阶段会被初始化。
二 kobject
1 kobject是linux设备驱动模型的组成架构最主要元素,它实现了类似于C++的继承
2 每一个kobject对象对应于sysfs文件系统的一个目录
3 kobject在内核源码<include/linux/object.h>中被定义
struct kobject{
/*对象名称*/
const char *name;
/*用于组织链表的指针*/
struct list_head entry;
/*指向父对象的指针(父目录)*/
struct kobject *parent;
/*指向所属 kset容器的指针*/
struct kset *kset;
/*对象属性描述*/
struct ktype *ktype;
/*在sysfs中的目录*/
struct sysfs_dirent *sd;
/*引用计数*/
struct kref kref;
unsigned int state_initialized:1;
unsigned int state_in_sysfs:1;
unsigned int state_add_uevenr_sent:1;
unsigned int state_remove_uevent_sent:1;
unsigned int state_uevent_suppress:1;
}
注:如果kboject属于某个kset那么它的变化就可以通过这个kset来向用户空间发送消息。
其中state_uevent_suppress标志位用于决定是否向用户空间发送消息。
4 用法;kobject嵌入某个对象当中。比如在字符设备对象当中
struct cdev{
struct kobject *kobj;
struct module *owmer;
const struct file_operation *ops;
struct list_head list;
dev_t dev;
unsigned int count;
}
5 相关函数
kobject_set_name(struct kobject *kobj,const char *fmt,......);
用于设置对象名称
kobject_init用于初始化kobject,在<lib/kobject.c>中。
主要代码如下:
void kobject_init(struct kobjcet* kobj,struct kobj_type *ktype)
{
......
kobject_init_internal(kobj);
kobj->ktype = ktype;
return ;
}
在kobject_init中做两件事:1 调kobject_init_internal实现大部分初始化 2 指定ktype
kobject_init_internl在<lib/kobject.c>中实现,主要代码如下。
kobject_init_inernal(struct object *kobj)
{
if(!kobject)
return;
kref_init(kobj->kref);
INIT_LIST_HEAD(&kobject->entry);
kobj->state_in_sysfs = 0 ;
kobj->state_add_uevent_sent = 0;
kobj->state_remove_uevent_sent= ;
lobj->state_initialized = 1;
}
int kobject_add(struct kobject* kobj,struct kobj *parent,const char *fmt......)
这个函数可以实现kobject之间的层次关系,并且将这个kobject添加到sysfs当中去。
这个函数将parent传递给kobj后调用kobject_add_initernl()
在<lib/kobject.c>中实现。
/*设置好parent变量 然后创建目录*/
int kobject_add_internal(struct kobject *kobj)
{
...
/*先取得kobj的parent成员*/
parent = kobject_get(&kobject->parent);
/*在kboj属于某个kset的情况下 如果其parent为NULL
就将其parent设为kset的kobj
*/
if(kobj->kset){
if(!parent){
parent = kobject_get(&kobj->kset->kobj);
kobj_kset_jion(kobj);
kobj->parent = parent;
}
}
....
}
接下来kobject_add_internal还会调用sysfs_create_dir(struct kobject *kobj)
用来创建目录。在<fs/sys/dir.c>中实现
sysfs_create_dir(struct kobject *kobj){
...
if(kobj->parent)
parent_sd = kobj->parent->sd;
else
parent_sd = &sysfs_root;
...
error = creat_dir(kobj,parent_sd,type,ns,kobject_name(kobj),&sd);
if(!error)
kobj->sd = sd;
return error;
}
注:在sysfs文件系统中一个目录的数据结构是sd实例。
一个kobj对象都会嵌入一个sd成员,所以一个kobj对象就是对应一个目录
内核中,将init和add两个函数合并之后得到kobject_init_and_add(struct kobject *kobj,struct kobj_type *ktype,
struct kobject *parent,const char *fmt,...)函数。
struct kobject *kobject_creat()用于分配并且初始化一个kobject
实现如下:
struct kobject *kobject_creat()
{
struct kobject *kobj;
kobj = kzalloc(sizeof(*kobj),GFP_KERNEL);
if(!kobj)
return NULL;
kobject_init(kobj,&dynamic_kob_ktype);
return kobj;
}
显然,如果我们要重新制定自己的kobject type那么我们需要再调用其他函数。
三 kboject的属性。
在kobject中有一个kob_type类型的成员ktype 用于描述kobject的属性。
在inlcude/linux/kobject.h 中定义如下;
四 kset
kset是一个管理kobj的数据结构,它将kobj组成一个链表来管理,一旦这些链表中的kobj发生改变,
kset就首先调用操作集中的filter函数,如果函数通过,那么就向用户空间进行通知广播。
kset的定义如下:
struct kset
{
struct list_head list ;
spinlock_ list_lock;
struct kobject kobj;
const struct kset_uevent_ops *uevent_ops;
}
主要操作函数有:
1 kset_register(struct kset *k)
{
int err;
if(!k)
return -EINVAL;
kset_init(k);
err = kobject_add_internal(&k->kobj);
if(err)
return err;
kobject_uevent(&k->kobj,KOBJ_ADD);/*通知内核有kset的kboj被添加*/
}
2 creat_and_add(const char *name,const struct kset_uevent_ops *uevent_ops,
struct kobject *parent_kobj);
用于创建一个kset并加入sysfs中
作用: 用于向用户描述内核的驱动组织关系和内部结构。
其中kobject 和 kset是这个文件系统的组成“砖瓦”
2 sysfs文件系统在linux内核启动的初级阶段会被初始化。
二 kobject
1 kobject是linux设备驱动模型的组成架构最主要元素,它实现了类似于C++的继承
2 每一个kobject对象对应于sysfs文件系统的一个目录
3 kobject在内核源码<include/linux/object.h>中被定义
struct kobject{
/*对象名称*/
const char *name;
/*用于组织链表的指针*/
struct list_head entry;
/*指向父对象的指针(父目录)*/
struct kobject *parent;
/*指向所属 kset容器的指针*/
struct kset *kset;
/*对象属性描述*/
struct ktype *ktype;
/*在sysfs中的目录*/
struct sysfs_dirent *sd;
/*引用计数*/
struct kref kref;
unsigned int state_initialized:1;
unsigned int state_in_sysfs:1;
unsigned int state_add_uevenr_sent:1;
unsigned int state_remove_uevent_sent:1;
unsigned int state_uevent_suppress:1;
}
注:如果kboject属于某个kset那么它的变化就可以通过这个kset来向用户空间发送消息。
其中state_uevent_suppress标志位用于决定是否向用户空间发送消息。
4 用法;kobject嵌入某个对象当中。比如在字符设备对象当中
struct cdev{
struct kobject *kobj;
struct module *owmer;
const struct file_operation *ops;
struct list_head list;
dev_t dev;
unsigned int count;
}
5 相关函数
kobject_set_name(struct kobject *kobj,const char *fmt,......);
用于设置对象名称
kobject_init用于初始化kobject,在<lib/kobject.c>中。
主要代码如下:
void kobject_init(struct kobjcet* kobj,struct kobj_type *ktype)
{
......
kobject_init_internal(kobj);
kobj->ktype = ktype;
return ;
}
在kobject_init中做两件事:1 调kobject_init_internal实现大部分初始化 2 指定ktype
kobject_init_internl在<lib/kobject.c>中实现,主要代码如下。
kobject_init_inernal(struct object *kobj)
{
if(!kobject)
return;
kref_init(kobj->kref);
INIT_LIST_HEAD(&kobject->entry);
kobj->state_in_sysfs = 0 ;
kobj->state_add_uevent_sent = 0;
kobj->state_remove_uevent_sent= ;
lobj->state_initialized = 1;
}
int kobject_add(struct kobject* kobj,struct kobj *parent,const char *fmt......)
这个函数可以实现kobject之间的层次关系,并且将这个kobject添加到sysfs当中去。
这个函数将parent传递给kobj后调用kobject_add_initernl()
在<lib/kobject.c>中实现。
/*设置好parent变量 然后创建目录*/
int kobject_add_internal(struct kobject *kobj)
{
...
/*先取得kobj的parent成员*/
parent = kobject_get(&kobject->parent);
/*在kboj属于某个kset的情况下 如果其parent为NULL
就将其parent设为kset的kobj
*/
if(kobj->kset){
if(!parent){
parent = kobject_get(&kobj->kset->kobj);
kobj_kset_jion(kobj);
kobj->parent = parent;
}
}
....
}
接下来kobject_add_internal还会调用sysfs_create_dir(struct kobject *kobj)
用来创建目录。在<fs/sys/dir.c>中实现
sysfs_create_dir(struct kobject *kobj){
...
if(kobj->parent)
parent_sd = kobj->parent->sd;
else
parent_sd = &sysfs_root;
...
error = creat_dir(kobj,parent_sd,type,ns,kobject_name(kobj),&sd);
if(!error)
kobj->sd = sd;
return error;
}
注:在sysfs文件系统中一个目录的数据结构是sd实例。
一个kobj对象都会嵌入一个sd成员,所以一个kobj对象就是对应一个目录
内核中,将init和add两个函数合并之后得到kobject_init_and_add(struct kobject *kobj,struct kobj_type *ktype,
struct kobject *parent,const char *fmt,...)函数。
struct kobject *kobject_creat()用于分配并且初始化一个kobject
实现如下:
struct kobject *kobject_creat()
{
struct kobject *kobj;
kobj = kzalloc(sizeof(*kobj),GFP_KERNEL);
if(!kobj)
return NULL;
kobject_init(kobj,&dynamic_kob_ktype);
return kobj;
}
显然,如果我们要重新制定自己的kobject type那么我们需要再调用其他函数。
三 kboject的属性。
在kobject中有一个kob_type类型的成员ktype 用于描述kobject的属性。
在inlcude/linux/kobject.h 中定义如下;
四 kset
kset是一个管理kobj的数据结构,它将kobj组成一个链表来管理,一旦这些链表中的kobj发生改变,
kset就首先调用操作集中的filter函数,如果函数通过,那么就向用户空间进行通知广播。
kset的定义如下:
struct kset
{
struct list_head list ;
spinlock_ list_lock;
struct kobject kobj;
const struct kset_uevent_ops *uevent_ops;
}
主要操作函数有:
1 kset_register(struct kset *k)
{
int err;
if(!k)
return -EINVAL;
kset_init(k);
err = kobject_add_internal(&k->kobj);
if(err)
return err;
kobject_uevent(&k->kobj,KOBJ_ADD);/*通知内核有kset的kboj被添加*/
}
2 creat_and_add(const char *name,const struct kset_uevent_ops *uevent_ops,
struct kobject *parent_kobj);
用于创建一个kset并加入sysfs中