日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux内核 DebugFS

發(fā)布時間:2025/4/16 linux 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux内核 DebugFS 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

點(diǎn)擊打開鏈接

一、簡介

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。我們在調(diào)試時可能需要修改某些內(nèi)核變量,這種情況下printk就無能為力,而如果為了修改某個值重新編譯內(nèi)核或者驅(qū)動又過于低效,此時就需要一個臨時的文件系統(tǒng)可以把我們需要關(guān)心的數(shù)據(jù)映射到用戶空間。不論是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 /sys/kernel/debug


二、打開debugfs選項(xiàng)

要使用debugfs,首先我們要設(shè)置一下配置選項(xiàng)CONFIG_DEBUG_FS,可以在config文件中設(shè)置CONFIG_DEBUG_FS=y,也可以通過menuconfig來設(shè)置

Kernelhacking --->

????????????????????????? [*]Debug Filesystem

并且驅(qū)動中使用debugfs需要包含頭文件<linux/debugfs.h>,為了在用戶態(tài)下使用debugfs,必須把它mount到一個目錄下


三、Llinux內(nèi)核為debugfs提供了非常簡潔的API:

debugfs
|--mydebug
?? |--subdir
????? c
?? a
?? b


1、創(chuàng)建和撤銷目錄及文件

1)structdentry *debugfs_create_dir(constchar*name,structdentry *parent);
第一個參數(shù)是目錄的名稱,第二個參數(shù)是指定這個目錄的上級目錄,如果是NULL,表示放在debugfs的根目錄下
my_debugfs_root = debugfs_create_dir("mydebug", NULL);
sub_dir = debugfs_create_dir("subdir", my_debugfs_root);
debugfs
|--mydebug
?? |--subdir

2)structdentry *debugfs_create_file(constchar*name, mode_t mode,structdentry *parent,void*data,conststructfile_operations *fops);
文件c通過自定義的文件操作實(shí)現(xiàn)讀寫
debugfs
|--mydebug
?? |--subdir
????? c
[cpp]?view plaincopy
  • 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);??

  • 3)voiddebugfs_remove(structdentry *dentry);4)voiddebugfs_remove_recursive(structdentry *dentry);
    在module_exit中,我們要釋放創(chuàng)建的數(shù)據(jù)
    debugfs_remove_recursive(my_debugfs_root);
    這個函數(shù)可以幫我們逐步移除每個分配的dentry,如果你想要一個個手動移除,也可以直接調(diào)用debugfs_remove

    2、創(chuàng)建單值文件
    1)structdentry *debugfs_create_u8(constchar*name, mode_t mode,structdentry *parent, u8 *value);
    debugfs_create_u8("a", 0644, my_debugfs_root, &a);
    debugfs
    |--mydebug
    ?? |--subdir
    ?? a
    創(chuàng)建的文件名是a,對應(yīng)內(nèi)核中的變量名為a,文件屬性為0644,可以對文件讀寫,相當(dāng)于是對內(nèi)核變量讀寫。

    2)structdentry *debugfs_create_u16(constchar*name, mode_t mode,structdentry *parent, u16 *value);3)structdentry *debugfs_create_u32(constchar*name, mode_t mode,structdentry *parent, u32 *value);4)structdentry *debugfs_create_u64(constchar*name, mode_t mode,structdentry *parent, u64 *value);其中,后綴為x8、x16、x32的這三個函數(shù)是指debugfs中的數(shù)據(jù)用十六進(jìn)制表示。?5)structdentry *debugfs_create_x8(constchar*name, mode_t mode,structdentry *parent, u8 *value);6)structdentry *debugfs_create_x16(constchar*name, mode_t mode,structdentry *parent, u16 *value);7)structdentry *debugfs_create_x32(constchar*name, mode_t mode,structdentry *parent, u32 *value);8)structdentry *debugfs_create_size_t(constchar*name, mode_t mode,structdentry *parent,size_t*value);9)structdentry *debugfs_create_bool(constchar*name, mode_t mode,structdentry *parent, u32 *value);

    3、創(chuàng)建BLOB文件
    structdebugfs_blob_wrapper {????void*data;????unsignedlongsize;};structdentry *debugfs_create_blob(constchar*name, mode_t mode,structdentry *parent,structdebugfs_blob_wrapper *blob);
    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);
    debugfs
    |--mydebug
    ?? |--subdir
    ?? b
    需要注意的是blob wrapper定義的數(shù)據(jù)只能是只讀的,在本例中我們將文件b的權(quán)限設(shè)定為0644,但實(shí)際這個文件還是只讀的,
    如果試圖改寫這個文件,系統(tǒng)將提示出錯。
    因此,如果我們要對內(nèi)核數(shù)組進(jìn)行讀寫動作,blob wrapper就無法滿足要求,我們只能自己定義文件操作來實(shí)現(xiàn)。

    4、其他
    structdentry *debugfs_rename(structdentry *old_dir,structdentry *old_dentry,structdentry *new_dir,constchar*new_name);structdentry *debugfs_create_symlink(constchar*name,structdentry *parent,constchar*target);

    以上部分轉(zhuǎn)自:http://www.cnblogs.com/wwang/archive/2011/01/17/1937609.html


    三、實(shí)例
    這個實(shí)例雖然簡單,但是融合了如何在debugfs目錄下創(chuàng)建文件,并給出了文件的操作方法;
    也說明了如何創(chuàng)建變量文件,并且用戶空間讀寫這個變量文件相當(dāng)于是在讀寫內(nèi)核空間的這個文件對應(yīng)的變量
    [cpp]?view plaincopy
  • //?dbgfs.c???
  • /*?
  • ?*?(C)?05-07-2012?Yang?Honggang?(Joseph),?Dslab?<eagle.rtlinux@gmail.com>?
  • ?*/??
  • #include?<linux/debugfs.h>??
  • #include?<linux/module.h>??
  • #include?<linux/mm.h>??
  • #include?<asm/uaccess.h>???
  • ??
  • struct?dentry?*parent,?*sw,?*inf;??
  • u32?tr_on?=?0;??
  • ??
  • struct?my_data_struct?{??
  • ????void*?data;??
  • ????unsigned?long?size;??
  • }?mds;??
  • ??
  • struct?page*?pg;??
  • ??
  • static?ssize_t?data_read(struct?file?*file,?char?__user?*user_buf,size_t?count,?loff_t?*ppos)??
  • {??
  • ????unsigned?long?i;??
  • ????size_t?cnt;??
  • ?????
  • ????printk("tr_on:%d\n",?tr_on);??
  • ????/*?If?the?tracing_on?is?Y,?fill?the?data?buffer?with?debug?info?*/??
  • ????if?(tr_on)?{??
  • ????????tr_on?=?0;?/*?Automaticlly?clear?the?'tracing_on'?flag?*/??
  • ????????????????for?(i?=?0;?i?<?(mds.size?-?11)?/?11;?i?++)?{??
  • ????????????????sprintf((char*)((char*)mds.data?+?i?*?11?),?"%ld\n",?i?+?1000000000);??
  • ????????}??
  • ??????????
  • ????????/*?Copy?debug?info?to?userspace?*/??
  • ????????cnt?=?copy_to_user(user_buf,?(const?void?*)mds.data,?mds.size);??
  • ????????return?(mds.size?-?cnt);??
  • ????}??
  • ?????
  • ????return?0;??
  • }??
  • ??
  • const?struct?file_operations?fops?=??
  • {??
  • ????????.read?=?data_read,??
  • };??
  • ??
  • static?int?__init?dbgfs_demon_init(void)??
  • {??
  • ??
  • ????printk("dbgfs?init\n");???
  • ????/*?Create?dbgfs_demon?directory?in?the?debugfs?root?*/??
  • ????parent?=?debugfs_create_dir("dbgfs_demon",?NULL);??
  • ????if?(!parent)???
  • ????return?-1;?????
  • ??
  • //在debugfs目錄下創(chuàng)建變量名tracing_on,對應(yīng)內(nèi)核中的變量tr_on??
  • ????/*?Create?a?output?switch?in?dbgfs_demon?*/??
  • ????sw?=?debugfs_create_bool("tracing_on",?S_IRWXU,parent,?&tr_on);???
  • ????if?(!sw)??
  • ????goto?p_out;??
  • ??????
  • ????/*?Create?a?file?for?debug?information?exporting?*/??
  • ????mds.size?=?4?*?1024;??????
  • ????/*?Allocate?one?page?for?info.?storing?*/??
  • ????pg?=?alloc_pages(__GFP_HIGHMEM?|?__GFP_ZERO,?0);??
  • ????/*?Covert?to?Memory?address?*/??
  • ????mds.data?=?(void*)?page_address(pg);??
  • ????if?(!pg)??
  • ????goto?p_out;??
  • ??
  • //在debugfs目錄下創(chuàng)建文件名data,對應(yīng)的文件操作為fops里面的read和write方法,??
  • //通過read函數(shù)中從用戶空間傳來的buf進(jìn)行相應(yīng)的處理。??
  • ????inf?=?debugfs_create_file("data",?S_IRUSR,parent,?&mds,?&fops);??
  • ????if?(!inf)??
  • ????goto?sw_out;??
  • ??
  • ????return?0;??
  • ??
  • sw_out:??
  • ????debugfs_remove(sw);??
  • ????__free_pages(pg,?0);??
  • p_out:??
  • ????debugfs_remove(parent);??
  • ??
  • ????return?-1;??
  • }??
  • ??
  • static?void?__exit?dbgfs_demon_exit(void)??
  • {??
  • ??
  • ????if?(pg)??
  • ????__free_pages(pg,?0);??
  • ??
  • ????debugfs_remove(inf);??
  • ????debugfs_remove(sw);??
  • ????debugfs_remove(parent);??
  • ????printk("dbgfs?exit\n");??
  • ??
  • ????return;??
  • }??
  • ??
  • module_init(dbgfs_demon_init);????
  • module_exit(dbgfs_demon_exit);????
  • MODULE_LICENSE("GPL");????
  • MODULE_AUTHOR("Yang?Honggang?(Joseph)?<eagle.rtlinux@gmail.com>");??
  • 模塊會在/sys/kernel/debugfs根目錄下創(chuàng)建
    dbgfs_demon/
    |--data
    |--tracing_on
    函數(shù)的操作邏輯是,如果tracing_on的值為Y,那么可以從文件data中讀出有用的調(diào)試信息,
    如果為N,那么讀data操作將不會返回任何數(shù)據(jù)。



    另外還有一個網(wǎng)上找到的debugfs的小例子:http://download.csdn.net/detail/luckywang1103/9369310

    總結(jié)

    以上是生活随笔為你收集整理的linux内核 DebugFS的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。