【Linux】sysfs文件系统
前言
一、sysfs文件系统
1.1 sysfs系统是什么
sysfs是一种虚拟文件系统,提供一种访问内核数据结构的方法从而允许用户空间程序查看和控制系统的设备和资源。
sysfs文件系统是挂载在sys文件目录下的,我们可以通过sys下面的目录和文件清楚的了解Linux系统的嵌入式设备的系统状况。sysfs 把连接在系统上的设备和总线组织成为一个分级的文件,它们可以由用户空间存取,向用户空间导出内核的数据结构Q以及它们的属性。
sysfs 的一个目的就是展示设备驱动模型中各组件的层次关系,如下图所示:
在sys目录下,各文件的功能如下:
1.2 sysfs的运行机制原理
sysfs 提供一种机制,使得可以显式的描述内核对象、对象属性及对象间关系。
- 一组接口,针对内核,用于将设备映射到文件系统中。
- 一组接口,针对用户程序,用于读取或操作这些设备。描述了内核中的 sysfs 要素及其在用户空间的表现,如下图所示:
sys下面的目录和文件反映了整台机器的系统状况。这些目录代表了完全不同的设备类型,这些目录只是给我们提供了如何去看整个设备模型的不同视角。真正的设备信息放在 devices 子目录下,Linux 系统中的所有设备都可以在这个目录里找到。如上图所示,bus 下对应驱动和设备,classes下有设备的不同分类,分类下也对应各种设备,实际上它们都是 devices 目录下设备文件的符号链接。
二、sysfs中重要的结构体
2.1 kobject和kset之间的关系
从下面的图,非常清晰的知道kset和kobject之间的关系和联系。
2.2 kobject结构体
kobject是设备模型的核心,在后台运行。它为内核带来类似于面向对象的编程风格。
在内核中include/linux/kobject.h中定义了kobject结构体,在kobject结构体中包含了一些成员变量,其中比较重要的name、parent、sd、kref以及ktype。具体结构代码如下:
/*
name: 指向这个kobject的名称。使用kobject_set_name(struct kobject* kobj,const char * name)函数可以修改它。
entry: 简单讲就是要挂载入kset的链表。
parent: 指向此kobject父项的指针。它用于构建描述对象之间关系的层次结构。
sd: 指向struct sysfs dirent结构,它表示该结构内sysfs节点中的这个kobject。
kref: 提供kobject上的引用计数。
ktype: 描述该对象,kset说明这个对象属于哪套(组)对象。
*/
struct kobject {
const char *name;
struct list_head entry;
struct kobject *parent;
struct kset *kset;
struct kobj_type *ktype;
struct kernfs_node *sd; /* sysfs directory entry */
struct kref kref;
#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
struct delayed_work release;
#endif
unsigned int state_initialized:1; //初始化状态
unsigned int state_in_sysfs:1; //是否在sys中
unsigned int state_add_uevent_sent:1;
unsigned int state_remove_uevent_sent:1;
unsigned int uevent_suppress:1;
};
常使用kobject_create_and_add来进行创建和添加目录。在添加到系统之前,必须使用kobject_ create()函数分配kobject,并将已经分配但尚未初始化的kob ject指针及其kobject_type 指针作为参数。kobject_add()函数用于添加kobject并将其链接到系统,同时根据其层次结构创建目录及其默认属性。功能与之相反的函数是kobject_ del(),将kobject删除链接。
struct kobject *kobject_create(void)
{
struct kobject *kobj;
kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
if (!kobj)
return NULL;
kobject_init(kobj, &dynamic_kobj_ktype);
return kobj;
}
struct kobject *kobject_create_and_add(const char *name, struct kobject *parent)
{
struct kobject *kobj;
int retval;
kobj = kobject_create();
if (!kobj)
return NULL;
retval = kobject_add(kobj, parent, "%s", name);
if (retval) {
printk(KERN_WARNING "%s: kobject_add error: %d\n",
__func__, retval);
kobject_put(kobj);
kobj = NULL;
}
return kobj;
}
2.3 kset结构体
内核对象集(kset)主要将相关的内核对象组合在一起,kset是object的集合。
kset结构体还比kobject多了一个链表头,可以将子目录项对应的kobject结构体实例加入该链表,使得kset可以遍历这些子目录项的kobject。
struct kset {
struct list_head list; //挂载kobject结构的链表
spinlock_t list_lock; //保护链表访问的自旋锁
struct kobject kobj; //自身包含一个kobject结构
const struct kset_uevent_ops *uevent_ops;
} __randomize_layout;