本篇內(nèi)容主要講解“Linux內(nèi)核里的DebugFS有什么用”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“Linux內(nèi)核里的DebugFS有什么用”吧!
資源ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場景,ssl證書未來市場廣闊!成為成都創(chuàng)新互聯(lián)公司的ssl證書銷售渠道,可以享受市場價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:18980820575(備注:SSL證書合作)期待與您的合作!
DebugFS,顧名思義,是一種用于內(nèi)核調(diào)試的虛擬文件系統(tǒng),內(nèi)核開發(fā)者通過debugfs和用戶空間交換數(shù)據(jù)。類似的虛擬文件系統(tǒng)還有procfs和sysfs等,這幾種虛擬文件系統(tǒng)都并不實(shí)際存儲在硬盤上,而是Linux內(nèi)核運(yùn)行起來后才建立起來。
通常情況下,最常用的內(nèi)核調(diào)試手段是printk。但printk并不是所有情況都好用,比如打印的數(shù)據(jù)可能過多,我們真正關(guān)心的數(shù)據(jù)在大量的輸出里不是那么一目了然;或者我們在調(diào)試時可能需要修改某些內(nèi)核變量,這種情況下printk就無能為力,而如果為了修改某個值重新編譯內(nèi)核或者驅(qū)動又過于低效,此時就需要一個臨時的文件系統(tǒng)可以把我們需要關(guān)心的數(shù)據(jù)映射到用戶空間。在過去,procfs可以實(shí)現(xiàn)這個目的,到了2.6時代,新引入的sysfs也同樣可以實(shí)現(xiàn),但不論是procfs或是sysfs,用它們來實(shí)現(xiàn)某些debug的需求,似乎偏離了它們創(chuàng)建的本意。比如procfs,其目的是反映進(jìn)程的狀態(tài)信息;而sysfs主要用于Linux設(shè)備模型。不論是procfs或是sysfs的接口應(yīng)該保持相對穩(wěn)定,因?yàn)橛脩魬B(tài)程序很可能會依賴它們。當(dāng)然,如果我們只是臨時借用procfs或者sysfs來作debug之用,在代碼發(fā)布之前將相關(guān)調(diào)試代碼刪除也無不可。但如果相關(guān)的調(diào)試借口要在相當(dāng)長的一段時間內(nèi)存在于內(nèi)核之中,就不太適合放在procfs和sysfs里了。故此,debugfs應(yīng)運(yùn)而生。
默認(rèn)情況下,debugfs會被掛載在目錄/sys/kernel/debug之下,如果您的發(fā)行版里沒有自動掛載,可以用如下命令手動完成:
# mount -t debugfs none /your/debugfs/dir
Linux內(nèi)核為debugfs提供了非常簡潔的API,本文接下來將以一個實(shí)作為例來介紹,sample code可以從這里下載。
這個實(shí)作會在debugfs中建立如下的目錄結(jié)構(gòu):
其中,a對應(yīng)模塊中的一個u8類型的變量,b和subdir下面的c都是對應(yīng)模塊里的一個字符數(shù)組,只是它們的實(shí)現(xiàn)方式不同。
在module_init里,我們首先要建立根目錄mydebug:
my_debugfs_root = debugfs_create_dir("mydebug", NULL);
***個參數(shù)是目錄的名稱,第二個參數(shù)用來指定這個目錄的上級目錄,如果是NULL,則表示是放在debugfs的根目錄里。
子目錄也是用debugfs_create_dir來實(shí)現(xiàn):
sub_dir = debugfs_create_dir("subdir", my_debugfs_root);
建立文件a的代碼非常簡單:
debugfs_create_u8("a", 0644, my_debugfs_root, &a);
這表示文件名為“a”,文件屬性是0644,父目錄是上面建立的“mydebug”,對應(yīng)的變量是模塊中的a。
Linux內(nèi)核還提供了其他一些創(chuàng)建debugfs文件的API,請參考本文的附錄。
b是一個32-bytes的字符數(shù)組,在debugfs里,數(shù)組可以用blob wrapper來實(shí)現(xiàn)。
char hello[32] = "Hello world!\n"; struct debugfs_blob_wrapper b; b.data = (void *)hello; b.size = strlen(hello) + 1; debugfs_create_blob("b", 0644, my_debugfs_root, &b);
這里需要注意的是,blob wrapper定義的數(shù)據(jù)只能是只讀的。在本例中,雖然我們把文件b的權(quán)限設(shè)定為0644,但實(shí)際這個文件還是只讀的,如果試圖改寫這個文件,系統(tǒng)將提示出錯。
如果需要對內(nèi)核數(shù)組進(jìn)行寫的動作,blob wrapper就無法滿足要求,我們只能通過自己定義文件操作來實(shí)現(xiàn)。在這個實(shí)作里,可以參考文件c的實(shí)現(xiàn)。c和b在模塊里對應(yīng)著同一塊字符數(shù)組,不同的是,b是只讀的,而c通過自定義的文件操作同時實(shí)現(xiàn)了讀和寫。
static int c_open(struct inode *inode, struct file *filp) { filp->private_data = inode->i_private; return 0; } static ssize_t c_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos) { if (*ppos >= 32) return 0; if (*ppos + count > 32) count = 32 - *ppos; if (copy_to_user(buffer, hello + *ppos, count)) return -EFAULT; *ppos += count; return count; } static ssize_t c_write(struct file *filp, const char __user *buffer, size_t count, loff_t *ppos) { if (*ppos >= 32) return 0; if (*ppos + count > 32) count = 32 - *ppos; if (copy_from_user(hello + *ppos, buffer, count)) return -EFAULT; *ppos += count; return count; } struct file_operations c_fops = { .owner = THIS_MODULE, .open = c_open, .read = c_read, .write = c_write, }; debugfs_create_file("c", 0644, sub_dir, NULL, &c_fops);
注:代碼里,c_open其實(shí)并沒有任何用處,因?yàn)閏_read和c_write直接引用了全局變量hello。這里,我們也可以換一種寫法,在read/write函數(shù)里用filp->private_data來引用字符數(shù)組hello。
到這里,三個文件和子目錄已經(jīng)創(chuàng)建完畢。在module_exit中,我們要記得釋放創(chuàng)建的數(shù)據(jù)。
debugfs_remove_recursive(my_debugfs_root);
debugfs_remove_recursive可以幫我們逐步移除每個分配
到此,相信大家對“Linux內(nèi)核里的DebugFS有什么用”有了更深的了解,不妨來實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!