做再生料的網(wǎng)站小紅書如何引流推廣
文章目錄
- 前言
- 一、Sysfs
- 1.1 Sysfs的引入
- 1.2 Sysfs的目錄結(jié)構(gòu)
- 1.2 Sysfs的目錄詳解
- 1.2.1 devices
- 1.2.2 bus
- 1.2.3 class
- 1.2.4 devices、bus、class目錄之間的關(guān)系
- 1.2.5 其他子目錄
- 二、Sysfs使用
- 2.1 核心數(shù)據(jù)結(jié)構(gòu)
- 2.2 相關(guān)函數(shù)
- 2.2.1 kobject_create_and_add
- 2.2.2 kobject_put()
- 2.2.3 kobject_get()
- 2.2.4 sysfs_create_file
- 2.3 設(shè)計(jì)思路
前言
??前面章節(jié)驅(qū)動學(xué)習(xí)中,我們測試驅(qū)動時經(jīng)常使用/sys目錄下文件,我們本章就簡單介紹下Sysfs文件系統(tǒng)。
一、Sysfs
1.1 Sysfs的引入
??sysfs則是Linux內(nèi)核中的一種特殊虛擬文件系統(tǒng),它用來向用戶空間提供內(nèi)核設(shè)備和驅(qū)動程序的信息。因此,sysfs是一種具體的文件系統(tǒng)實(shí)現(xiàn),它利用了VFS提供的抽象接口來展示內(nèi)核數(shù)據(jù)。Sysfs在Linux內(nèi)核2.6版本中引入,旨在替代和擴(kuò)展早期的proc文件系統(tǒng)。它提供了一種統(tǒng)一的接口,用于查看和操作設(shè)備、驅(qū)動程序、文件系統(tǒng)等內(nèi)核對象。Sysfs采用層次化的目錄結(jié)構(gòu),反映了內(nèi)核對象之間的關(guān)系,目錄和文件分別表示內(nèi)核對象及其屬性。
??內(nèi)核對象(如設(shè)備、驅(qū)動程序等)在sysfs中被表示為目錄,目錄下的文件表示對象的屬性。這些文件通常是只讀的,但有些也可以通過寫操作進(jìn)行配置。
??通過sysfs,用戶可以統(tǒng)一地訪問不同類型的內(nèi)核信息,而不需要關(guān)心底層實(shí)現(xiàn)細(xì)節(jié)。Sysfs內(nèi)容會隨著系統(tǒng)硬件配置的變化動態(tài)更新。例如,插拔設(shè)備會導(dǎo)致相應(yīng)的sysfs目錄和文件創(chuàng)建或刪除。
1.2 Sysfs的目錄結(jié)構(gòu)
??Sysfs文件系統(tǒng)是一種虛擬文件系統(tǒng),也就是文件系統(tǒng)中文件不對應(yīng)硬盤上任何文件,存在于內(nèi)存中,其通常掛載在/sys目錄下,主要目錄包括:
/sys/devices:表示系統(tǒng)中的物理設(shè)備,每個子目錄對應(yīng)一個設(shè)備。
/sys/class:表示系統(tǒng)中的設(shè)備類別(如網(wǎng)絡(luò)設(shè)備、塊設(shè)備等),子目錄按類別分類。
/sys/block:表示塊設(shè)備(如硬盤、USB存儲設(shè)備等)。
/sys/bus:表示系統(tǒng)總線類型(如PCI、USB等),每個子目錄對應(yīng)一個總線。
/sys/kernel:表示內(nèi)核參數(shù)和信息,如調(diào)度器參數(shù)、內(nèi)核模塊等。
/sys/module:表示加載的內(nèi)核模塊,每個子目錄對應(yīng)一個模塊,包含模塊參數(shù)和狀態(tài)信息。
??Sysfs是通過內(nèi)核中的對象模型(kobject)實(shí)現(xiàn)的。每個kobject都可以在sysfs中創(chuàng)建一個對應(yīng)的目錄,kobject的屬性(kobj_attribute)則映射為sysfs中的文件。通過定義和注冊kobject和kobj_attribute,內(nèi)核模塊可以在sysfs中創(chuàng)建自己的條目。這些目錄是在子系統(tǒng)注冊kobject核心的系統(tǒng)啟動時刻產(chǎn)生的, 當(dāng)它們被初始化以后, 它們開始搜尋在各自的目錄內(nèi)注冊了的對象。 一個kobject對應(yīng)一個目錄,包含的對象屬性對應(yīng)一個文件,文件只支持 目錄、 普通文件 (文本或二進(jìn)制文件)和 符號鏈接文件三種類型。
1.2 Sysfs的目錄詳解
1.2.1 devices
??devices目錄反映系統(tǒng)中所有物理設(shè)備及其層次結(jié)構(gòu),設(shè)備按照硬件拓?fù)浣Y(jié)構(gòu)組織,表示設(shè)備的物理連接關(guān)系。/sys/devices是內(nèi)核對系統(tǒng)中所有設(shè)備的分層次表達(dá)模型, 也是/sys文件系統(tǒng)管理設(shè)備的最重要的目錄結(jié)構(gòu)。其目錄結(jié)構(gòu)如下:
- 系統(tǒng)設(shè)備:如 CPU、系統(tǒng)內(nèi)存等。
- 總線設(shè)備:例如 PCI、USB、SCSI 等設(shè)備。
- 虛擬設(shè)備:如虛擬網(wǎng)絡(luò)設(shè)備。
1.2.2 bus
??bus目錄包含系統(tǒng)中所有已注冊總線類型的子目錄,每個子目錄表示一種總線類型,例如 PCI、USB、I2C 等。這里是設(shè)備按照總線類型分層放置的目錄結(jié)構(gòu), 每個子目錄(總線類型)下包含兩個子目錄——devices和drivers文件夾;其中devices下是該總線類型下的所有設(shè)備, 而這些設(shè)備都是符號鏈接,它們分別指向真正的設(shè)備(/sys/devices/下);如下圖bus下的usb總線中的device則是Devices目 錄下/pci()/dev 0:10/usb2的符號鏈接。而drivers下是所有注冊在這個總線上的驅(qū)動,每個driver子目錄下 是一些可以觀察和修改的driver參數(shù)。其目錄結(jié)構(gòu)如下:
- devices:列出所有連接到該總線的設(shè)備。
- drivers:列出與該總線相關(guān)的所有驅(qū)動程序。
- drivers_autoprobe 和 drivers_probe:用于自動或手動驅(qū)動程序綁定。
- uevent:用于觸發(fā) uevent 事件。
1.2.3 class
??class 目錄按設(shè)備類型對設(shè)備進(jìn)行分類,每個子目錄表示一種設(shè)備類型,例如網(wǎng)絡(luò)設(shè)備、塊設(shè)備、字符設(shè)備等。其目錄結(jié)構(gòu)如下:
- net:表示所有網(wǎng)絡(luò)接口。
- block:表示所有塊設(shè)備。
- tty:表示所有終端設(shè)備。
注:大家可能注意到在/sys/class目錄下也存在一個block子目錄,這是由于歷史遺留因素而導(dǎo)致的。 塊設(shè)備現(xiàn)在是已經(jīng)移到/sys/class/block, 舊的接口/sys/block為了向后兼容保留存在,現(xiàn)在該目錄下的都是鏈接文件
1.2.4 devices、bus、class目錄之間的關(guān)系
- /sys/devices 目錄表示設(shè)備的物理連接和層次結(jié)構(gòu),而 /sys/class 目錄按設(shè)備功能或類型對設(shè)備進(jìn)行邏輯分類。
- /sys/bus 目錄表示系統(tǒng)中的各種總線類型,每種總線都有一個子目錄,包含該總線上的設(shè)備(鏈接到 /sys/devices)和驅(qū)動程序信息。
- /sys/devices 中的設(shè)備可能會在 /sys/bus/<bus_type>/devices 下有一個符號鏈接,反映設(shè)備與總線的關(guān)系。/sys/class 提供了按設(shè)備類型的視圖,使用戶能夠方便地找到特定類型的設(shè)備,而無需了解設(shè)備的具體物理連接位置。
??以USB 存儲設(shè)備插入系統(tǒng)為例,以下是目錄之間關(guān)系的具體示例:
//表示 USB 存儲設(shè)備的物理連接路徑
ls /sys/devices/pci0000:00/0000:00:14.0/usb1/1-1//目錄中包含指向上述設(shè)備的符號鏈接,表示它是一個 USB 設(shè)備
ls /sys/bus/usb/devices//目錄中包含該設(shè)備的邏輯分類信息,表示它是一個塊設(shè)備
ls /sys/class/block/sda
1.2.5 其他子目錄
??在Sysfs文件系統(tǒng)中最重要的就是以上三個子目錄,其他子目錄我們簡單了解即可。
?firmware目錄
??該目錄包含具有固件對象和屬性的子目錄,關(guān)于內(nèi)核的固件加載和firmware驅(qū)動,有興趣可以自己去了解下。其目錄結(jié)構(gòu)如下:
- devicetree:描述加載設(shè)備樹信息,根節(jié)點(diǎn)對應(yīng)base目錄,每一個設(shè)備樹節(jié)點(diǎn)對應(yīng)一個目錄,每個屬性對應(yīng)一個文件
- fdt:原始dtb文件,是uboot傳給內(nèi)核的設(shè)備樹文件,可以使用hexdump -C查看
?fs目錄
??這里按照設(shè)計(jì)是用于描述系統(tǒng)中所有文件系統(tǒng),包括文件系統(tǒng)本身和按文件系統(tǒng)分類存放的已掛載點(diǎn),描述已注冊的文件系統(tǒng)視圖, 但目前只有 fuse,ext4 等少數(shù)文件系統(tǒng)支持 sysfs 接口,一些傳統(tǒng)的虛擬文件系統(tǒng)(VFS)層次控制參數(shù)仍然在sysctl(/proc/sys/fs) 接口中。
?kernel目錄
??該目錄是內(nèi)核所有可調(diào)整參數(shù)的位置,有些內(nèi)核可調(diào)整參數(shù)仍然位于sysctl(/proc/sys/kernel)接口中。
?module目錄
??該目錄有系統(tǒng)中所有模塊的信息,不論這些模塊是以內(nèi)聯(lián)(inlined)方式編譯到內(nèi)核映像文件(vmlinuz)中還是編譯為外部模塊(.ko文件), 都可能會出現(xiàn)在/sys/module目錄下。
??編譯為外部模塊(.ko文件)在加載后,會/sys/module/出現(xiàn)對應(yīng)的模塊文件夾,在這個文件夾下會出現(xiàn)一些屬性文件和屬性目錄, 表示此外部模塊的一些信息,如版本號、加載狀態(tài)、所提供的驅(qū)動程序等。
??編譯進(jìn)內(nèi)核的模塊則只在當(dāng)它有非0屬性的模塊參數(shù)時會出現(xiàn)對應(yīng)的/sys/module/, 這些模塊的可用參數(shù)會出現(xiàn)在/sys/modules/parameters/中, 如:/sys/module/printk/parameters/time 這個可讀寫參數(shù)控制著內(nèi)聯(lián)模塊printk在打印內(nèi)核消息時是否加上時間前綴。
?power目錄
??該目錄下是系統(tǒng)中電源選項(xiàng),包含電源管理子系統(tǒng)提供的統(tǒng)一接口文件。 一些屬性文件可以用于控制整個機(jī)器的電源狀態(tài),如可以向其中寫入控制命令進(jìn)行關(guān)機(jī)、重啟等操作。
二、Sysfs使用
2.1 核心數(shù)據(jù)結(jié)構(gòu)
??kobject是 Linux內(nèi)核中的一個核心數(shù)據(jù)結(jié)構(gòu),用于表示內(nèi)核中的對象并支持內(nèi)核對象的引用計(jì)數(shù)、生命周期管理和對象間關(guān)系管理。它主要用于內(nèi)核的設(shè)備模型(device model)以及 sysfs 文件系統(tǒng)的實(shí)現(xiàn)。kobject 提供了一個通用的機(jī)制來管理對象,這樣不同的子系統(tǒng)可以共享一些通用的代碼來處理對象。
struct kobject {const char *name;struct list_head entry;struct kobject *parent;struct kset *kset;struct kobj_type *ktype;struct kernfs_node *sd;struct kref 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;
};
- 關(guān)鍵成員解釋
- name:kobject 的名字,用于在 sysfs 文件系統(tǒng)中表示對象的名字。
- parent:指向父對象的指針,用于形成層次結(jié)構(gòu),表示對象之間的包含關(guān)系。
- kref:內(nèi)核引用計(jì)數(shù)機(jī)制的對象,用于確保 kobject 在引用計(jì)數(shù)為零之前不會被釋放。
- ktype:指向 kobj_type 結(jié)構(gòu)體的指針,kobj_type 定義了 kobject 的特定操作,如釋放函數(shù)、sysfs 文件操作等。
- kset:指向 kset 結(jié)構(gòu)體的指針,一個 kset 是一組相關(guān) kobject 的集合,可以用來組織和管理一組相關(guān)的對象。
- sd:指向 kernfs_node 結(jié)構(gòu)體的指針,表示 sysfs 中的目錄項(xiàng)。
- state_initialized 等標(biāo)志位:用于跟蹤對象的狀態(tài),如是否已初始化、是否已添加到 sysfs 中等。
??kobj_attribute是一個用于為kobject(內(nèi)核對象)創(chuàng)建屬性的結(jié)構(gòu)體。這些屬性可以通過sysfs文件系統(tǒng)進(jìn)行讀取或?qū)懭?#xff0c;sysfs提供了一種機(jī)制,讓內(nèi)核子系統(tǒng)、設(shè)備驅(qū)動程序和其他內(nèi)核模塊可以向用戶空間導(dǎo)出信息。kobj_attribute結(jié)構(gòu)體定義在linux/kobject.h中,包含以成員:
- struct attribute attr: 一個通用的屬性結(jié)構(gòu)體,包含屬性的名稱和權(quán)限模式。
- ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr, char *buf): 指向顯示方法的函數(shù)指針,當(dāng)讀取屬性時調(diào)用該方法。
- ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count): 指向存儲方法的函數(shù)指針,當(dāng)寫入屬性時調(diào)用該方法。
??__ATTR宏用于方便地定義struct attribute類型的結(jié)構(gòu)體成員。它通常與kobj_attribute結(jié)構(gòu)體一起使用,來定義sysfs屬性。
#define __ATTR(_name, _mode, _show, _store) { \.attr = { .name = __stringify(_name), .mode = _mode }, \.show = _show, \.store = _store, \
}
- 參數(shù)說明
- _name:屬性的名稱。
- _mode:屬性的權(quán)限模式,如0644,表示所有者可讀寫,組和其他用戶可讀。
- _show:指向顯示函數(shù)的指針,該函數(shù)在讀取屬性時被調(diào)用。
- _store:指向存儲函數(shù)的指針,該函數(shù)在寫入屬性時被調(diào)用。
2.2 相關(guān)函數(shù)
??更多的函數(shù)可以參考內(nèi)核源碼include/linux/sysfs.h文件。
2.2.1 kobject_create_and_add
//函數(shù)用于創(chuàng)建、初始化并將kobject添加到系統(tǒng)中
struct kobject *kobject_create_and_add ( const char *name, struct kobject *parent);
- 參數(shù)
- name:創(chuàng)建kobj的名字
- parent:指定父kobject,實(shí)際就是在那個目錄下創(chuàng)建一個目錄。比如為kernel_kobj,將在/sys/kernel目錄下創(chuàng)建目錄,如果為NULL,將在/sys下創(chuàng)建。
- 返回值
- 成功:指向新創(chuàng)建并添加的 kobject 結(jié)構(gòu)體的指針
- 失敗:NULL
2.2.2 kobject_put()
//用于減少kobject的引用計(jì)數(shù),當(dāng)引用計(jì)數(shù)降為零時會釋放該對象。
void kobject_put(struct kobject *kobj);
- 參數(shù):
- kobj:指向要減少引用計(jì)數(shù)的 kobject 結(jié)構(gòu)體。
2.2.3 kobject_get()
//用于增加kobject的引用計(jì)數(shù)
struct kobject *kobject_get(struct kobject *kobj);
- 參數(shù):
- kobj:指向要增加引用計(jì)數(shù)的 kobject 結(jié)構(gòu)體。
- 返回值:
- 成功:返回 kobj,或者如果 kobj 為 NULL 則返回 NULL。
2.2.4 sysfs_create_file
//創(chuàng)建一個文件
int sysfs_create_file ( struct kobject * kobj, const struct attribute * attr);
- 參數(shù):
- kobj:我們創(chuàng)建的kobject
- attr:屬性描述
- 返回值:
- 成功:0
- 錯誤:錯誤碼
2.3 設(shè)計(jì)思路
??在內(nèi)核中,創(chuàng)建和使用 kobject 通常需要以下步驟:
- 初始化并添加到 sysfs:使用 kobject_create_and_add函數(shù)創(chuàng)建kobject并添加到sysfs文件系統(tǒng)中。
- 增加引用計(jì)數(shù):使用 kobject_get() 增加引用計(jì)數(shù)。
- 減少引用計(jì)數(shù)并釋放:使用 kobject_put() 減少引用計(jì)數(shù),當(dāng)引用計(jì)數(shù)降到零時,kobject 會被釋放。
//示例
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/module.h>
#include <linux/init.h>static struct kobj_attribute foo_attribute = __ATTR(foo, 0664, foo_show, foo_store);
static struct kobject *example_kobj;static ssize_t foo_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) {return sprintf(buf, "%d\n", 123); // 顯示的示例值
}static ssize_t foo_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) {// 處理存儲的示例邏輯int val;sscanf(buf, "%d", &val);printk(KERN_INFO "新值: %d\n", val);return count;
}static int __init example_init(void) {int error;example_kobj = kobject_create_and_add("example_kobject", kernel_kobj);if (!example_kobj)return -ENOMEM;error = sysfs_create_file(example_kobj, &foo_attribute.attr);if (error) {kobject_put(example_kobj);}return error;
}static void __exit example_exit(void) {kobject_put(example_kobj);
}module_init(example_init);
module_exit(example_exit);
MODULE_LICENSE("GPL");
免責(zé)聲明:本內(nèi)容部分參考野火科技及其他相關(guān)公開資料,若有侵權(quán)或者勘誤請聯(lián)系作者。