嵌入式linux中,请问文件系统和设备驱动程序是什么关系?用户应用程序如果去读写操作flash中的 50
嵌入式linux中,请问文件系统和设备驱动程序是什么关系?用户应用程序如果去读写操作flash中的文件数据,从分层的角度看,从上到下,是怎么一个调用关系?...
嵌入式linux中,请问文件系统和设备驱动程序是什么关系?用户应用程序如果去读写操作flash中的文件数据,从分层的角度看,从上到下,是怎么一个调用关系?
展开
1个回答
展开全部
1. What is sysfs?
个人理解:sysfs向用户空间展示了驱动设备的层次结构。我们都知道设备和对应的驱动都是由内核管理的,这些对于用户空间是不可见的。现在通过sysfs,可以在用户空间直观的了解设备驱动的层次结构。
我们来看看sysfs的文件结构:
[root@yj423 /sys]#ls
block class devices fs module
bus dev firmware kernel power
block:块设备
bus:系统中的总线
class: 设备类型,比如输入设备
dev:系统中已注册的设备节点的视图,有两个子目录char和block。
devices:系统中所有设备拓扑结构视图
fireware:固件
fs:文件系统
kernel:内核配置选项和状态信息
module:模块
power:系统的电源管理数据
2. kobject ,kset和ktype
要分析sysfs,首先就要分析kobject和kset,因为驱动设备的层次结构的构成就是由这两个东东来完成的。
2.1 kobject
kobject是一个对象的抽象,它用于管理对象。每个kobject对应着sysfs中的一个目录。
kobject用struct kobject来描述。
[cpp] view plain copy
struct kobject {
const char *name; /*在sysfs建立目录的名字*/
struct list_head entry; /*用于连接到所属kset的链表中*/
struct kobject *parent; /*父对象*/
struct kset *kset; /*属于哪个kset*/
struct kobj_type *ktype; /*类型*/
struct sysfs_dirent *sd; /*sysfs中与该对象对应的文件节点*/
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;
};
2.2 kset
kset是一些kobject的集合,这些kobject可以有相同的ktype,也可以不同。同时,kset自己也包含一个kobject。在sysfs中,kset也是对应这一个目录,但是目录下面包含着其他的kojbect。
kset使用struct kset来描述。
[cpp] view plain copy
/**
* 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; /*属于该kset的kobject链表*/
spinlock_t list_lock;
struct kobject kobj; /*该kset内嵌的kobj*/
struct kset_uevent_ops *uevent_ops;
};
2.3 ktype
每个kobject对象都内嵌有一个ktype,该结构定义了kobject在创建和删除时所采取的行为。
[cpp] view plain copy
struct kobj_type {
void (*release)(struct kobject *kobj);
struct sysfs_ops *sysfs_ops;
struct attribute **default_attrs;
};
struct sysfs_ops {
ssize_t (*show)(struct kobject *, struct attribute *,char *);
ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);
};
/* FIXME
* The *owner field is no longer used.
* x86 tree has been cleaned up. The owner
* attribute is still left for other arches.
*/
struct attribute {
const char *name;
struct module *owner;
mode_t mode;
};
当kobject的引用计数为0时,通过release方法来释放相关的资源。
attribute为属性,每个属性在sysfs中都有对应的属性文件。
sysfs_op的两个方法用于实现读取和写入属性文件时应该采取的行为。
2.4 kobject与kset的关系
下面这张图非常经典。最下面的kobj都属于一个kset,同时这些kobj的父对象就是kset内嵌的kobj。通过链表,kset可以获取所有属于它的kobj。
从sysfs角度而言,kset代表一个文件夹,而下面的kobj就是这个文件夹里面的内容,而内容有可能是文件也有可能是文件夹。
3.举例
在上一节中,我们知道sys下有一个bus目录,这一将分析如何通过kobject创建bus目录。
下面代码位于drivers/base/bus.c
[cpp] view plain copy
int __init buses_init(void)
{
bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
if (!bus_kset)
return -ENOMEM;
return 0;
}
static struct kset_uevent_ops bus_uevent_ops = {
.filter = bus_uevent_filter,
};
static int bus_uevent_filter(struct kset *kset, struct kobject *kobj)
{
struct kobj_type *ktype = get_ktype(kobj);
if (ktype == &bus_ktype)
return 1;
return 0;
}
这里直接调用kset_create_and_add,第一个参数为要创建的目录的名字,而第三个参数表示没有父对象。
下面代码位于drivers/base/kobject.c
[cpp] view plain copy
/**
* 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,
struct kset_uevent_ops *uevent_ops,
struct kobject *parent_kobj)
{
struct kset *kset;
int error;
kset = kset_create(name, uevent_ops, parent_kobj); /*建立kset,设置某些字段*/
if (!kset)
return NULL;
error = kset_register(kset); /*添加kset到sysfs*/
if (error) {
kfree(kset);
return NULL;
}
return kset;
}
这里主要调用了两个函数,接下分别来看下。
3.1 kset_create函数
下面代码位于drivers/base/kobject.c
[cpp] view plain copy
/**
* 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,
struct kset_uevent_ops *uevent_ops,
struct kobject *parent_kobj)
{
struct kset *kset;
kset = kzalloc(sizeof(*kset), GFP_KERNEL);/*分配kset*/
if (!kset)
return NULL;
kobject_set_name(&kset->kobj, name);/*设置kobj->name*/
kset->uevent_ops = uevent_ops;
kset->kobj.parent = parent_kobj; /*设置父对象*/
/*
* The kobject of this kset will have a type of kset_ktype and belong to
* no kset itself. That way we can properly free it when it is
* finished being used.
*/
kset->kobj.ktype = &kset_ktype;
kset->kobj.kset = NULL; /*本keset不属于任何kset*/
return kset;
}
个人理解:sysfs向用户空间展示了驱动设备的层次结构。我们都知道设备和对应的驱动都是由内核管理的,这些对于用户空间是不可见的。现在通过sysfs,可以在用户空间直观的了解设备驱动的层次结构。
我们来看看sysfs的文件结构:
[root@yj423 /sys]#ls
block class devices fs module
bus dev firmware kernel power
block:块设备
bus:系统中的总线
class: 设备类型,比如输入设备
dev:系统中已注册的设备节点的视图,有两个子目录char和block。
devices:系统中所有设备拓扑结构视图
fireware:固件
fs:文件系统
kernel:内核配置选项和状态信息
module:模块
power:系统的电源管理数据
2. kobject ,kset和ktype
要分析sysfs,首先就要分析kobject和kset,因为驱动设备的层次结构的构成就是由这两个东东来完成的。
2.1 kobject
kobject是一个对象的抽象,它用于管理对象。每个kobject对应着sysfs中的一个目录。
kobject用struct kobject来描述。
[cpp] view plain copy
struct kobject {
const char *name; /*在sysfs建立目录的名字*/
struct list_head entry; /*用于连接到所属kset的链表中*/
struct kobject *parent; /*父对象*/
struct kset *kset; /*属于哪个kset*/
struct kobj_type *ktype; /*类型*/
struct sysfs_dirent *sd; /*sysfs中与该对象对应的文件节点*/
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;
};
2.2 kset
kset是一些kobject的集合,这些kobject可以有相同的ktype,也可以不同。同时,kset自己也包含一个kobject。在sysfs中,kset也是对应这一个目录,但是目录下面包含着其他的kojbect。
kset使用struct kset来描述。
[cpp] view plain copy
/**
* 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; /*属于该kset的kobject链表*/
spinlock_t list_lock;
struct kobject kobj; /*该kset内嵌的kobj*/
struct kset_uevent_ops *uevent_ops;
};
2.3 ktype
每个kobject对象都内嵌有一个ktype,该结构定义了kobject在创建和删除时所采取的行为。
[cpp] view plain copy
struct kobj_type {
void (*release)(struct kobject *kobj);
struct sysfs_ops *sysfs_ops;
struct attribute **default_attrs;
};
struct sysfs_ops {
ssize_t (*show)(struct kobject *, struct attribute *,char *);
ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);
};
/* FIXME
* The *owner field is no longer used.
* x86 tree has been cleaned up. The owner
* attribute is still left for other arches.
*/
struct attribute {
const char *name;
struct module *owner;
mode_t mode;
};
当kobject的引用计数为0时,通过release方法来释放相关的资源。
attribute为属性,每个属性在sysfs中都有对应的属性文件。
sysfs_op的两个方法用于实现读取和写入属性文件时应该采取的行为。
2.4 kobject与kset的关系
下面这张图非常经典。最下面的kobj都属于一个kset,同时这些kobj的父对象就是kset内嵌的kobj。通过链表,kset可以获取所有属于它的kobj。
从sysfs角度而言,kset代表一个文件夹,而下面的kobj就是这个文件夹里面的内容,而内容有可能是文件也有可能是文件夹。
3.举例
在上一节中,我们知道sys下有一个bus目录,这一将分析如何通过kobject创建bus目录。
下面代码位于drivers/base/bus.c
[cpp] view plain copy
int __init buses_init(void)
{
bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
if (!bus_kset)
return -ENOMEM;
return 0;
}
static struct kset_uevent_ops bus_uevent_ops = {
.filter = bus_uevent_filter,
};
static int bus_uevent_filter(struct kset *kset, struct kobject *kobj)
{
struct kobj_type *ktype = get_ktype(kobj);
if (ktype == &bus_ktype)
return 1;
return 0;
}
这里直接调用kset_create_and_add,第一个参数为要创建的目录的名字,而第三个参数表示没有父对象。
下面代码位于drivers/base/kobject.c
[cpp] view plain copy
/**
* 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,
struct kset_uevent_ops *uevent_ops,
struct kobject *parent_kobj)
{
struct kset *kset;
int error;
kset = kset_create(name, uevent_ops, parent_kobj); /*建立kset,设置某些字段*/
if (!kset)
return NULL;
error = kset_register(kset); /*添加kset到sysfs*/
if (error) {
kfree(kset);
return NULL;
}
return kset;
}
这里主要调用了两个函数,接下分别来看下。
3.1 kset_create函数
下面代码位于drivers/base/kobject.c
[cpp] view plain copy
/**
* 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,
struct kset_uevent_ops *uevent_ops,
struct kobject *parent_kobj)
{
struct kset *kset;
kset = kzalloc(sizeof(*kset), GFP_KERNEL);/*分配kset*/
if (!kset)
return NULL;
kobject_set_name(&kset->kobj, name);/*设置kobj->name*/
kset->uevent_ops = uevent_ops;
kset->kobj.parent = parent_kobj; /*设置父对象*/
/*
* The kobject of this kset will have a type of kset_ktype and belong to
* no kset itself. That way we can properly free it when it is
* finished being used.
*/
kset->kobj.ktype = &kset_ktype;
kset->kobj.kset = NULL; /*本keset不属于任何kset*/
return kset;
}
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询