Kobject 與 sysfs 文件系統框架的分析
時間:2018-05-14作者:華清遠見
1、設備模型 2.6內核增加(jia)了一(yi)個引人注目的新特性------統一(yi)設備模型 設備模型提供了一(yi)個獨立的機制專門來表示(shi)設備,并(bing)描述在系統中的拓撲(pu)結構 (1)代碼重復最(zui)小(xiao)化(hua) (2)可以列(lie)出(chu)系統(tong)中所有的設備,觀察到他們(men)的狀態(tai),并且查看他們(men)連接(jie)的總線 (3) 可以將設備(bei)和其對應的(de)驅動聯系起來 (4) 可以(yi)按(an)照設(she)備類(lei)型進行分類(lei) 2、kobject 設備模型的核心部(bu)分就是kobject
struct kobject { const char *name; /*指向kobject的名字*/ struct list_head entry; struct kobject *parent/*指向(xiang)父kobject 實(shi)現(xian)層次(ci)結(jie)構*/ struct kset *kset; struct kobj_type *ktype; struct sysfs_dirent *sd;/*指向(xiang)sysfs_dirent結構體(ti) 這個結構體(ti)就(jiu)表示kobject對象(xiang)的層次結構*/ struct kref kref;/*提供引(yin)用計數 其核心成(cheng)(cheng)員是一(yi)原(yuan)子型變量(liang),用來表(biao)示內(nei)核對(dui)象(xiang)的(de)引(yin)用計數 內(nei)核通(tong)過該成(cheng)(cheng)員追蹤(zong)內(nei)核對(dui)象(xiang)生命周期(qi)*/ unsigned int state_initialized:1; unsigned int state_in_sysfs:1;/*是否已經加入sysfs*/ unsigned int state_add_uevent_sent:1; unsigned int state_remove_uevent_sent:1; }; 3、ktype
kobject對象被關聯到一種特殊的類型 即ktype(kernel object type的縮寫) ktype由kobj_type結構體來表示,定義于頭文件 struct kobj_type { void (*release)(struct kobject *kobj); struct sysfs_ops *sysfs_ops; struct attribute **default_attrs; }; 1)ktype的存在是(shi)為(wei)了描述一族kobject所具有的普遍特性(xing),實現同(tong)類的kobject都能共享相同(tong)的特性(xing) 2)release指(zhi)針指(zhi)向(xiang)在kobject引用(yong)計數減至零時調用(yong)析構函(han)數,該函(han)數負責釋放所有kobject使用(yong)的內存和其他(ta)相關的清理工作 3)defaults_attrars 結構體數(shu)組定(ding)義(yi)了(le)所有具有相同類型(xing)的(de)kobject對(dui)象的(de)屬性 4)sysfs文(wen)件(jian)系(xi)統根據對應(ying)的(de)kobject屬性來創建文(wen)件(jian) 4、kset 1)kset是(shi)kobject對(dui)象的(de)集合體,將相(xiang)關的(de)kobject集合到一起 2)具有相(xiang)同(tong)ktype的(de)kobject可以被分組到(dao)不同(tong)的(de)kset 5、管理和操(cao)作kobject kobject一(yi)般都(dou)被(bei)嵌(qian)入到設(she)備結(jie)構體中 (1)kobject的初(chu)始化一個(ge)kobject對象 void kobject_init(struct kobject *kobj,struct kobj_type *ktype) (2)定(ding)義并初始化 struct kobject *kobject_create(void) 6、引用計數 1)kobject通(tong)過引用計數控制對象的有效生命周期 (1)初(chu)始(shi)化(hua)后kobject的(de)引(yin)用計數置為1 (2)當引(yin)用計數為0時,則表示設備已經卸載(zai),不(bu)能(neng)在操作對應的(de)設備 2)操(cao)作引用計數(shu)的接(jie)口 (1)增加一個引用(yong)計數(shu) struct kobject *kobject_get(struct kobject *kobj) (2)減少一(yi)個引(yin)用(yong)計數 void kobject_put(struct kobject *kobj) 3)描述引(yin)用計(ji)數的結構(gou)kref kobject計數是通過kref實(shi)現 struct kref{ atomic_t refcount } (1)初始化 void kref_init(struct kref *kref) (2)增加一個計數(shu) void kref_get(struct kref *kref) (3)減一個計數(shu) void kref_put(struct kref *kref) 代碼: (1)創(chuang)建(jian)一(yi)個kobject對象并初(chu)始化 (2) 定制(zhi)自己的kobject對(dui)象創建與釋放函數 7、sysfs sysfs文(wen)(wen)(wen)件(jian)系統(tong)(tong)是(shi)一個處于內存中的虛擬文(wen)(wen)(wen)件(jian)系統(tong)(tong),用文(wen)(wen)(wen)件(jian)系統(tong)(tong)的方(fang)式(shi)提(ti)供kobject對象層次(ci)結構的視圖 bus:提供一個(ge)系(xi)統總線視圖 dev:提供已經注冊設(she)備節點的視圖 device:系統中設(she)備結(jie)構(gou)體視圖 class:給(gei)用戶(hu)的視圖 通過對(dui)device實際設備目錄的符號鏈接 kernel:包含內(nei)核(he)配置項和狀態(tai)信(xin)息 fs:已經注(zhu)冊(ce)文件系統的視圖 class與(yu)devices 一個(ge)是(shi)高層(ceng)概念 給(gei)用戶的視(shi)圖(tu) 一個(ge)底層(ceng)物(wu)理設備(bei) 給(gei)內核的視(shi)圖(tu) 8、sysfs添加和刪除kobject 將kobject對象映射到(dao)sysfs文件系(xi)統中,產(chan)生對應的文件 int kobject_add(struct kobject *kobj, struct kobject *parent, const char *fmt, ...) 從sysfs文件系統中(zhong)刪(shan)除一個(ge)kobject對應文件目錄,需(xu)要(yao)使用(yong)函數(shu)kobject_decl() void kobject_del(struct kobject *kobj) int kobject_set_name(struct kobject *kobj, const char *fmt, ...)//設置kobject對象(xiang)在sysfs中的名字 int sysfs_create_dir(struct kobject * kobj)//在(zai)sysfs文件(jian)系統中創(chuang)建目錄 void sysfs_remove_dir(struct kobject * kobj)//在sysfs文件(jian)系統中刪除目錄 struct kobject *kobject_get(struct kobject *kobj)//可以用來(lai)獲取kobj-parent 代碼3:將對應的kobject映射到對應sysfs文件系統中,增加my_kobject_add()函數my_kobject_del()函數 代碼4:將當前的kobject對象增加parent節點(dian) 增加my_kobject_create_and_add()函(han)數 9、向sysfs添加文件 1)默認的(de)文件集合通(tong)過kobject和(he)kset中的(de)ktype字段提供 2)具有(you)相同屬性的(de)kobject導入到sysfs文(wen)件系統(tong)中的(de)文(wen)件也(ye)具有(you)相同的(de)屬性 3)默認文件屬性由kobj_type結構(gou)來描述 struct kobj_type { void (*release)(struct kobject *kobj); struct sysfs_ops *sysfs_ops; struct attribute **default_attrs; }; 4)kobj_type結(jie)構中包(bao)含默認文件集合中所有文件的屬性, default_attrs 默認文件屬(shu)性結構體數(shu)組 struct attribute { const char *name; 屬性(xing)名(ming)稱,在(zai)sysfs文(wen)件系統中(zhong)顯示的名(ming)字 struct module *owner;所(suo)屬模塊 如果存在 mode_t mode;權限 }; sysfs 文件系(xi)統(tong)根(gen)據默認(ren)文件屬性建立對應的文件 5)增加新的文件(jian) (1)根據新文(wen)件(jian)屬性在sysfs文(wen)件(jian)系統(tong)創建(jian)文(wen)件(jian) int sysfs_create_file(struct kobject * kobj, const struct attribute * attr) { BUG_ON(!kobj || !kobj->sd || !attr); return sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_ATTR); } 6)對(dui)sysfs文件系統中的文件進行讀寫 struct sysfs_ops { 在(zai)讀sysfs文件(jian)時該方法會調用 ssize_t (*show)(struct kobject *, struct attribute *,char *); 在(zai)寫sysfs文件時(shi)該方法被調用 ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); }; struct kset *kset_create_and_add(const char *name,struct kset_uevent_ops *uevent_ops,struct kobject *parent_kobj)//創建一(yi)個kset集合 10、創建(jian)新屬性(xing) sysfs_create_link():增加新的鏈接 sysfs_remove_file():刪(shan)除新的文件 sysfs_remove_link() 刪除(chu)鏈(lian)接文件 代(dai)碼5:在sysfs文件系(xi)統中增加文件 代碼6:在sysfs文(wen)件系統中(zhong)增加多個文(wen)件,并設(she)置新文(wen)件的屬性 代碼7: 在(zai)sysfs文件(jian)系(xi)統中針對每個(ge)文件(jian)設置相應的(de)的(de)操作方法show()與store() 代碼8:底層實現(xian)led驅動并(bing)關聯到kobject對象中 11、uevent 1)kset是(shi)屬于一組kobject的集合 struct kset { struct list_head list; spinlock_t list_lock; struct kobject kobj; const struct kset_uevent_ops *uevent_ops; }; kset_uevent_ops : 當(dang)kset中的kobject對象(xiang)發生(sheng)狀(zhuang)態變化需(xu)要(yao)通知用戶空間 struct kset_uevent_ops { int (* const filter)(struct kset *kset, struct kobject *kobj); const char *(* const name)(struct kset *kset, struct kobject *kobj); int (* const uevent)(struct kset *kset, struct kobject *kobj, struct kobj_uevent_env *env); }; 2)kset相關的API void kset_init(struct kset *k) 初(chu)始化kset對(dui)象(xiang) int kset_register(struct kset *k) 初(chu)始化(hua)并(bing)向系統注冊一個kset對象 static void kobject_init_internal(struct kobject *kobj) 注冊kset對象 notes: .kset對(dui)象本身也是一個(ge)kobject內核對(dui)象,在sysfs文(wen)件系統中(zhong)生成一個(ge)新的(de)目錄 .注冊(ce)kset對象(xiang),內核(he)編譯啟用(yong)了CONFIG_HOTPLUG,則需要(yao)就(jiu)這一(yi)事(shi)件(jian)通知用(yong)戶空間(jian)(內核(he)配置文(wen)件(jian)中可以查(cha)詢) .事件通知由(you)kobject_uevent完成 .不屬(shu)于kset的kobject對象(xiang)不能完成事件(jian)通(tong)知 .kobject之間通過parent成(cheng)員實現層(ceng)次關系,當kobject的(de)parent為(wei)NULL時,就會把(ba)kobj->kset->kobj作為(wei)kobj的(de)parent struct kset *kset_create_and_add(const char *name, const struct kset_uevent_ops *uevent_ops, struct kobject *parent_kobj) 創建一個kset對(dui)象(xiang)并添加到sysfs文件系(xi)統中 3)hotplug(熱插拔(ba)) 當一個設備(bei)動態(tai)加入系統時,設備(bei)驅動程序可以檢(jian)查到設備(bei),并通(tong)過通(tong)知(zhi)的方(fang)式告知(zhi)用戶空間 通知用戶(hu)空間(jian)的方式(shi)一般有兩種:udev 與(yu) /sbin/hotplug,現在使用更多的是udev udev 的實現基(ji)于內核(he)中的網絡機制(zhi),通過標準的socket接口來(lai)監(jian)聽(ting)來(lai)自內核(he)的網絡廣播包,并(bing)對接收(shou)的包進行(xing)分(fen)析處(chu)理 4)hotplug相關的(de)API int kobject_uevent(struct kobject *kobj, enum kobject_action action) 發送一個 event給用戶(hu)空間(jian),以網絡(luo)數據(ju)包的形式發送給用戶(hu)空間(jian)應用程序 @action : 發送event類型 enum kobject_action { KOBJ_ADD, KOBJ_REMOVE, KOBJ_CHANGE, KOBJ_MOVE, KOBJ_ONLINE, KOBJ_OFFLINE, KOBJ_MAX }; kobject_uevent_env() sprintf(scratch, "%s@%s", action_string, devpath); @273L 傳遞給用戶(hu)空間event數據的內容 "事件類型@設備路徑" example: "add@/kset-test/kobject-test/" uevent一般與應用程(cheng)序(xu)結(jie)合起來使用,一般可以接收(shou)并處理(li)uevent的(de)應用程(cheng)序(xu)有udev or mdev udev工具通(tong)過(guo)netlink獲(huo)取內核發出的uevent消息,并且處理,加載相應(ying)的驅動或者在/dev/目(mu)錄下生(sheng)成對應(ying)的設備結點 udev服務啟動后,會掃描/sys目錄(lu)下所有具有uevent屬性(xing)文件,在進行相應的處理 uevent的觸發(fa)被(bei)封裝到設(she)備模型的操作中(zhong),當添加設(she)備的時則(ze)會發(fa)送一個uevent(user event)事件, udev 工具會通過netlink獲取uevent消息 ,然后(hou)進行加載驅動或者(zhe)在/dev/目錄下生成(cheng)對(dui)應的設備結點(dian) int device_add() { ...... kobject_uevent(&dev->kobj, KOBJ_ADD); ...... } 5)netlink機制(zhi) (1)netlink機(ji)制(zhi)的特點 .netlink是一種特殊(shu)的(de)socket .netlink可以實現內核(he)與應用程序(xu)進行雙向傳(chuan)輸通訊,并且使用socket()API進行交互 .netlink是(shi)一種異步通訊方式,在內核與用(yong)戶態進行傳(chuan)遞的消息(xi)(xi)保存在socket緩(huan)沖區數據隊列中(zhong),發送消息(xi)(xi)只是(shi)把消息(xi)(xi)保存在接(jie)收(shou)者的socket的接(jie)收(shou)隊列中(zhong),而不需要等待(dai)接(jie)收(shou)者收(shou)到消息(xi)(xi) (2)使用socket()創建netlink套接字 int socket(int domain, int type, int protocol); @domain:協議族 AF_NETLINK or PF_NETLINK @type :socket類型 SOCK_DGRAM or SOCK_RAW @protocol : 協(xie)議類型 NETLINK_KOBJECT_UEVENT (3)netlink地址(zhi)結構 struct sockaddr_nl { __kernel_sa_family_t nl_family; /* AF_NETLINK */ unsigned short nl_pad; /* zero */ __u32 nl_pid; /* port ID */ __u32 nl_groups; /* multicast groups mask */ }; @nl_family : AF_NETLINK 協議族 @nl_pad : 填0 @nl_pid : 進程(cheng)pid ,可以通過getpid()獲(huo)取 (3)使(shi)用setsockopt()設置套接字選項 setsockopt(sd, SOL_SOCKET, SO_RCVBUFFORCE, &buffersize, sizeof(buffersize)); @SO_RCVBUFFORCE:設置或者(zhe)獲取緩沖區的大小 (4)使用bind()綁(bang)定地址結構(gou) retval= bind(sd, (void*)&snl, sizeof(struct sockaddr_nl)) (5)讀取netlink接收緩(huan)沖區的(de)內容 read(sd, buf, sizeof(buf)); 相關資訊
發表評論
|
全國咨詢電話:400-611-6270,雙休日及節假(jia)日請致電值班手機:15010390966
在(zai)線咨(zi)詢: 曹老(lao)師(shi)(shi)QQ(3337544669), 徐老(lao)師(shi)(shi)QQ(1462495461), 劉老(lao)師(shi)(shi) QQ(3108687497)
企業(ye)培訓洽談(tan)專(zhuan)線:010-82600901,院校合作洽談(tan)專(zhuan)線:010-82600350,在線咨詢:QQ(248856300)
Copyright 2004-2018 華清遠(yuan)見教育科技集團 版權所(suo)有 ,京ICP備16055225號,京公(gong)海(hai)網(wang)安備11010802025203號