Linux驱动之设备模型


1.Overview

l  设备模型是2.6内核引入的新特性,提供了一个一个独立的机制专门来表示设备,并描述其在系统中的拓扑结构,使得系统具有以下优点:

n  代码重复最小化

n  提供诸如引用计数这样的统一机制

n  可以列举系统中所有的设备,观察它们的状态,并查看它们连接的总线

n  可以将系统中的全部设备结构以树的形式完整、有效地展现出来

n  可以将设备和其对应的驱动联系起来,反之亦然

n  可以将设备按照类型加以归类,比如归类为输入设备,而无需理解物理设备的拓扑结构

可以沿设备树的叶子向其根的方向依次遍历,以保证能以正确顺序关闭个设备的电源

最后一点是实现设备模型的最初动机。

 

l  作为Linux驱动工程师,掌握设备模型是非常必要的。掌握了设备驱动模型,再去阅读内核源码,发现自己会在一个更高的高度阅读代码。

 

2.  kobject

2.1  overview

设备模型的核心部分就是kobject(kernel object),由struct kobject结构体表示,在sysfs中表现为一个目录。

 

2.2  kobject结构体

l  Kobject是组成设备模型的基本结构,通常嵌入到其它结构体中,这样就可以通过kobject来访问该结构体

struct kobject {

         const char                  *name;    /* kobject名称 */

         struct list_head        entry;     /* 用于链入所属的kset的链表 */

         struct kobject           *parent;   /* 指向kobject的父对象 */

         struct kset                 *kset;     /* 所属kset */

         struct kobj_type       *ktype;   /* 所属ktype */

         struct sysfs_dirent  *sd;      /* sysfs中的目录项 */

         struct kref                  kref;       /* 提供引用计数 */

         unsigned intstate_initialized:1;  /* 标志:初始化 */

         unsigned intstate_in_sysfs:1;   /* 标志:在sysfs中 */

         unsigned intstate_add_uevent_sent:1;     /* 标志:已发出KOBJ_ADDuevent */

         unsigned intstate_remove_uevent_sent:1;/* 标志:已发出KOBJ_REMOVE uevent */

         unsigned intuevent_suppress:1;     /* 标志:禁止发出uevent*/

};

 

2.3  kobject的基本操作

Kobject操作函数实现在kobject.c文件中,这里介绍常用的几个

l  初始化

voidkobject_init(struct kobject *kobj, struct kobj_type *ktype)

l  Kobject添加,在sysfs产生一个目录

intkobject_add(struct kobject *kobj, struct kobject *parent,

                   constchar *fmt, ...)

l  初始化和添加

intkobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype,

                             struct kobject *parent, const char *fmt, ...)

l  创建和添加

struct kobject *kobject_create_and_add(const char *name,struct kobject *parent)

l  删除

void kobject_del(struct kobject *kobj)

l  引用数加一

struct kobject*kobject_get(struct kobject *kobj)

l  引用数减一,当引用计数减到0时,会调用release函数进行销毁工作

voidkobject_put(struct kobject *kobj)

 

2.3  实例解析

创建一个kobject,并建立一个属性文件

/*

*       forlearn kobject

*/

#include <linux/module.h>

#include <linux/init.h>

#include <linux/kobject.h>

#include <linux/sysfs.h>

#include <linux/string.h>

 

static int n = 6;

/* 当用户空间读取一个属性时,有调用到此方法把指定的值编码后放入缓冲区 */

static ssize_t sc_show(struct kobject*kobj,

                            structkobj_attribute *attr, char *buf)

{

         returnsprintf(buf, "%d\n", n);

}

/* 当用户空间写入一个属性时,有调用到此方法把指定的值解码后放入传递给相应变量 */

static ssize_t sc_store(struct kobject*kobj,

                            structkobj_attribute *attr, const char *buf, size_t count)

{

         sscanf(buf,"%du", &n);

         returncount;

}

 

/* 构建kobject的属性 */

static struct kobj_attribute sc_attrb =

         __ATTR(sc_example,0666, sc_show, sc_store);

 

static struct kobject *kobj;

 

static int __init example_init(void)

{

         intret;

 

         /*create kobject, a dir(kobj_example) in sys/ */

         kobj= kobject_create_and_add("kobj_example", NULL);

         if(!kobj)

                   return- ENOMEM;

        

         /*create a attribute file(sc_example) in kobj_example */

         ret= sysfs_create_file(kobj, &sc_attrb.attr);

         if(ret)

                   gotoattr_file_failed;

         return0;

        

attr_file_failed:

         kobject_put(kobj);

         returnret;

}

 

static void __exit example_exit(void)

{

         sysfs_remove_file(kobj,&sc_attrb.attr);

         kobject_put(kobj);

}

 

module_init(example_init);

module_exit(example_exit);

 

MODULE_LICENSE("Dual BSD/GPL");

MODULE_AUTHOR("CJOK<cjok.liao@gmail.com>");

 

试验结果:

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 下一页

相关内容