linux总线设备驱动模型之Kobject&Kset

来源:互联网 发布:启示录 知乎 编辑:程序博客网 时间:2024/05/17 23:24

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.oall: kobjkobj: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modulesclean: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.oall: ksetkset:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modulesclean:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean</span><span style="font-size:18px;">




0 0