Linux設備驅動模型kobject

1、sysfs文件系統是一種特殊的文件系統,與/proc相似,通常被安裝於 /sys目錄。/proc文件系統首次被設計成允許用戶態應用程序訪問內核內部數據結構的一種文件系統。/sysfs文件系統本質上與/proc文件系統有相同的目的,但它還提供關於內核數據結構的附加信息。(摘自深入理解Linux內核第525頁)
2、sysfs文件系統的目標是要展現設備驅動程序模型組件間的層次關係。該文件系統的相應高層目錄是:
	block :塊設備,它們獨立於所連接的總線。	
	bus:系統中用於連接設備的總線。每個總線目錄包含兩個子目錄:devices、drivers;devices:包含了再整個系統中發現的屬於該		  總線類型的設備,drivers:包含註冊到該總線的所有設備驅動。
	devices:所有被內核識別的硬件設備,依照連接他們的總線進行組織。
	drivers:在內核中註冊的設備驅動程序。
	classs:系統中的設備類型(聲卡、網卡、顯卡等等);同一類可能包含由不同總線連接的設備,於是由不同的驅動程序驅動。(按			照功能進行分類)
	power:處理一些硬件設備電源狀態的文件。
	firmware:處理一些硬件設備的固件文件。
3、設備驅動程序模型的核心數據結構是一個普通的數據結構,j叫做kobject,它與sysfs文件系統自然的綁定在一起:每個kobject對應於sysfs文件系統中的一個目錄。kobject被嵌入一個叫做”容器“的更大的對象中,容器描述設備驅動程序模型中的組件。容器的典型例子有總線、設備以及驅動程序的描述符;例如,第一個IDE磁盤的第一個分區描述符對應於/sys/block/hda/hda1目錄。
每個kobject由kobject數據結構描述,各字段如下所示:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
char *	k_name; //指向含有容器名稱的字符串
char []	name; //含有容器名稱的字符串
struct kref	kref; //容器的引用計數器
struct list_head	entry; //用於kobject所插入的鏈表的指針
struct kobject *	parent; //指向父kobject(如果存在的話)
struct kset *	kest;//指向包含的kset
struct kobj_type *	ktype; //指向kobject的類型描述符
struct dentry *		dentry; //指向與kobject相對應的sysfs文件的dentry數據結構
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ktype字段指向kobj_type對象,該對象描述了kobject的 ”類型“,本質上它描述的是包括kobject的容器的類型。kobj_type數據結構包括三個字段:release方法(當kobject被釋放時執行),指向sysfs操作表的sysfs_ops指針以及sysfs文件系統的缺省屬性鏈表。
struct attribute{
const char *name;//屬性文件名
struct module *owner;
mode_t  mode;
}
4、kobject對象操作
         1)voidkobject_init(struct kobject * kobj)初始化kobject結構
         2)intkobject_add(struct kobject * kobj)將kobject對象註冊到Linux系統
         3)intkobject_init_and_add(struct kobject *kobj, struct kobj_type*ktype,struct kobject *parent, const char *fmt, ...)初始化kobject,並將其註冊到linux系統
           4)voidkobject_del(struct kobject * kobj)從Linux系統中刪除kobject對象
           5)structkobject *kobject_get(struct kobject*kobj)將kobject對象的引用計數加1,同時返回該對象指針。
           6)voidkobject_put(struct kobject *kobj)將kobject對象的引用計數減1,如果引用計數降爲0,則調用release方法釋放該kobject對象。
5、下面是一個簡單的kobject的例子:
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include <linux/stat.h>
 
MODULE_AUTHOR("David Xie");//定義驅動的編程者爲 "David Xie"
MODULE_LICENSE("Dual BSD/GPL");//告訴內核,該模塊採用自由許可證
 
void obj_test_release(struct kobject *kobject);
ssize_t kobj_test_show(struct kobject *kobject, struct attribute *attr,char *buf);
ssize_t kobj_test_store(struct kobject *kobject,struct attribute *attr,const char *buf, size_t count);
 
struct attribute test_attr = {//sysfs文件系統的屬性
        .name = "kobj_config", //屬性文件名稱
        .mode = S_IRWXUGO, //屬性文件訪問權限
};
 
static struct attribute *def_attrs[] = {
        &test_attr,
        NULL,
};
 
//struct sysfs_ops中包含show和store兩個函數指針,它們分別在sysfs文件讀和文件寫時調用。  
struct sysfs_ops obj_test_sysops =
{
        .show = kobj_test_show,
        .store = kobj_test_store,
};
 
struct kobj_type ktype = 
{
        .release = obj_test_release,//kobject釋放的時候被調用
        .sysfs_ops=&obj_test_sysops,//操作的函數
        .default_attrs=def_attrs,//屬性
};
 
void obj_test_release(struct kobject *kobject)
{
        printk("eric_test: release .\n");
}
 
ssize_t kobj_test_show(struct kobject *kobject, struct attribute *attr,char *buf)
{
        printk("have show.\n");
        printk("attrname:%s.\n", attr->name);
        sprintf(buf,"%s\n",attr->name);
        return strlen(attr->name)+2;
}
 
ssize_t kobj_test_store(struct kobject *kobject,struct attribute *attr,const char *buf, size_t count)
{
        printk("havestore\n");
        printk("write: %s\n",buf);
        return count;
}
 
struct kobject kobj;
static int kobj_test_init()
{
        printk("kboject test init.\n");
        kobject_init_and_add(&kobj,&ktype,NULL,"kobject_test");
        return 0; 
}
 
static int kobj_test_exit()
{
        printk("kobject test exit.\n");
        kobject_del(&kobj);
        return 0;
}
 
module_init(kobj_test_init);//insmod時候,調用初始化函數
module_exit(kobj_test_exit);//rmmod,調用退出函數
///////////////////////////////////////////////////////////////////////////////////////////////////////////
假設這個代碼,編譯後的模塊的名稱爲kobject.ko,則運行結果如下
insmod kobject.ko
kboject test init.
lsmod
kobject 1884 0 - Live 0xbf000000
此時在查看/sys文件的時候,發現多了一個名稱爲"kobject_test"文件夾。
進入kobject_test目錄,會發現多了一個文件
cd kobject_test
ls
kobj_config

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章