kobject
->kobject *parent
->kset
->struct list_head //指向了所包含的kobject的煉表頭
->struct kobject kobj
->kobj_type
->void (*release) (struct kobject *kobj)
->struct sysfs_ops *sysfs_ops;
....
(1).kobject如果沒有指定父節點,parent將指向kset內嵌的kobject。
(2)每個kobject都有它的kobj_type欄位指標,用來表示kobject在檔案系統中
的操作方法。relase方法是在kobject釋放時呼叫,sysfs_ops指向kobject
對應的檔案操作,default_attrskobject的預設屬性,sysfs_ops將使用這
個屬性。
一、kobject在核心的結構:
(1)kobject_create_and_add()函式建立kobject,掛到父kobject,並設定其kobj_type,在檔案系統中為其建立目錄和屬性檔案等。
kobject_create_and_add()
->kobject_create()
->kobject_init()
->kobject_init_internal()
->kobject_add()
->kobject_add_varg()
->kobject_set_name_vargs(kobj, fmt, vargs)
->kvasprintf()
->kobject_add_internal()
->kobject_get(kobj->parent);
->create_dir(kobj)
->sysfs_create_dir(kobj);
->populate_dir(kobj)
->sysfs_remove_dir(kobj)
函式說明:
kobject_create_and_add()介面函式,kobject新增到檔案系統中去(實際上是新增到其父節點所代表的kset中去)
kobject_create()為要建立的kobject分配記憶體空間並對其初始化.
kobject_init()對kobject基本字段進行初始化,用輸入引數設定kobj_type屬性.
kobject_add_varg中將把fmt指向的內容賦給kobject的name欄位。
kobject_set_name_vargs(kobj, fmt, vargs),如果kobj的name欄位指向的內容為空,則為分配乙個記憶體空
間並用fmt指向的內容初始化,把位址賦給kobj的name欄位。
kobject_add_varg()返回kobject_add_internal(kobj),就是在這個函式理為kobj建立檔案系統結構
kobject_add_internal()檢查kobj和它的name欄位,不存在則返回錯誤資訊
arent = kobject_get(kobj->parent);獲得其父節點,並增加父節點的計數器,kobject結構中的
kref欄位用於容器的計數,kobject_get和kobject_put分別
增加和減少計數器,如果計數器為0,則釋放該kobject,
kobject_get返回該kobject。
create_dir()函式中具體建立了那些內容
sysfs_create_dir()先為kobj建立了乙個目錄檔案
如果kobj->parent為null,就把&sysfs_root作為父節點sd,即在/sys下面建立結
點。populate_dir:然後呼叫
由於上面kobject_init(kobj, &dynamic_kobj_ktype)用預設dynamic_kobj_ktype作為kobj_type引數,而dynamic_kobj_ktype的default_attrs為null,所以這裡沒有建立屬性檔案。
至此,我們已經知道了kobject_create_and_add()函式建立kobject,掛到父kobject,並設定其kobj_type,在檔案系統中為其建立目錄和屬性檔案等。
另外,如果我們已靜態定義了要建立的kobject,則可以呼叫kobject_init_and_add()來註冊kobject
int kobject_init_and_add()
(2)我們已靜態定義了要建立的kobject,則可以呼叫kobject_init_and_add()來註冊kobject
(3)核心提供登出kobject的函式是kobject_del()
二、kset在核心中的結構:
(1)核心同樣提供了建立和註冊kset的函式kset_create_and_add()
->先呼叫kset_create ()建立乙個kset,接著呼叫kset_register()註冊它
->kset_create()中kset內嵌的kobject(這裡還未將kobject註冊到檔案系統),另外用輸
入引數初始化kset的uevent_ops欄位。
->kset_register()呼叫kobject_add_internal()將kset內嵌的kobject註冊到檔案系統, 這個函式我們在上面已經分析。
->註冊kset會產生乙個事件,就是在這裡呼叫了kobject_uevent(&k->kobj, kobj_add)
->如果kobj的kset和parent欄位都不存在,說明找不到所屬kset,也就沒有 uevent_ops,不能產生事件,返回錯誤資訊;相反則找到了存在kset的kobj 或父kobject(依次往上找),並賦值給uevent_ops。
->add_uevent_var()kobj_uevent_env填充action_string,kobject路徑,
子系統名稱以及其他指定環境變數
->呼叫uevent_ops的uevent函式,程式設計人員可在此函式中實現自定義的
功能。->設定kobj_add和kobj_remove的標誌。
->新增home和path環境變數。
->呼叫hotplug函式。
(2)kset_unregister() 減少其內嵌的kobj計數,為0則釋放其記憶體空間。
常用函式:
1 #define mkdev(major,minor) (((major) << minorbits) | (minor)) 將主裝置號和次裝置號轉換成
dev_t型別
2 struct list_head ;
#define list_head_init(name)
->list_head()
#define list_head(name) \
struct list_head name = list_head_init(name)
static inline void init_list_head(struct list_head *list)
常見函式:
cdev_alloc(void)
-> kzalloc(sizeof(struct cdev), gfp_kernel)
->init_list_head(&p->list)
->kobject_init(&p->kobj, &ktype_cdev_dynamic)
cdev_init(...)
->init_list_head(&cdev->list)
->kobject_init(&cdev->kobj, &ktype_cdev_default)
->cdev->ops = fops;
cdev_add(...)
->kobj_map(...) kobj_map 結構的 cdev_map 變數中包含乙個雜湊表用來快速訪問所有的物件。
kobj_map() 函式就是用來把字元裝置編號和 cdev 結構變數一起保 存到 cdev_map 這個雜湊表裡。當後續要開啟乙個字元裝置檔案時, 通過呼叫 kobj_lookup() 函式,根據裝置編號就可以找到 cdev 結 構變數,從而取出其中的 ops 字段。
驅動 網絡卡驅動 linux核心網路分層結構
preface linux核心對網路驅動程式使用統一的介面,並且對於網路裝置採用物件導向的思想設計。linux核心採用分層結構處理網路資料報。分層結構與網路協議的結構匹配,既能簡化資料報處理流程,又便於擴充套件和維護。核心網路結構 在linux核心中,對網路部分按照網路協議層 網路裝置層 裝置驅動功...
linux驅動結構pci之resource
linux設計了乙個通用的資料結構resource來描述各種i o資源 如 i o埠 外設記憶體 dma和irq等 該結構定義在include linux ioport.h標頭檔案中 struct resource linux是以一種倒置的樹形結構來管理每一類i o資源 如 i o埠 外設記憶體 d...
linux網路驅動體系結構
在分析網絡卡驅動程式之前,我們先來了解一下linux網路驅動體系結構 我們來說一下流程 當網路裝置驅動載入時,首先在入口函式裡面完成一些初始化工作,這主要就是對net device結構體的設定,以及跟硬體相關的設定,其中發包和收包函式比較重要。ifconfig up來配置網絡卡的時候,會呼叫net ...