sysfs檔案系統:linux2.6引入的全新的檔案系統,它是基于核心的虛拟檔案系統,其作用是将核心資訊一檔案的形式呈現給使用者。
sys部分目錄結構:
.
├── block
│ ├── loop0 -> ../devices/virtual/block/loop0
│ ├── loop1 -> ../devices/virtual/block/loop1
│ ├── loop2 -> ../devices/virtual/block/loop2
├── bus
│ ├── acpi
│ │ ├── devices
│ │ │ ├── ACPI0003:00 -> ../../../devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0003:00
│ │ │ ├── AUI1627:00 -> ../../../devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:01/AUI1627:00
│ │ │ ├── device:00 -> ../../../devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00
│ │ ├── drivers
│ │ │ ├── ac
│ │ │ │ ├── ACPI0003:00 -> ../../../../devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0003:00
│ │ │ ├── battery
│ │ │ │ ├── bind
│ │ └── uevent
├── class
│ ├── ata_device
│ │ ├── dev1.0 -> ../../devices/pci0000:00/0000:00:1f.2/ata1/link1/dev1.0/ata_device/dev1.0
│ │ ├── dev2.0 -> ../../devices/pci0000:00/0000:00:1f.2/ata2/link2/dev2.0/ata_device/dev2.0
│ │ ├── dev3.0 -> ../../devices/pci0000:00/0000:00:1f.2/ata3/link3/dev3.0/ata_device/dev3.0
├── dev
│ ├── block
│ │ ├── 1:0 -> ../../devices/virtual/block/ram0
│ │ └── 8:9 -> ../../devices/pci0000:00/0000:00:1f.2/ata5/host4/target4:0:0/4:0:0:0/block/sda/sda9
│ └── char
│ ├── 10:1 -> ../../devices/virtual/misc/psaux
│ ├── 10:183 -> ../../devices/virtual/misc/hw_random
│ ├── 10:184 -> ../../devices/virtual/misc/microcode
│ ├── 89:8 -> ../../devices/pci0000:00/0000:00:01.1/0000:07:00.0/i2c-8/i2c-dev/i2c-8
│ └── 89:9 -> ../../devices/pci0000:00/0000:00:01.1/0000:07:00.0/i2c-9/i2c-dev/i2c-9
├── devices
│ ├── breakpoint
│ │ ├── perf_event_mux_interval_ms
│ │ ├── power
│ │ ├── events
│ │ │ ├── branch-instructions
├── fs
│ ├── bpf
│ ├── cgroup
│ │ ├── blkio
│ │ │ ├── blkio.io_merged
│ │ │ ├── blkio.io_merged_recursive
│ │ │ ├── blkio.io_queued
│ │ │ ├── blkio.io_queued_recursive
│ │ │ ├── blkio.io_service_bytes
│ │ │ ├── blkio.io_service_bytes_recursive
│ │ │ ├── blkio.io_serviced
├── hypervisor
├── kernel
│ ├── boot_params
│ │ ├── data
│ │ └── version
│ ├── debug [error opening dir]
│ ├── fscaps
└── power
├── disk
├── image_size
├── pm_async
├── pm_freeze_timeout
kobject:實作了基本的面向對象的管理機制,是構成linux2.6裝置模型的核心結構,是所有總線、裝置和驅動的抽象基類,每一個kobject對應一個sysfs檔案系統中的一個目錄。
kobject原型:
struct kobject {
const char *name;
struct list_head entry;
struct kobject *parent;
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;
};
對kobject的初始化、添加、删除、等操作函數:
void kobject_init(struct kobject *kobj); //初始化
int kobject_add(struct kobject *kobj);//添加
void kobject_init_and_add(struct kobject* kobj,struct kobj_type *ktpye,struct kobject *parent,const char *fmt,...);
void kobject_del(struct kobject *kobj);
struct kobject *kobject_get(struct kobject *kobj);//将kobject對象的引用加一,同時傳回該對象的指針。
void kobject_put(struct kobject *kobj);//将kobject對象的引用減一,若為0則調用relase函數釋放該kobject對象。
struct kobj_type原型:
struct kobj_type{
void (*release)(struct kobject *kobj);
struct sysfs_ops *sysfs_ops;
strcut attribute **default_attrs;
};
release:釋放kobject占用的資源,當kobject的應用為0時調用。
sysfs_ops:設定擷取檔案的屬性資訊。
attribute:對應object目錄下的一個檔案。
struct sysfs_ops原型:
struct sysfs_ops{
ssize_t (*show) (struct kobject *,struct attribute *,char *);
ssize_t (*store) (struct kobject *,struct attribute *,const char *,size_t);
};
show:使用者讀檔案屬性時,該函數将屬性值存入buf中傳回給使用者。
store:使用者寫屬性檔案時,該函數将使用者寫入的值傳入屬性值中。
struct attribute原型:
struct attribute{
char *name; //屬性(檔案)名
struct module *owner;
mode_t mode;//屬性(檔案)保護位
};
kset具有相同類型的kobject集合,在sysfs檔案系統中形成一個目錄。
struct kest原型:
struct kset{
struct list_head list; //連接配接該kest中所有kobject的連結清單頭
spinlock_t list_lock;
struct kobject kobj; //内嵌的kobject
struct kset_uevent_ops *uevent_ops; //處理熱插拔事件的操作集合
};
struct kest_uevent_ops原型:
struct kest_uevent_ops{
int (*filter)(struct kest *kset,struct kobject *kobj);
const char *(*name)(struct kset *kset,struct kobject *kobj);
int (*uevent)(struct kset *kset,struct kobject *kobj,struct kobj_uevent_env *env);
};
filter:決定是否将事件傳遞到使用者,若filter傳回值為0,将不傳遞事件。
name:用于将字元串傳遞給使用者空間的熱插拔處理程式。
uevent:将使用者空間需要的參數添加到環境變量中。
熱插拔事件:
在linux系統中,當系統配置發生變化時,如添加kset到系統、移動kobject,一個通知會從核心發送到使用者空間,這就是熱插拔事件。熱插拔事件會導緻使用者空間中相應的處理程式被調用,這些處理程式,會通過加載驅動程式,建立裝置節點等來響應熱插拔事件。
kobject具體事例:
/*
* kobj.c
*
* Created on: 2016年10月16日
* Author: chy
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/sysfs.h>
#include <linux/stat.h>
void release_test(struct kobject *test);
ssize_t test_show(struct kobject *obj,struct attribute *attr,char *buff);
ssize_t test_store(struct kobject *obj,struct attribute *attr,char *buff,size_t zie);
struct attribute attr = {
.name = "lobject_test",
.mode = S_IRWXUGO,
};
struct attribute att[] = {
&attr,
NULL,
};
struct sysfs_ops sysfs = {
.show = test_show,
.store = test_store,
};
struct kobj_type type = {
.release = release_test,
.sysfs_ops = &sysfs,
.default_attrs = att,
};
void release_test(struct kobject *test)
{
printk("del test");
return;
}
ssize_t test_show(struct kobject *obj,struct attribute *attr,char *buff)
{
printk("show_func test\n");
printk("this name is %s\n",attr->name);
sprintf(buff,"%s",attr->name);
return strlen(attr->name) + 2;
}
ssize_t test_store(struct kobject *obj,struct attribute *attr,char *buff,size_t szie)
{
printk("write %s\n",buff);
return szie;
}
struct kobject s;
static int __init kobj_init(void)
{
printk("this test start\n");
kobject_init_and_add(&s,&type,NULL,"obj_test");
return 0;
}
static int __exit kobj_exit(void)
{
printk("this is test end\n");
kobject_del(&s);
return 0;
}
MODULE_AUTHOR("David Xie");
MODULE_LICENSE("GPL v2");
module_init(kobj_init);
module_exit(kobj_exit);
Makefile:
obj-m := /src/kobj.o
all: kobj
kobj:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
kset具體執行個體:
/*
* obj_set.c
*
* Created on: 2016年10月16日
* Author: chy
*/
#include <linux/stat.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/sysfs.h>
int filter_test(struct kset *kset,struct kobject *kobj)
{
printk("this is filter\n");
return 1;
}
const char *name_test(struct kset *kset,struct kobject *kobj)
{
char buff[256];
printk("kobj name is %s\n",kobj->name);
sprintf(&buff,"%s","kset");
return buff;
}
int ssenv(struct kset *kset,struct kobject *kobj,struct kobj_uevent_env *env)
{
int i = 0;
printk("uevent: kobj %s.\n",kobj->name);
while( i < env->envp_idx){
printk("%s.\n",env->envp[i]);
i++;
}
return 0;
}
struct kset_uevent_ops envs = {
.filter = filter_test,
.name = name_test,
.uevent = ssenv,
};
struct kset set_s,set_p;
static int __init test_init(void)
{
printk("init test\n");
kobject_set_name(&set_s.kobj,"set.s");
set_s.uevent_ops = &envs;
kset_register(&set_s);
kobject_set_name(&set_p.kobj,"set.p");
set_p.kobj.kset = &set_s;
kset_register(&set_p);
return 0;
}
static int __exit test_exit(void)
{
printk("set test end\n");
kset_unregister(&set_s);
kset_unregister(&set_p);
return 0;
}
module_init(test_init);
module_exit(test_exit);</span><span style="font-size:18px;">
Makefile:
obj-m :=kset.o
all: kset
kset:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean</span><span style="font-size:18px;">