设备驱动模型 - kobject

目录

一. 设备驱动模型简介

二. kobject简介

2.1 kobject内核数据结构

2.2 kobject操作内核接口

三. kobject实例

3.1 Makefile

3.2 实例1

3.3 实例2

3.4 实例3


一. 设备驱动模型简介

     Linux设备模型的核心是使用Bus、Class、Device、Driver四个核心数据结构,将大量的、不同功能的硬件设备(以及驱动该硬件设备的方法),以树状结构的形式,进行归纳、抽象,从而方便Kernel的统一管理。

    linux将这些数据结构的共同功能抽象出来,同一实现, 表示为 kobject。

  • 通过parent指针,将所有kobject以层次结构的形式组合起来。
  • 使用引用计数(reference count)来表示kobject被引用的次数,并且在ref变为0时,释放掉。
  • 它与sysfs文件系统紧密相连,每个注册的kobject都对应sysfs文件系统中的一个目录。即"/sys/"下的某个目录。
  • kobject:是总线、驱动、设备的三种对象的一个基类,实现公共接口。
  • ktype:记录了kobject对象的一些属性。
  • kset:是同类型kobject对象的集合,即一个容器; 是特殊的kobject,故也会在"/sys/"下的某个目录。
     

二. kobject简介

    Kobject实现了基本的面向对象管理机制,是构成Linux设备模型的核心结构。它与sysfs文件系统紧密相连,在内核中注册的每个kobject对象对应sysfs文件系统中的一个目录。
    类似于C++中的基类,Kobject常被嵌入于其他类型(即:容器 kset)中。如bus,devices, drivers 都是典型的容器。这些容器通过kobject连接起来,形成了一个树状结构。

    kset与kobject的关系:

kset, kobject,sysfs的关系:

2.1 kobject内核数据结构

struct kobject {
    const char              *name;       /*名字*/      
    struct list_head        entry;         /*连接到kset建立层次结构*/
    struct kobject          *parent;     /*指向父节点,面向对象的层次架构。即反应到sysfs中为父目录*/
    struct kset             *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;
    /*是否处在sysfs下了*/
    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;
};


/*成员变量结构*/
/*1. 名称:kobj_type
     作用:Kobject的ktype成员是一个指向kobj_type结构的指针,该结构中记录了kobject对象的一些属性。
     注:
     release:用于释放kobject占用的资源,当kobject的引用计数为0时被调用。
*/
struct kobj_type {
    void (*release)(struct kobject *kobj);   /*用于释放kobject占用的资源*/
    const struct sysfs_ops *sysfs_ops;       /*属性文件的读写回调函数*/
    struct attribute **default_attrs;        /*默认属性文件列表*/
    const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);
    const void *(*namespace)(struct kobject *kobj);
};

/*2. 名称:sysfs_ops
     作用:kobj读写操作回调函数,负责分发到各个attribute的show和store函数中。
     注:
*/
struct sysfs_ops {
    /*应用层读数据:当用户读属性文件时,该函数被调用,该函数将属性值存入buffer中返回给用户态;*/
    ssize_t    (*show)(struct kobject *, struct attribute *, char *);  
        
    /*应用层写数据:当用户写属性文件时,该函数被调用,用于存储用户传入的属性值。*/          
    ssize_t    (*store)(struct kobject *, struct attribute *, const char *, size_t);
};

/*3. 名称:attribute
     作用:属性。对应于kobject的目录下的一个文件,Name成员就是文件名。
     注:
*/
struct attribute {
    const char              *name;             /*属性文件名*/
    umode_t                 mode;              /*属性的文件属性*/
#ifdef CONFIG_DEBUG_LOCK_ALLOC
    bool                    ignore_lockdep:1;
    struct lock_class_key   *key;
    struct lock_class_key   skey;
#endif
};

/*4. 名称:kobj_attribute
     作用:读写操作回调函数。
     注:
*/
struct kobj_attribute {
    struct attribute attr;
    /*具体attribute属性文件的读操作函数*/
    ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr, char *buf);
    
    /*具体attribute属性文件的写写操作函数*/
    ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count);
};

2.2 kobject操作内核接口

/*1.初始化kobject结构*/
void kobject_init(struct kobject * kobj)

/*2.将kobject对象注册到Linux系统*/
int kobject_add(struct kobject * kobj)

/*3.初始化kobject,并将其注册到linux系统*/
int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype,
    struct kobject *parent, const char *fmt, ...)

/*4.从Linux系统中删除kobject对象*/
void kobject_del(struct kobject * kobj)

/*5.将kobject对象的引用计数加1,同时返回该对象指针。*/
struct kobject *kobject_get(struct kobject *kobj)

/*6.将kobject对象的引用计数减1,如果引用计数降为0,则调用release方法释放该kobject对象。*/
void kobject_put(struct kobject * kobj)


三. kobject实例

3.1 Makefile

ifneq ($(KERNELRELEASE),)
    obj-m := object_test.o
else
    PWD  := $(shell pwd)
KDIR := /lib/modules/$(shell uname -r)/build

all:
        $(MAKE) -C $(KDIR) M=$(PWD) modules

clean:
        rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions modules.order Module.symvers
endif

3.2 实例1

#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/ioport.h>
#include <linux/errno.h>
#include <linux/workqueue.h>
#include <linux/platform_device.h>
#include <linux/types.h>
#include <linux/io.h>
#include <linux/slab.h>


static struct kobject *my_kobj = NULL;

static void my_release(struct kobject *kobj)
{
    printk("%s :in\n", __FUNCTION__);
    kfree(my_kobj);
}


static struct kobj_type my_ktype = {
    .release = my_release,
};

static int __init kobj_test_init(void)
{
    int err = 0;
    printk("%s :in\n", __FUNCTION__);
    
    my_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL);
    if (!my_kobj)
        return -ENOMEM;

    kobject_init(my_kobj, &my_ktype);

    err = kobject_add(my_kobj, NULL, "%s_kobj", "my");
    if (err) {
        printk("kobj_test init kobject_add error!\n");
        goto err;
    }

    return 0;

err:
    kobject_put(my_kobj);
    return err;
}


static void __exit kobj_test_exit(void)
{
    printk("%s :in\n", __FUNCTION__);
    kobject_del(my_kobj);
    kobject_put(my_kobj);
}

module_init(kobj_test_init);
module_exit(kobj_test_exit);
MODULE_AUTHOR("vector");
MODULE_LICENSE("Dual BSD/GPL");


结果:

3.3 实例2

#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/ioport.h>
#include <linux/errno.h>
#include <linux/workqueue.h>
#include <linux/platform_device.h>
#include <linux/types.h>
#include <linux/io.h>
#include <linux/slab.h>


static struct kobject *my_kobj = NULL;

static void my_release(struct kobject *kobj)
{
    printk("%s :in\n", __FUNCTION__);
    kfree(my_kobj);
}

/*用于分发到各个具体的attr属性文件中的show,store函数中*/
static ssize_t my_sysfs_ops_show(struct kobject *kobj, struct attribute *attr, char *buf)
{
    struct kobj_attribute *my_attr;
    ssize_t ret = -EIO;
    my_attr = container_of(attr, struct kobj_attribute, attr);
    if (my_attr->show)
        ret = my_attr->show(kobj, my_attr, buf);

    return ret;
}
static ssize_t my_sysfs_ops_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count)
{
    struct kobj_attribute *my_attr;
    ssize_t ret = -EIO;
    my_attr = container_of(attr, struct kobj_attribute, attr);
    if (my_attr->store)
        ret = my_attr->store(kobj, my_attr, buf, count);

    return ret;
}

/*
static ssize_t my_sysfs_ops_show(struct kobject *kobj, struct attribute *attr, char *buf)
{
    strcpy(buf, "sysfs ops show");
    return strlen("sysfs ops show");
}
static ssize_t my_sysfs_ops_store(struct kobject *kobj, struct attribute *attr,const char *buf, size_t count)
{
    printk("sysfs ops store %s", buf);
    return count;
}
*/

static const struct sysfs_ops my_sysfs_ops = {
    .show = my_sysfs_ops_show,
    .store = my_sysfs_ops_store,
};

static struct kobj_type my_ktype = {
    .sysfs_ops = &my_sysfs_ops,
    .release = my_release,
};



static ssize_t my_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
    printk("%s :in\n", __FUNCTION__);
    strcpy(buf, "my kobject show");
    return strlen("my kobject show");
}
static ssize_t my_store(struct kobject *kobj, struct kobj_attribute *attr,
    const char *buf, size_t count)
{
    printk("%s :in, %s!\n", __FUNCTION__, buf);
    return count;
}
static struct kobj_attribute my_attr =
    __ATTR(my, 0644, my_show, my_store);



static ssize_t your_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
    printk("%s :in\n", __FUNCTION__);
    strcpy(buf, "your kobject show");
    return strlen("your kobject show");
}
static ssize_t your_store(struct kobject *kobj, struct kobj_attribute *attr,
    const char *buf, size_t count)
{
    printk("%s :in, %s!\n", __FUNCTION__, buf);
    return count;
}
static struct kobj_attribute your_attr =
    __ATTR(your, 0644, your_show, your_store);



static int __init kobj_test_init(void)
{
    int err = 0;
    printk("%s :in\n", __FUNCTION__);
    
    my_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL);
    if (!my_kobj)
        return -ENOMEM;

    kobject_init(my_kobj, &my_ktype);

    err = kobject_add(my_kobj, NULL, "%s_kobj", "my");
    if (err) {
        printk("kobj_test init kobject_add error!\n");
        kobject_put(my_kobj);
        goto err;
    }

    err = sysfs_create_file(my_kobj, &my_attr.attr);
    if (err)
        printk("kobj_test_init, sysfs_create_file error!\n");

    
    err = sysfs_create_file(my_kobj, &your_attr.attr);
    if (err)
        printk("kobj_test_init, sysfs_create_file error!\n");

    return 0;

err:
    kobject_put(my_kobj);
    return err;
}


static void __exit kobj_test_exit(void)
{
    printk("%s :in\n", __FUNCTION__);
    sysfs_remove_file(my_kobj, &my_attr.attr);
    sysfs_remove_file(my_kobj, &your_attr.attr);
    kobject_del(my_kobj);
    kobject_put(my_kobj);
}

module_init(kobj_test_init);
module_exit(kobj_test_exit);
MODULE_AUTHOR("vector");
MODULE_LICENSE("Dual BSD/GPL");


结果:

3.4 实例3

#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/ioport.h>
#include <linux/errno.h>
#include <linux/workqueue.h>
#include <linux/platform_device.h>
#include <linux/types.h>
#include <linux/io.h>
#include <linux/slab.h>


static struct kobject *my_kobj = NULL;


static ssize_t my_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
    printk("%s :in\n", __FUNCTION__);
    strcpy(buf, "my kobject show");
    return strlen("my kobject show");
}
static ssize_t my_store(struct kobject *kobj, struct kobj_attribute *attr,
    const char *buf, size_t count)
{
    printk("%s :in, %s!\n", __FUNCTION__, buf);
    return count;
}
static struct kobj_attribute my_attr =
    __ATTR(my, 0644, my_show, my_store);


static ssize_t your_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
    printk("%s :in\n", __FUNCTION__);
    strcpy(buf, "your kobject show");
    return strlen("your kobject show");
}
static ssize_t your_store(struct kobject *kobj, struct kobj_attribute *attr,
    const char *buf, size_t count)
{
    printk("%s :in, %s!\n", __FUNCTION__, buf);
    return count;
}
static struct kobj_attribute your_attr =
    __ATTR(your, 0644, your_show, your_store);


/*group way*/
static  struct attribute *kobject_attrs[] = {
    &my_attr.attr,
    &your_attr.attr,
    NULL,
};
static const struct attribute_group kobject_attr_group = {
    .attrs = kobject_attrs,
};


static int __init kobj_test_init(void)
{
    int err = 0;
    printk("%s :in\n", __FUNCTION__);
    
    my_kobj = kobject_create_and_add("my_kobj", NULL);
    if (!my_kobj)
        return -1;    
/*
    err = sysfs_create_file(my_kobj, &my_attr.attr);
    if (err)
        printk("kobj_test_init, sysfs_create_file error!\n");

    
    err = sysfs_create_file(my_kobj, &your_attr.attr);
    if (err)
        printk("kobj_test_init, sysfs_create_file error!\n");
*/

    err = sysfs_create_group(my_kobj, &kobject_attr_group);    
    if (err) {
        printk("failed to create kobject attr group!\n");
        goto err;
    }
    return 0;
err:
    kobject_put(my_kobj);
    return err;
}


static void __exit kobj_test_exit(void)
{
    printk("%s :in\n", __FUNCTION__);
    sysfs_remove_file(my_kobj, &my_attr.attr);
    sysfs_remove_file(my_kobj, &your_attr.attr);
    kobject_del(my_kobj);
    kobject_put(my_kobj);
}

module_init(kobj_test_init);
module_exit(kobj_test_exit);
MODULE_AUTHOR("vector");
MODULE_LICENSE("Dual BSD/GPL");

相关博客:
https://blog.csdn.net/Guet_Kite/article/details/78368928

  • 3
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值