sysfs文件系統(tǒng)
sysfs,全稱為System Filesystem,是一個由Linux內(nèi)核實現(xiàn)的虛擬文件系統(tǒng)。它扮演著一個橋梁的角色,將內(nèi)核中的設備和驅動程序信息以文件的形式呈現(xiàn)給用戶空間。與/proc文件系統(tǒng)相似,sysfs專注于展示設備和驅動程序的細節(jié),而/proc則主要反映進程信息。
在sysfs中,信息被組織成層次化的文件系統(tǒng)結構。每個設備或內(nèi)核對象在文件系統(tǒng)中都有其對應的表示,通常是以文件或目錄的形式存在。這些文件不僅存儲了設備的屬性和狀態(tài)信息,而且很多文件還允許用戶通過讀寫操作來對設備進行配置或控制。
sysfs默認掛載在文件系統(tǒng)的/sys路徑下。通過這個虛擬文件系統(tǒng),用戶空間的應用程序能夠以一種直觀和動態(tài)的方式訪問和管理系統(tǒng)設備,無需進行復雜的內(nèi)核空間交互。這種設計提供了一種高效且用戶友好的接口,使得設備管理變得更加簡單和靈活。
kernel Object
在Linux內(nèi)核架構中,kobject扮演著一個核心角色,它是一個用于抽象化內(nèi)核對象的框架。kobject不僅構成了內(nèi)核中各種子系統(tǒng)的基礎構件,而且能夠代表設備、驅動程序、總線等多樣化的內(nèi)核實體。
kobject架構提供了一種靈活且統(tǒng)一的模型,用以維護和管理內(nèi)核對象。每個Kobject實例都擁有一個獨一無二的標識符和指向其上層Kobject的鏈接,這樣的設計允許它們形成一個有序的層級網(wǎng)絡。更進一步,Kobject可以附加多種屬性,這些屬性反映了對象的特征或狀態(tài),并且可以通過sysfs這一虛擬文件系統(tǒng)對外公布,使得用戶空間程序能夠訪問和操作這些屬性。
Sysfs作為Kobject信息呈現(xiàn)的媒介,將內(nèi)核內(nèi)部的設備和驅動程序等對象的狀態(tài)和信息以文件的形式展現(xiàn)給用戶空間。每當內(nèi)核中新增設備或驅動程序時,相應的Kobject實例也會被動態(tài)創(chuàng)建,并通過Sysfs將這些信息映射到用戶空間可訪問的路徑下。
在Linux內(nèi)核的源碼樹中,struct kobject這一數(shù)據(jù)結構在"linux/kobject.h"頭文件里定義。它經(jīng)常作為其他結構體的成員出現(xiàn),使得這些結構體所代表的內(nèi)核對象能夠整合進Kobject的管理體系中。通過這種方式,內(nèi)核開發(fā)者可以輕松地為各種內(nèi)核對象實現(xiàn)統(tǒng)一的管理和訪問接口。
structkobject{
constchar*name;
structlist_headentry;
structkobject*parent;
structkset*kset;
structkobj_type*ktype;
structkernfs_node*sd;/*sysfsdirectoryentry*/
structkrefkref;
...
};
其中:- kref:提供kobject的引用技術。- ktype:kobject關聯(lián)的類型。- kset:指向同一類kobject集合的指針。- sd:當前kobject在/sys下的目錄條目。
sysfs使用方式
Linux內(nèi)核中使用sysfs的步驟比較簡單:(1)在sys路徑下創(chuàng)建目錄;(2)創(chuàng)建sysfs文件。下面將詳細展開這兩步涉及的內(nèi)核API。
在sys下創(chuàng)建目錄
structkobject*kobject_create_and_add(constchar*name,structkobject*parent);
Linux內(nèi)核預定義了幾個常用的parent參數(shù):- kernel_kobj:在/sys/kernel下創(chuàng)建目錄;- firmware_kobj:在/sys/firmware下創(chuàng)建目錄;- fs_kobj:在/sys/fs下創(chuàng)建目錄。- 如果parent取值為NULL,則在/sys下面創(chuàng)建目錄。
相應地,如果需要刪除對應的sysfs目錄,可以用:
voidkobject_put(structkobject*kobj);
創(chuàng)建sysfs文件
sysfs文件可以通過sysfs屬性來創(chuàng)建,它定義在頭文件"sysfs.h"中:
structkobj_attribute{ structattributeattr; ssize_t(*show)(structkobject*kobj,structkobj_attribute*attr,char*buf); ssize_t(*store)(structkobject*kobj,structkobj_attribute*attr,constchar*buf,size_tcount); };
attr表示將要創(chuàng)建的文件(屬性),而show和store分別表示對應的sysfs文件在讀和寫操作時的回調(diào)函數(shù)。
struct kobj_attribute可以通過__ATTR宏來創(chuàng)建:
__ATTR(name,permission,show_ptr,store_ptr);
準備好attr之后,可以通過sysfs_create_file來創(chuàng)建出sysfs文件:
intsysfs_create_file(structkobject*kobj,conststructattribute*attr);
如果需要刪除對應的sysfs文件,可以用:
voidsysfs_remove_file(structkobject*kobj,conststructattribute*attr);
sysfs創(chuàng)建設備節(jié)點
前面描述了如何創(chuàng)建一個基本的sysfs,接下載描述的是如何創(chuàng)建設備節(jié)點的sysfs。
實際創(chuàng)建設備節(jié)點的sysf跟基本的sysfs是一樣的,只是結構體換了一個名字。它使用DEVICE_ATTR宏,可以定義一個struct device_attribute設備屬性,使用sysfs_create_file便可以在設備目錄下創(chuàng)建具有show和store方法的節(jié)點。
DEVICE_ATTR宏定義
DEVICE_ATTR宏定義如下:
#defineDEVICE_ATTR(_name,_mode,_show,_store) structdevice_attributedev_attr_##_name=__ATTR(_name,_mode,_show,_store)
__ATTR宏定義,宏定義在include/linux/sysfs.h文件中,如下:
#define__ATTR(_name,_mode,_show,_store){
.attr={.name=__stringify(_name),
.mode=VERIFY_OCTAL_PERMISSIONS(_mode)},
.show=_show,
.store=_store,
}
struct device_attribute結構體,該結構體的定義在include /linux/device.h,其定義如下:
structdevice_attribute{
structattributeattr;
ssize_t(*show)(structdevice*dev,structdevice_attribute*attr,
char*buf);
ssize_t(*store)(structdevice*dev,structdevice_attribute*attr,
constchar*buf,size_tcount);
};
struct attribute結構體, 該結構體的定義在include /linux/device.h,其定義如下:
structattribute{
constchar*name;
umode_tmode;
#ifdefCONFIG_DEBUG_LOCK_ALLOC
boolignore_lockdep:1;
structlock_class_key*key;
structlock_class_keyskey;
#endif
};
DEVICE_ATTR宏定義等價說明
我們頂一個文件的范式如下
DEVICE_ATTR(_name,_mode,_show,_store)
等價于:
structdevice_attributedev_attr_##_name={
.attr={.name=__stringify(_name),
.mode=VERIFY_OCTAL_PERMISSIONS(_mode)},
.show=_show,
.store=_store,
}
show函數(shù)的詳細描述:
ssize_t(*show)(structdevice*dev,structdevice_attribute*attr,char*buf);
參數(shù)說明:
入?yún)uf是需要我們填充的string即我們cat屬性節(jié)點時要顯示的內(nèi)容;-函數(shù)的返回值是我們填充buf的長度,且長度應當小于一個頁面的大小(4096字節(jié));
其他參數(shù)一般不用關心。
實例說明,當我們使用cat命令的時候,將調(diào)用該函數(shù)
staticssize_tshow_youyeetoo_device(structdevice*dev,
structdevice_attribute*attr,char*buf)
{
returnsprintf(buf,"%sn",mybuf);
}
store函數(shù)的詳細描述:
ssize_t(*store)(structdevice*dev,structdevice_attribute*attr,constchar*buf,size_tcount);
參數(shù)說明:
入?yún)uf是用戶傳入的字符串,即echo到屬性節(jié)點的內(nèi)容;
入?yún)ount是buf中字符串的長度。
函數(shù)的返回值通常返回count即可。
其他參數(shù)一般不用關心。
實例說明,當我們使用echo命令的時候,將調(diào)用該函數(shù):
staticssize_tstore_youyeetoo_device(structdevice*dev,
structdevice_attribute*attr,
constchar*buf,size_tcount)
{
sprintf(mybuf,"%s",buf);
returncount;
}
mode的權限定義,在kernel/include/uapi/linux/stat.h中:
#defineS_IRWXU00700//用戶可讀寫和執(zhí)行 #defineS_IRUSR00400//用戶可讀 #defineS_IWUSR00200//用戶可寫 #defineS_IXUSR00100//用戶可執(zhí)行 #defineS_IRWXG00070//用戶組可讀寫和執(zhí)行 #defineS_IRGRP00040//用戶組可讀 #defineS_IWGRP00020//用戶組可寫 #defineS_IXGRP00010//用戶組可執(zhí)行 #defineS_IRWXO00007//其他可讀寫和執(zhí)行 #defineS_IROTH00004//其他可讀 #defineS_IWOTH00002//其他可寫 #defineS_IXOTH00001//其他可執(zhí)行
至此,我們已經(jīng)定義好了.show和.store函數(shù),那么就可以使用DEVICE_ATTR了。
staticDEVICE_ATTR(youyeetoo_device,S_IWUSR|S_IRUSR,show_youyeetoo_device,store_youyeetoo_device);
device attribute添加到sysfs
上面描述的是sysfs的讀寫接口的定義方式,他還需要注冊到sysfs中。才會在對應驅動中顯示我們的文件,其中:
注冊函數(shù):sysfs_create_file();
注銷函數(shù):sysfs_remove_file();
樣例代碼代碼:
注冊樣例:
sysfs_create_file(&(youyeetoo_dev->kobj),&dev_attr_youyeetoo.attr);
注銷樣例:
sysfs_remove_file(&(youyeetoo_dev->kobj),&dev_attr_youyeetoo.attr);
sysfs樣例測試
完整的測試代碼,在sysfs的驅動節(jié)點里面生成一個youyeetoo文件,文件支持讀寫功能。
#include #include #include #include #include staticintmajor; staticstructclass*youyeetoo_class; structdevice*youyeetoo_dev; staticcharyouyeetoo_buff[100]="youyeetoo"; staticssize_tshow_youyeetoo_device(structdevice*dev, structdevice_attribute*attr,char*buf) { returnsprintf(buf,"%sn",youyeetoo_buff); } staticssize_tstore_youyeetoo_device(structdevice*dev, structdevice_attribute*attr, constchar*buf,size_tcount) { sprintf(youyeetoo_buff,"%s",buf); returncount; } staticDEVICE_ATTR(youyeetoo,S_IWUSR|S_IRUSR,show_youyeetoo_device,store_youyeetoo_device); structfile_operationsyouyeetoo_ops={ .owner=THIS_MODULE, }; staticintyouyeetoo_init(void) { major=register_chrdev(0,"youyeetoo",&youyeetoo_ops); youyeetoo_class=class_create(THIS_MODULE,"youyeetoo"); youyeetoo_dev=device_create(youyeetoo_class,0,MKDEV(major,0),NULL,"youyeetoo"); if(sysfs_create_file(&(youyeetoo_dev->kobj),&dev_attr_youyeetoo.attr)) {//在mytest_device設備目錄下創(chuàng)建一個sys_device_file屬性文件 return-1; } return0; } staticvoidyouyeetoo_exit(void) { device_destroy(youyeetoo_class,MKDEV(major,0)); class_destroy(youyeetoo_class); unregister_chrdev(major,"youyeetoo"); sysfs_remove_file(&(youyeetoo_dev->kobj),&dev_attr_youyeetoo.attr); } module_init(youyeetoo_init); module_exit(youyeetoo_exit); MODULE_AUTHOR("youyeetoo"); MODULE_LICENSE("GPL");
將上面驅動編譯燒錄之后,就可以sysfs下看到我們創(chuàng)建的文件:

測試我們創(chuàng)建的sysfs


審核編輯 黃宇
-
Linux
+關注
關注
88文章
11758瀏覽量
219006 -
Sysfs
+關注
關注
0文章
15瀏覽量
6433
發(fā)布評論請先 登錄
飛凌嵌入式ElfBoard ELF 1板卡-應用編程示例控制LED燈之sysfs文件系統(tǒng)
【AWorks試用體驗】使用sysfs文件系統(tǒng) 控制IED(1) Shell 點亮LED
Linux文件系統(tǒng)課程
Linux根文件系統(tǒng)簡介
玩轉Linux,先把文件系統(tǒng)搞懂
《Linux設備驅動開發(fā)詳解》第5章、Linux文件系統(tǒng)與設備文件系統(tǒng)
Linux 內(nèi)核/sys 文件系統(tǒng)介紹
學會使用Linux 文件系統(tǒng):procfs, sysfs, debugfs
可以了解的Linux 文件系統(tǒng)結構
Linux最新UBI文件系統(tǒng)介紹
Linux設備模型:sysfs
Linux文件系統(tǒng)解析
適用于Linux的最佳通用文件系統(tǒng) Linux文件系統(tǒng)的安裝
Linux的文件系統(tǒng)特點
linux--sysfs文件系統(tǒng)
評論