設備模型2

前言

在上一篇中,我們大致描述了LINUX設備模型,我們先來總結一下三要素的關系。

?

Linux設備模型 - 哥哥 - 哥哥

?

從圖中可以看出,Linux設備模型就是"總線、設備、驅動、類"這四個概念之前的相互關系;這也是Linux2.6內核抽象出來的用于管理系統中所有設備的模型圖;
簡單地描述設備模型的層次關系如下:
1、驅動核心中可以注冊多種類型的總線(bus_type);
2、每一種類型的總線下面可以掛載許多設備(device);
3、每一種類型的總線可以使用很多設備驅動(device_driver);
4、每一個驅動程序可以管理一組設備;
這種基本關系的建立源于實際系統中各種總線、設備、驅動、類結構的抽象;

?

設備模型之kobject、kset

?

kobject是設備模型中一個很基本的概念,最初支持為了支持引用計數,但是隨著時間的轉移,它承擔了越來越多的任務:

1)對象的引用計數

2)SYS表述

3)數據結構關聯

4)熱插拔處理

?

?

它的定義如下:

struct kobject {

//名稱
?constchar??*name;


?struct list_head?entry;

//指向kobject的父對象,以此來在內核中構造一個對象層次結構,并且可以將多個對象之間的關系表現初來,這就是sysfs的真相:一個用戶空間的文件系統,用來表示內核中kobject對象的層次結構。
?structkobject??*parent;


?structkset??*kset;
?struct kobj_type?*ktype;
?struct sysfs_dirent?*sd;


?structkref??kref;
?unsigned int state_initialized:1;
?unsigned int state_in_sysfs:1;
?unsigned int state_add_uevent_sent:1;
?unsigned int state_remove_uevent_sent:1;
?unsigned int uevent_suppress:1;
};

一個kobject存在的意義在于把高級對象連接到設備模型上。kobject正如最頂層的基類,而其他類則是派生物,它實現了一系列方法,對自身并沒有額數的作用,但是對其他對象卻非常有效。

這句話可以這么理解,在LINUX中,是用C語言實現的,沒有對象的概念,但是kobject被包含在各個結構中,就如同面向對象的的基類,根據它描述的父子兄弟關系,把各個結構實例聯系起來,想成目錄結構。現在回過頭去看看總線,設備,驅動的結構定義中其實都有這個KOBJECT的影子,只是在前面我們分析的時候沒有把列出來。

kobject的初始化:
1首先使用memest函數將整個kobject清零。
2調用kobject_init()函數。設置結構內部的一些成員。void kobject_init(struct kobject*kobj);kobject_init設置kobject的引用計數為 1。
3設置kobject的名字,這是sysfs入口中使用的名字。int kobject_set_name(struct kobject*kobj, const char *format, ...)

kobject的引用計數:
kobject 的其中一個關鍵函數是作為一個引用計數器, 給一個它被嵌入的對象. 只要對這個對象的引用存在, 這個對象(和支持它的代碼)必須繼續存在.
struct kobject *kobject_get(struct kobject *kobj);
void kobject_put(struct kobject *kobj);

釋放函數和 kobject 類型:
通知由 kobject 的一個釋放函數來完成. 常常地, 這個方法有一個形式如下:
void my_object_release(struct kobject *kobj)
{
?? ?structmy_object *mine = container_of(kobj, struct my_object, kobj);
???kfree(mine);
}
有一點需要注意:每一個kobject都必須有一個release方法,并且kobject在該方法被調用前必須保持不變。
而需要在意一點,release函數并沒有包含在kobject自身內,而是與包含kobject的結構類型相關聯的kobj_type數據結構負責對該類型進行跟蹤。

注意結構中的ktype,以及SYSFS_OPS,見下邊SYS相關的分析。
struct kobj_type
{
?? ?void(*release)(struct kobject *);//保存kobject類型的release函數
?? ?structsysfs_ops *sysfs_ops;
?? ?structattribute ** default_attrs;
}


kobject層次結構、kset

內核用kobject結構將各個對象連接起來組成一個分層的結構體系,從而與模型化的子系統相匹配。有兩種獨立的機制用于連接:parent指針和kset
在kobject結構的parent成員中,保存了另外一個kobject結構的指針,這個結構表示了分層結構中上一層的節點,而parent最重要的用途是在sysfs分層結構中定位對象。

kset是嵌入相同類型結構的kobject集合,但是不同之處在于,kobject在乎的是對象的類型,而kset關心的是對象的集合與聚合。需要注意的是,kset總是在sysfs中出現,一旦設置了kset并把它添加到系統中,將在sysfs中創建一個目錄。kobject不必在sysfs中表示,但是kset中的每一個kobject成員都將在sysfs中得到表述。

創建一個對象時,要把一個kobject添加到kset中,要先將kobject的kset成員指向目的的kset,調用extern intkobject_register(struct kobject *kobj);
這個函數僅僅是一個 kobject_init 和 kobject_add 的結合.

struct kset {
?struct list_head list;
?spinlock_t list_lock;
?struct kobject kobj;
?const struct kset_uevent_ops *uevent_ops;
};
對于初始化和設置, kset有一個接口非常類似于 kobjects.
void kset_init(struct kset *kset);
int kset_add(struct kset *kset);
int kset_register(struct kset *kset);
void kset_unregister(struct kset *kset);

為管理 ksets 的引用計數, 情況大概相同:
struct kset *kset_get(struct kset *kset);
void kset_put(struct kset *kset);

一個 kset 還有一個名子, 存儲于嵌入的 kobject. 因此, 如果你有一個 kset 稱為 my_set,你將設置它的名子用:
kobject_set_name(&my_set->kobj, "Thename");

ksets 還有一個指針( 在 ktye 成員 )指向 kobject_type 結構來描述它包含的 kobject.這個類型優先于在 kobject 自身中的 ktype 成員. 結果, 在典型的應用中, 在 struct kobject 中的ktype 成員被留為 NULL, 因為 kset 中的相同成員是實際使用的那個.

低層sysfs操作
(什么是SYSFS?? 我們就把它先看做設備文件系統,用來管理系統的各種設備,驅動,總線,類的文件系統)。
kobject隱藏在sysfs文件系統之后的機制,對于sysfs每個目錄,內核中都會存在一個對應的kobject。每一個kobject都輸出一個或者多個屬性。在sysfs目錄中表現為文件,其中的內容由內核生成。在<linux/sysfs.h>中包含了sysfs工作代碼。

使kobject在sysfs出現僅僅是調用kobject_add的事情.kobjects的sysfs入口一直為目錄,因此一個對kobject_add的調用導致在sysfs中創建一個目錄.常常地, 這個目錄包含一個或多個屬性;
分配給 kobject 的名子( 用 kobject_set_name ) 是給 sysfs 目錄使用的名子. 因此, 出現在sysfs 層次的相同部分的 kobjects 必須有獨特的名子. 分配給 kobjects 的名子也應當是合理的文件名子:它們不能包含斜線字符, 并且空白的使用強烈不推薦.
sysfs 入口位于對應 kobject 的 parent 指針的目錄中. 如果 parent 是 NULL 當kobject_add 被調用時, 它被設置為嵌在新 kobject 的 kset 中的 kobject;

當被創建時, 每個kobject被給定一套缺省屬性. 這些屬性通過kobj_type結構來指定.

default_attr 成員列舉了對每個這樣類型的 kobject 被創建的屬性, 并且 sysfs_ops提供方法來實現這些屬性.

struct attribute {
?char *name;
?struct module *owner;
?mode_t mode;
};

在這個結構中, name 是屬性的名子( 如同它出現在 kobject 的 sysfs 目錄中), owner是一個指向模塊的指針(如果有一個), 模塊負責這個屬性的實現, 并且 mode 是應用到這個屬性的保護位. mode 常常是S_IRUGO 對于只讀屬性; 如果這個屬性是可寫的, 你可以扔出 S_IWUSR 來只給 root 寫權限( modes 的宏定義在<linux/stat.h> 中). default_attrs列表中的最后一個入口必須用 0 填充.

實現這些屬性則需要kobj_type->sysfs_ops成員, 它指向一個結構, 定義為:

struct sysfs_ops {
?ssize_t (*show)(struct kobject *kobj, structattribute *attr, char *buffer);
?ssize_t (*store)(struct kobject *kobj, structattribute *attr, const char *buffer, size_t size);
};

無論何時一個屬性從用戶空間讀取, show 方法被用一個指向 kobject 的指針和適當的屬性結構來調用.這個方法應當將給定屬性值編碼進緩沖, 要確定沒有覆蓋它( 它是 PAGE_SIZE 字節), 并且返回實際的被返回數據的長度.sysfs 的慣例表明每個屬性應當包含一個單個的, 人可讀的值; 如果你有許多消息返回, 你可要考慮將它分為多個屬性.

同樣的 show 方法用在所有的和給定 kobject 關聯的屬性. 傳遞到函數的 attr 指針可用來決定需要哪個屬性. 一些show 方法包含對屬性名子的一系列測試. 其他的實現將屬性結構嵌入另一個結構, 來包含需要返回屬性值的信息; 在這種情況下,container_of 可能用在 show 方法中來獲得一個指向嵌入結構的指針.

store 方法類似; 它應當將存在緩沖的數據編碼( size 包含數據的長度, 這不能超過 PAGE_SIZE ),存儲和以任何有意義的的方式響應新數據, 并且返回實際編碼的字節數. store 方法只在屬性的許可允許寫才被調用. 當編寫一個store 方法時, 不要忘記你在接收來自用戶空間的任意信息; 你應當在采取對應動作之前非常小心地驗證它. 如果到數據不匹配期望,返回一個負的錯誤值, 而不是可能地做一些不想要的和無法恢復的事情. 如果你的設備輸出一個自銷毀的屬性,你應當要求一個特定的字符串寫到那里來引發這個功能; 一個偶然的, 隨機寫應當只產生一個錯誤.

非默認屬性:

多數情況下,kobject類型的default_attrs成員描述了kobject擁有的所有屬性。但是我們還可以根據需要對kobject捏的樹型進行添加和刪除,希望在kobject的sysfs目錄中添加新的屬性,只需要填寫一個個attribute結構,并調用下面的函數:
int sysfs_create_file(struct kobject *kobj, struct attribute*attr);
將用attribute中的名字創建文件,并返回0,否則返回一個錯誤編碼。而下面的函數則是刪除屬性:
int sysfs_remove_file(struct kobject *kobj, struct attribute*attr);

符號鏈接:

sysfs 文件系統有通常的樹結構, 反映它代表的 kobjects 的層次組織.sysfs 子樹 (/sys/devices)代表所有的系統已知的設備, 而其他的子樹( 在 /sys/bus 之下)表示設備驅動.這些樹,不代表驅動和它們所管理的設備間的關系.展示這些附加關系需要額外的指針,指針在sysfs中通過符號連接實現.

創建符號連接:
int sysfs_create_link(struct kobject *kobj, struct kobject *target,char *name);
這個函數創建一個連接(稱為name)指向目標的sysfs入口作為一個kobj的屬性.它是一個相對連接,因此它不管sysfs在任何特殊的系統中安裝在哪里都可用.
去除符號連接可使用:
void sysfs_remove_link(struct kobject *kobj, char *name);

?

二進制屬性:

struct bin_attribute {
?struct attribute?attr;
?size_t???size;
?void???*private;
?ssize_t (*read)(struct file *, struct kobject *,struct bin_attribute *,
???char *,loff_t, size_t);
?ssize_t (*write)(struct file *,struct kobject *,struct bin_attribute *,
??? char *,loff_t, size_t);
?int (*mmap)(struct file *, struct kobject *,struct bin_attribute *attr,
?????struct vm_area_struct *vma);
};

?

int  sysfs_create_bin_file(struct kobject *kobj,struct bin_attribute *attr); 
我們可以顯示的定義一個KOBJ的二進制屬性,這三個函數指針對應月SYS_***,記住這點就夠了。用的地方不是特別多,在我們PROBE一個設備的時候,可以針對該驅動的KOBJ設置二進制屬性,然后就可以在用戶空間通過VFS來訪問這個設備了。以后降到具體的驅動的例子再詳細探討。
 

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/457881.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/457881.shtml
英文地址,請注明出處:http://en.pswp.cn/news/457881.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

angular自定義指令詳解

指令&#xff08;directive&#xff09;是angular里面最核心也是最難懂的東西&#xff0c;在慕課網看了下大漠窮秋老濕的視頻&#xff0c;自己百度半天做了一些小test&#xff0c;總算把一切都搞明白了。 先列出學習來源&#xff1a; 指令中controller和link的區別&#xff1a;…

delphi7aes加密解密與java互轉_跨語言(java vs python vs nodejs)的RSA加解密問題探討

多次被問到這樣的問題&#xff1a;java服務端的rsa加密操作已經完成&#xff0c;返回一個16進制的字符串給python平臺&#xff0c;但是在python進行私鑰解密的時候發現行不通。。。。前端python加密&#xff0c;后端用java解密&#xff0c;解不出來還有諸如nodejs從理論上來說&…

類的定義、成員定義修飾符

類的定義 修飾符含義1無或internal 只能在當前項目中訪問類&#xff0c;其它項目引用后也無法訪問2public 可以任何地方訪問類3abstract 不能實例化&#xff0c;只能供繼承之用4sealed 不能供派生之用&#xff0c;只能實例化5internal abstract136public abstract237intern…

設備模型3

在上一篇分析中&#xff0c;多次提到了SYSFS&#xff0c;這是個什么東西&#xff1f;這可是個很大的TOPIC&#xff0c;關于它的講述可以寫本書&#xff0c;但是我們暫時的目標不是要完全啃投它所有的東西&#xff0c;沒時間&#xff0c;沒精力&#xff0c;我們只要掌握我們需要…

浪潮之巔讀后感

這幾天看到一本非常好的書《浪潮之巔》。浪潮&#xff0c;指的是時代的大潮。而浪潮之巔&#xff0c;顧名思義就是指站在時代潮流的巔峰&#xff0c;引領時代潮流&#xff0c;扛起發展大旗。而本書就是在介紹各大處在浪潮之巔的IT公司的歷史及發展。 書中有句話說得好&#xff…

利用dft的定義計算dft的matlab程序_CP2K教程系列之靜態計算(Pymatflow篇)

本系列CP2K教程是《CP2K菜根譚》的升級版&#xff0c;在舊版基礎上添加了如何結合Pymatflow工具簡化計算流程的內容。話不多說&#xff0c;本文將為您帶來CP2K系列教程中的靜態計算部分。靜態計算設置靜態計算是大多數人接觸第一性原理計算后第一次運行的計算類型。很多其它類型…

機器學習:最大似然估計與最大后驗概率估計

在機器學習領域&#xff0c;概率估計是經常用到的一種模型&#xff0c;而概率估計中&#xff0c;我們經常會看到兩種估計模型&#xff0c;一種是最大似然估計&#xff0c;即 Maximum likelihood&#xff0c; 另外一種就是最大后驗概率估計&#xff0c;即 Maximum posterior &am…

ubuntu14.04安裝git

參考教程&#xff1a;git介紹&#xff1a;安裝&#xff0c;使用&#xff0c;創建分支 安裝的方法有兩種&#xff0c;一種直接是通過ubuntu的APT安裝&#xff0c;這種方法最簡便&#xff0c;缺點是版本可能不是最新的。所有還有另一種方法是下載源碼進行安裝&#xff0c;這種能…

微軟是如何戲耍程序員們的

2019獨角獸企業重金招聘Python工程師標準>>> 別用微軟的東西。商業目的性太強&#xff0c;千萬別被微軟牽著鼻子走&#xff0c;血淋淋的教訓。微軟推出的垃圾多了去了。它什么都想做&#xff0c;很多都沒做好&#xff1a; MFC&#xff1a;Win31時代出生&#xff0c;…

3d立體相冊特效html網頁代碼_新聞類網頁正文通用抽取器

項目起源開發這個項目&#xff0c;源自于我在知網發現了一篇關于自動化抽取新聞類網站正文的算法論文——《基于文本及符號密度的網頁正文提取方法》這篇論文中描述的算法看起來簡潔清晰&#xff0c;并且符合邏輯。但由于論文中只講了算法原理&#xff0c;并沒有具體的語言實現…

ubuntu14.04安裝 R16 Tina Linux SDK

第一步&#xff1a;由于是14.04系統所以這樣$sudo -i $cd /etc/apt/sources.list.d $echo "deb http://old-releases.ubuntu.com/ubuntu/ raring main restricted universe multiverse" > ia32-libs-raring.list $apt-get update $apt-get install ia32-libs $r…

分答

用戶在分答上可以自我介紹或描述擅長的領域&#xff0c;設置付費問答的價格&#xff0c;其他用戶感興趣就可以付費向其提問。分答的收入分配機制增加了信息的價值&#xff0c;分答中信息接收者被區分成了兩種身份。首先提問的人是一種付費懸賞模式&#xff0c;當回答完畢內容沉…

字節數組轉換為圖片_每日一課 | Python 3 TypeError:無法將“字節”對象隱式轉換為str...

將Python 2套接字示例轉換為Python 3whois.py import sysimport sockets socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.connect(("whois.arin.net", 43))s.send((sys.argv[1] "\r\n").encode())response ""while True: data s.re…

php版redis插件,SSDB數據庫,增強型的Redis管理api實例

php版redis插件,SSDB數據庫,增強型的Redis管理api實例 SSDB是一套基于LevelDB存儲引擎的非關系型數據庫&#xff08;NOSQL&#xff09;&#xff0c;可用于取代Redis&#xff0c;更適合海量數據的存儲。另外&#xff0c;rocksdb是FB在LevelDB的二次開發版本&#xff0c;因此也存…

加速度計和陀螺儀數據融合

本帖翻譯自 IMU&#xff08;加速度計和陀螺儀設備&#xff09;在嵌入式應用中使用的指南。這篇文章主要介紹加速度計和陀螺儀的數學模型和基本算法&#xff0c;以及如何融合這兩者&#xff0c;側重算法、思想的討論介紹本指南旨在向興趣者介紹慣性MEMS&#xff08;微機電系統&a…

循環嵌套練習題

//BOSS://讓用戶輸入一個奇數&#xff0c;打印菱形&#xff0c;最長的行內容個數為用戶輸入的個數&#xff0c;并且由英文字母拼接而成//比如用戶輸入了7// A// ABA// ABCBA// ABCDCBA// ABCBA// ABA// A//1、接收并判斷用戶輸入的是不是數字 try{#region 解法一…

python leetcode_leetcode 介紹和 python 數據結構與算法學習資料

for &#xff08;剛入門的編程&#xff09;的高中 or 大學生leetcode 介紹leetcode 可以說是 cs 最核心的一門“課程”了&#xff0c;雖然不是大學開設的&#xff0c;但基本上每一個現代的高水平的程序員都修過這門“課程”&#xff08;或者類似的課程&#xff0c;比如數據結構…

平衡小車卡爾曼濾波算法

最近研究STM32的自平衡小車&#xff0c;發現有兩座必過的大山&#xff0c;一為卡爾曼濾波&#xff0c;二為PID算法。 網上看了很多關于卡爾曼濾波的代碼&#xff0c;感覺寫得真不咋地。一怒之下&#xff0c;自己重寫&#xff0c;不廢話&#xff0c;貼代碼 [pre lang"C&quo…

IOS 為UILabel添加長按復制功能

IOS 為UILabel添加長按復制功能 在iOS中下面三個控件&#xff0c;自身就有復制-粘貼的功能&#xff1a; 1、UITextView 2、UITextField 3、UIWebView UIKit framework提供了幾個類和協議方便我們在自己的應用程序中實現剪貼板的功能。 1、UIPasteboard&#xff1a;我們可以向其…

navicat 的查詢功能

navicat的查詢的位置在&#xff1a; 在編輯器界面寫代碼&#xff0c;代碼完成后點左上角的運行。 代碼&#xff1a; create&#xff08;創建&#xff09; table&#xff08;一個表&#xff09; <xxx>尖括號內的內容必填——我要創建并查詢一個名叫做xxx的表 &#xff08…