歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Linux驅動之設備模型

1.Overview

l  設備模型是2.6內核引入的新特性,提供了一個一個獨立的機制專門來表示設備,並描述其在系統中的拓撲結構,使得系統具有以下優點:

n  代碼重復最小化

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<[email protected]>");

 

試驗結果:

Copyright © Linux教程網 All Rights Reserved