1.the linux device model--kobject kset学习笔记
http://blog.chinaunix.net/uid-22547469-id-4590385.html?utm_source=jiancool
Linux設備模型就是一棟規模宏大的建筑,為了構建它,需要基本的建筑材料鋼筋:kobject、若干鋼筋組成的鋼架結構:kset,還需要一種機制sysfs,來向外界(用戶空間的程序)展示其內部構造。并且通過文件接口的方式實現與外界溝通與互動。
設備文件系統:Linux下一切皆是文件,而設備文件系統包括設備文件、設備節點以及設備特定文件,它們是驅動程序的接口?,而在文件系統中,他們就像普通文件一樣。
devfs:是一種Linux2.4內核引入的設備文件系統,用來解決Linux中設備管理混亂的問題位于內核空間,可以通過程序在設備初始化時在/dev下創建設備文件,卸載時將它刪除,現已被udev取代。
udev:udev是一種工具,它能夠根據系統中的硬件設備的狀況動態更新設備文件,包括設備文件的創建,刪除等。設備文件通常放在/dev目錄下,使用udev后,在/dev下面只包含系統中真實存在的設備。它于硬件平臺無關的,位于用戶空間,需要內核sysfs和tmpfs的支持,sysfs為udev提供設備入口和uevent通道,tmpfs為udev設備文件提供存放空間。
mdev:在嵌入式系統中,通常可以用udev的輕量級版本mdev,集成于busybox。
sysfs:是Linux2.6所提供的一種跟devfs一樣的虛擬文件系統,基于ramfs(內存文件系統)開發,掛在到/sys目錄,也是用來對系統的設備進行管理的。sysfs以文件目錄層次結構展示了系統硬件設備間的一個拓撲圖。
設備、驅動、總線:這些都是對象,已經是宏偉建筑給外界的展現形式的那部分了,主要是與這三個打交道。
詳細實現:
1、kobject[鋼筋]
kobject是組成設備模型的一個最底層的核心數據結構,與sysfs文件系統自然的綁定在一起:每個kobject對應sysfs文件系統中一個目錄。kobject結構所能處理的任務以及所支持的代碼包括:
(1)引用計數;
(2)維持容器的層次列表和組。
(3)為容器的屬性提供一種用戶態查看的視圖。
(4)熱插拔事件的處理:當系統中的硬件熱插拔時,在kset(其內嵌有kobject)內核對象的控制下,將產生事件以通知用戶空間,該結構一般沒有單獨定義而是嵌入到其他設備結構體中。
kobject定義如下:
點擊(此處)折疊或打開
創建kobject的時候,都回、會給每個kobject一系列默認屬性。這些屬性保存在kobj_type結構中。
點擊(此處)折疊或打開
kobject一般不單獨定義,常內嵌于其他結構體中。
經常遇到相反的問題,對于給定的一個kobject指針,如何獲得包含他的結構指針呢?嘎嘎,大名鼎鼎的container_of宏有有用了。
比如kp是指向kobj的指針,而kobj是cdev?device的一個成員,如何根據kp獲取只想cdev的指針,如下:
struct?cdev?*device=container_of(kp,struct?cdev,kobj);
?
kobject相關函數:
(1)初始化前第一個操作,將整個kobject設置為0,通常使用memset函數,例如:memset(&kobj,0,sizeof(struct?kobject));
(2)設定kobject中的name成員,使用如下函數:
int?kobject_set_name(struct?kobject?*kobj,const?char?*fmt,...)
(3)初始化一個內核對象的kobject結構,建立kojbect對象間的層次關系,在sysfs中建立一個目錄:
int?kobject_init_and_add(struct?kobject?*kobj,
struct?kobj_type?ktype,struct?kobject?*parent,const?char?*fmt,...)
(4)從linux設備層次中刪除kobj對象:
void?kobject_del(struct?kobject?*kobj);
(5)增加kobject引用計數:
struct?kobject?*?kobject_get(struct?kobject?*?kobj)
(6)減少kobject引用計數:
void?kobject_put(struct?kobject?*?kobj)
(7)每個kobject都必須有一個release方法,該方法保存在kobject相關聯的kobj_type中。
在sysfs中,kobject對應目錄,kobject的屬性對應這個目錄下的文件。調用show和store函數來讀寫文件,就可以得到屬性中的內容。
點擊(此處)折疊或打開
編譯完成后生成kobject.ko文件,執行sudo?insmod?kobject.ko
加載成功,因該kobject的parent是NULL,會在sys的目錄之間建立如下文件:
打開文件夾后,會看到兩個屬性文件:
first_attr是777權限,second_attr是只讀權限,和程序中寫的相同。
接下來,執行?cat?first_attr,會發現驅動層自動調用了ktype中的sysfs_ops的show函數:
同理,執行echo?“123”?>?first_attr,應該調用ops_store函數,執行結果如下:
和預想完全相同。同理可測試second_attr文件,只是不能寫而已。
2、kset[由若干個kobject(鋼筋)組成的鋼架結構]
kset是同種類型的kobject對象的集合,也可以說是對象的容器,通過kset數據結構可以將kobjects組成一顆層次樹。kset的名字保存在內嵌的kobject中。
包含在kset中的所有kobject被組織成一個雙向循環鏈表,list是這個鏈表的鏈表頭。kset數據結構還內嵌了一個kobject對象(kobj),所有屬于這個kset的kobject對象的parent域均指向這個內嵌的對象。此外,kset還依賴kobj維護引用計數。
kset和它的kobject的關系如下圖所示:
黑線:kset?child?list
綠線:kobject->parent
藍線:kobject->kset
注意:一個kobject的父節點不一定是包含他的kset。
?
數據結構如下:
點擊(此處)折疊或打開
kset相關函數:
創建一個對象時,通常要把一個kobject添加到kset中去。兩個步驟:
先把kobject內的kset指針指向目的kset
int?kobject_add(struct?kobject?*kobj);
(1)初始化一個kset對象:
void?kset_init(struct?kset?*?k);
(2)用來初始化并向系統注冊一個kset對象:
int?kobject_register(struct?kobject?*kobj);
(3)注銷kset
void?kset_unregister(struct?kset?*k);
(4)某些時候,將kobject從kset中刪除,使用:
void?kobject_del(struct?kobject?*kobj);
點擊(此處)折疊或打開
執行sudo?insmod?kset.ko:出現如下信息;
在/sys文件夾,會生成kset_p文件夾,打開該文件夾后,出現kset_c文件夾。
3、子系統(一個子系統其實就是對kset和一個信號量的封裝)
點擊(此處)折疊或打開
子系統函數列表如下:
void?subsystem_init(struct?kset?*);
int??subsystem_register(struct?kset?*);
void?subsystem_unregister(struct?kset?*);
struct?kset?*subsys_get(struct?kset?*s);
void?subsys_put(struct?kset?*s);
4、屬性
非默認屬性
如果希望在kobject的sysfs目錄中添加新的屬性,只需要填寫一個attribute結構,并把它傳遞給下面的函數。
int?sysfs_create_file(struct?kobject?*kobj,struct?attribute?*attr);
刪除屬性:
int?sysfs_remove_file(struct?kobject?*kobj,struct?attribute?*attr);
二進制屬性(比如支持向設備上載固件的功能)
先定義一個二進制屬性結構:
struct?bin_attribute?{
struct?attribute attr;//名字,所有者,二進制屬性的權限
size_t size;//最大長度,如果沒有最大值設置為0
void *private;
ssize_t?(*read)(struct?kobject?*,?char?*,?loff_t,?size_t);
ssize_t?(*write)(struct?kobject?*,?char?*,?loff_t,?size_t);
int?(*mmap)(struct?kobject?*,?struct?bin_attribute?*attr,
????struct?vm_area_struct?*vma);
};
必須顯式的創建二進制屬性
int??sysfs_create_bin_file(struct?kobject?*kobj,struct?bin_attribute?*attr);
void?sysfs_remove_bin_file(struct?kobject?*kobj,struct?bin_attribute?*attr);
符號鏈接
sysfs具有常用的樹形結構,但是內核中各對象之間的關系遠比這復雜。這些樹并不能表示驅動程序及其管理的設備之間的關系,為了表示這種關系還需要其他的指針,那就是符號鏈接。
int?sysfs_create_link(struct?kobject?*kobj,struct?kobject?*target,const?char?*name);
void?sysfs_remove_link(struct?kobject?*,?const?char?*?name);
5、熱插拔機制(從內核空間發送到用戶空間的通知)
當一個設備動態加入系統時(比如插入一個U盤),設備驅動程序可以檢查到這種設備狀態的變化(加入或移除),然后通過某種機制使得在用戶空間找到該設備對應的驅動程序模塊并加載之。在linux系統上有兩種機制可以在設備狀態發生變化時,通知用戶空間去加載或者卸載該設備所對應的驅動程序模塊:一個是udev,另一個是/sbin/hotplug。在Linux早期階段只有唯一的/sbin/hotplug工具,隨著內核的發展,udev機制逐漸取代了/sbin/hotplug。很多ubuntu系統已經不提供/sbin/hotplug工具了。
udev熱插拔機制:以守護進程的形式運行,通過偵聽內核發出來的?uevent?來管理?/dev目錄下的設備文件。不像之前的設備管理工具,udev?在用戶空間?(user?space)?運行,而不在內核空間?(kernel?space)?運行。(驗證:ps?aux?|?grep?udevd);當設備添加?/?刪除時,udev的守護進程偵聽來自內核的uevent,以此添加或者刪除?/dev下的設備文件,所以udev只為已經連接的設備產生設備文件,而不會在/dev下產生大量虛無的設備文件;通過?Linux?默認的規則文件,udev在/dev/?里為所有的設備定義了內核設備名稱,比如/dev/sda、/dev/hda、/dev/fd等等。由于udev是在用戶空間(user?space)運行,Linux?用戶可以通過自定義的規則文件,靈活地產生標識性強的設備文件名,比如?/dev/boot_disk、/dev/root_disk、/dev/color_printer等等。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
總結
以上是生活随笔為你收集整理的1.the linux device model--kobject kset学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大数据汇聚全球精英
- 下一篇: table分页的简单实现逻辑