您的位置:首页 > 运维架构 > Linux

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

2016-10-16 18:20 716 查看
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 i
c039
s %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;">
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  kobjest