Linux debugfs

DebugFS,顧名思義,是一種用于內(nèi)核調(diào)試的虛擬文件系統(tǒng),內(nèi)核開發(fā)者通過debugfs和用戶空間交換數(shù)據(jù)咆瘟。類似的虛擬文件系統(tǒng)還有procfs和sysfs等,這幾種虛擬文件系統(tǒng)都并不實際存儲在硬盤上诽里,而是Linux內(nèi)核運行起來后才建立起來搞疗。

通常情況下,最常用的內(nèi)核調(diào)試手段是printk须肆。但printk并不是所有情況都好用,比如打印的數(shù)據(jù)可能過多桩皿,我們真正關心的數(shù)據(jù)在大量的輸出里不是那么一目了然豌汇;或者我們在調(diào)試時可能需要修改某些內(nèi)核變量,這種情況下printk就無能為力泄隔,而如果為了修改某個值重新編譯內(nèi)核或者驅動又過于低效拒贱,此時就需要一個臨時的文件系統(tǒng)可以把我們需要關心的數(shù)據(jù)映射到用戶空間。在過去佛嬉,procfs可以實現(xiàn)這個目的逻澳,到了2.6時代,新引入的sysfs也同樣可以實現(xiàn)暖呕,但不論是procfs或是sysfs斜做,用它們來實現(xiàn)某些debug的需求,似乎偏離了它們創(chuàng)建的本意湾揽。比如procfs瓤逼,其目的是反映進程的狀態(tài)信息;而sysfs主要用于Linux設備模型库物。不論是procfs或是sysfs的接口應該保持相對穩(wěn)定霸旗,因為用戶態(tài)程序很可能會依賴它們。當然戚揭,如果我們只是臨時借用procfs或者sysfs來作debug之用诱告,在代碼發(fā)布之前將相關調(diào)試代碼刪除也無不可。但如果相關的調(diào)試借口要在相當長的一段時間內(nèi)存在于內(nèi)核之中民晒,就不太適合放在procfs和sysfs里了精居。故此,debugfs應運而生镀虐。

默認情況下箱蟆,debugfs會被掛載在目錄/sys/kernel/debug之下,如果您的發(fā)行版里沒有自動掛載刮便,可以用如下命令手動完成:

mount -t debugfs none /your/debugfs/dir

Linux內(nèi)核為debugfs提供了非常簡潔的API空猜,本文接下來將以一個實作為例來介紹,sample code可以從這里下載。

這個實作會在debugfs中建立如下的目錄結構:

image

其中辈毯,a對應模塊中的一個u8類型的變量坝疼,b和subdir下面的c都是對應模塊里的一個字符數(shù)組,只是它們的實現(xiàn)方式不同谆沃。

在module_init里钝凶,我們首先要建立根目錄mydebug:

my_debugfs_root = debugfs_create_dir("mydebug", NULL);

第一個參數(shù)是目錄的名稱,第二個參數(shù)用來指定這個目錄的上級目錄唁影,如果是NULL耕陷,則表示是放在debugfs的根目錄里。

子目錄也是用debugfs_create_dir來實現(xiàn):

sub_dir = debugfs_create_dir("subdir", my_debugfs_root);

建立文件a的代碼非常簡單:

debugfs_create_u8("a", 0644, my_debugfs_root, &a);

這表示文件名為“a”据沈,文件屬性是0644哟沫,父目錄是上面建立的“mydebug”,對應的變量是模塊中的a锌介。

Linux內(nèi)核還提供了其他一些創(chuàng)建debugfs文件的API嗜诀,請參考本文的附錄币砂。

b是一個32-bytes的字符數(shù)組绵估,在debugfs里,數(shù)組可以用blob wrapper來實現(xiàn)亲族。

char hello[32] = "Hello world!\n";  
structdebugfs_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的權限設定為0644尊浪,但實際這個文件還是只讀的匣屡,如果試圖改寫這個文件,系統(tǒng)將提示出錯拇涤。

如果需要對內(nèi)核數(shù)組進行寫的動作捣作,blob wrapper就無法滿足要求,我們只能通過自己定義文件操作來實現(xiàn)鹅士。在這個實作里券躁,可以參考文件c的實現(xiàn)。c和b在模塊里對應著同一塊字符數(shù)組掉盅,不同的是也拜,b是只讀的,而c通過自定義的文件操作同時實現(xiàn)了讀和寫趾痘。

staticint c_open(structinode *inode, structfile *filp)   
{   
    filp->private_data = inode->i_private;  
    return0;   
}   
    
staticssize_t c_read(structfile *filp, char__user *buffer,   
        size_tcount, loff_t *ppos)   
{   
    if(*ppos >= 32)   
        return0;   
    if(*ppos + count > 32)   
        count = 32 - *ppos;  
    
    if(copy_to_user(buffer, hello + *ppos, count))   
        return-EFAULT;   
    
    *ppos += count;  
    
    returncount;   
}   
    
staticssize_t c_write(structfile *filp, constchar __user *buffer,  
        size_tcount, loff_t *ppos)   
{   
    if(*ppos >= 32)   
        return0;   
    if(*ppos + count > 32)   
        count = 32 - *ppos;  
    
    if(copy_from_user(hello + *ppos, buffer, count))   
        return-EFAULT;   
    
    *ppos += count;  
    
    returncount;   
}   
    
structfile_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其實并沒有任何用處,因為c_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可以幫我們逐步移除每個分配的dentry缀辩,如果您想一個一個手動的移除,也可以直接調(diào)用debugfs_remove踪央。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末臀玄,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子畅蹂,更是在濱河造成了極大的恐慌镐牺,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件魁莉,死亡現(xiàn)場離奇詭異,居然都是意外死亡募胃,警方通過查閱死者的電腦和手機旗唁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來痹束,“玉大人检疫,你說我怎么就攤上這事〉凰唬” “怎么了屎媳?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長论巍。 經(jīng)常有香客問我烛谊,道長,這世上最難降的妖魔是什么嘉汰? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任丹禀,我火速辦了婚禮,結果婚禮上鞋怀,老公的妹妹穿的比我還像新娘双泪。我一直安慰自己,他們只是感情好密似,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布焙矛。 她就那樣靜靜地躺著,像睡著了一般残腌。 火紅的嫁衣襯著肌膚如雪村斟。 梳的紋絲不亂的頭發(fā)上贫导,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天,我揣著相機與錄音邓梅,去河邊找鬼脱盲。 笑死,一個胖子當著我的面吹牛日缨,可吹牛的內(nèi)容都是我干的钱反。 我是一名探鬼主播,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼匣距,長吁一口氣:“原來是場噩夢啊……” “哼面哥!你這毒婦竟也來了?” 一聲冷哼從身側響起毅待,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤尚卫,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后尸红,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吱涉,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年外里,在試婚紗的時候發(fā)現(xiàn)自己被綠了怎爵。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡盅蝗,死狀恐怖鳖链,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情墩莫,我是刑警寧澤芙委,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站狂秦,受9級特大地震影響灌侣,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜裂问,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一顶瞳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧愕秫,春花似錦慨菱、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至甜孤,卻和暖如春协饲,著一層夾襖步出監(jiān)牢的瞬間畏腕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工茉稠, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留描馅,地道東北人。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓而线,卻偏偏與公主長得像铭污,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子膀篮,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 第一章 1.Linux是一套免費使用和自由傳播的類UNIX操作系統(tǒng)嘹狞,它可以基于Intel x86系列處理器以及Cy...
    yansicing閱讀 5,359評論 0 9
  • 姓名:吳兆陽 學號:14020199009 轉自韋東山 嵌牛導讀:對嵌入式初學者,沒有足夠的視野選擇一個合適投入方...
    吳兆陽閱讀 2,380評論 0 4
  • Linux print system linux中的調(diào)試方法有很多種誓竿,但我們最常用的也是最關鍵的調(diào)試工具應該就是使...
    Creator_Ly閱讀 1,930評論 0 4
  • 在C語言中,五種基本數(shù)據(jù)類型存儲空間長度的排列順序是: A)char B)char=int<=float C)ch...
    夏天再來閱讀 3,333評論 0 2
  • ef
    紅昔昔閱讀 84評論 0 2