0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

linux內(nèi)核中的debugfs該怎樣去使用呢?

嵌入式小生 ? 來源:嵌入式小生 ? 2023-08-21 09:01 ? 次閱讀

二、簡介

debugfs可用于內(nèi)核向用戶空間提供信息,debugfs是個小型的文件系統(tǒng),與/proc和sysfs不同,debugfs沒有較為嚴(yán)苛的規(guī)則和定義,我們可以在里面放置想要的任何信息,以便于系統(tǒng)開發(fā)和調(diào)試。

通常使用如下命令安裝debugfs:

mount-tdebugfsnone/sys/kernel/debug

或者:

mount-tdebugfsdebugfs/sys/kernel/debug/

也可以在/etc/fstab文件中使用等效的語句:

af29dad6-3fb9-11ee-ac96-dac502259ad0.png

默認(rèn)情況下,在一些發(fā)行版的linux系統(tǒng)中,只有root用戶可以訪問debugfs根目錄。

注意,在內(nèi)核源碼中,debugfs API僅以GPL方式導(dǎo)出到模塊。

三、debugfs的API

1、在debugfs中創(chuàng)建目錄

使用debugfs的代碼應(yīng)包含頭文件。然后是創(chuàng)建至少一個目錄來保存一組debugfs文件,可使用下列API實現(xiàn):

structdentry*debugfs_create_dir(constchar*name,structdentry*parent);

當(dāng)函數(shù)執(zhí)行成功后,將在指定的父目錄下創(chuàng)建一個名為name的目錄,如果parent為NULL,則該目錄將在debugfs根目錄中創(chuàng)建。

函數(shù)執(zhí)行成功后,返回一個指向struct dentry的指針,可用于在目錄中創(chuàng)建文件。

如果返回值為ERR_PTR(-ERROR)則表明出現(xiàn)了問題,如果返回ERR_PTR(-ENODEV),則表明內(nèi)核是在沒有debugfs支持的情況下構(gòu)建,這時候相關(guān)API將失效。

2、在debugfs目錄中創(chuàng)建文件

在debugfs目錄中創(chuàng)建文件的常用API是:

structdentry*debugfs_create_file(constchar*name,umode_tmode,structdentry*parent,
void*data,conststructfile_operations*fops);

name是要創(chuàng)建文件的名稱。

mode描述了文件應(yīng)具有的訪問權(quán)限。

parent表示應(yīng)保存該文件的目錄,數(shù)據(jù)將存儲在生成的inode結(jié)構(gòu)的i_private字段中。

fops是一個實現(xiàn)文件行為的一組文件操作。struct file_operations中包含了關(guān)于文件操作的很多接口函數(shù),此處至少應(yīng)提供read()和write()操作,其他操作可以根據(jù)實際情況實現(xiàn)。

該函數(shù)返回值將是指向所創(chuàng)建文件的dentry指針,如果發(fā)生錯誤,則返回ERR_PTR(-ERROR),如果缺少debugfs支持,則返回ERR_PTR(-ENODEV)。

3、創(chuàng)建一個具有初始大小的文件

創(chuàng)建一個具有初始大小的文件,可以使用以下API:

voiddebugfs_create_file_size(constchar*name,umode_tmode,structdentry*parent,void*data,
conststructfile_operations*fops,loff_tfile_size);

file_size是初始文件大小,其他參數(shù)與函數(shù)debugfs_create_file相同。

4、創(chuàng)建包含單個整數(shù)值(十進制)的文件

在多數(shù)情況下,創(chuàng)建一組文件操作并不是必需的,這時候可以使用以下助手函數(shù)創(chuàng)建包含單個整數(shù)值的文件:

//創(chuàng)建包含u8整數(shù)值的文件
voiddebugfs_create_u8(constchar*name,umode_tmode,structdentry*parent,u8*value);

//創(chuàng)建包含u16整數(shù)值的文件
voiddebugfs_create_u16(constchar*name,umode_tmode,structdentry*parent,u16*value);

////創(chuàng)建包含u32整數(shù)值的文件
voiddebugfs_create_u32(constchar*name,umode_tmode,structdentry*parent,u32*value);

//創(chuàng)建包含u64整數(shù)值的文件
voiddebugfs_create_u64(constchar*name,umode_tmode,structdentry*parent,u64*value);

這些文件支持讀取和寫入給定值;如果不支持寫入特定文件,只需相應(yīng)設(shè)置模式位即可,使用上述API創(chuàng)建的文件中的值是十進制的。

5、創(chuàng)建包含單個十六進制值的文件:

如果需要設(shè)置十六進制,可以使用以下API函數(shù):

voiddebugfs_create_x8(constchar*name,umode_tmode,structdentry*parent,u8*value);
voiddebugfs_create_x16(constchar*name,umode_tmode,structdentry*parent,u16*value);
voiddebugfs_create_x32(constchar*name,umode_tmode,structdentry*parent,u32*value);
voiddebugfs_create_x64(constchar*name,umode_tmode,structdentry*parent,u64*value);

只要我們知道要導(dǎo)出的值的大小,上述函數(shù)就非常有用。但是需要注意的是,某些類型在不同體系結(jié)構(gòu)上可能具有不同的寬度。下列函數(shù)可以在這種特殊情況下提供幫助:

voiddebugfs_create_size_t(constchar*name,umode_tmode,structdentry*parent,size_t*value);

debugfs_create_size_t()函數(shù)將創(chuàng)建一個debugfs文件來表示size_t類型的變量。

6、創(chuàng)建包含unsigned long 類型的變量的文件

對于十進制和十六進制的 unsigned long 類型的變量可使用以下助手函數(shù):

structdentry*debugfs_create_ulong(constchar*name,umode_tmode,structdentry*parent,unsignedlong*value);

voiddebugfs_create_xul(constchar*name,umode_tmode,structdentry*parent,unsignedlong*value);

7、創(chuàng)建包含布爾類型的文件

對于布爾值可使用下列API函數(shù):

voiddebugfs_create_bool(constchar*name,umode_tmode,structdentry*parent,bool*value);

讀取結(jié)果文件將產(chǎn)生Y(對于非零值)或N,后跟換行符。如果想要向該文件寫入數(shù)值,該文件將接收大寫或小寫值,或者1或0,其他任何的輸入都將被忽略。

8、創(chuàng)建包含atomic_t類型的值的文件

atomic_t值可使用以下API函數(shù)放置在debugfs中:

voiddebugfs_create_atomic_t(constchar*name,umode_tmode,structdentry*parent,atomic_t*value)

讀取該文件將獲取atomic_t值,寫入該文件將設(shè)置atomic_t值。

9、創(chuàng)建包含二進制數(shù)據(jù)塊的文件

也可以導(dǎo)出二進制數(shù)據(jù)塊,數(shù)據(jù)塊具有以下結(jié)構(gòu)和功能:

structdebugfs_blob_wrapper{
void*data;
unsignedlongsize;
};

structdentry*debugfs_create_blob(constchar*name,umode_tmode,structdentry*parent,structdebugfs_blob_wrapper*blob);

如果想轉(zhuǎn)儲一個寄存器塊,debugfs提供了兩個函數(shù):1、創(chuàng)建一個只有寄存器的文件。2、在另一個順序文件的中間位置插入一個寄存器塊:

structdebugfs_reg32{
char*name;
unsignedlongoffset;
};

structdebugfs_regset32{
conststructdebugfs_reg32*regs;
intnregs;
void__iomem*base;
structdevice*dev;/*OptionaldeviceforRuntimePM*/
};

debugfs_create_regset32(constchar*name,umode_tmode,structdentry*parent,structdebugfs_regset32*regset);

voiddebugfs_print_regs32(structseq_file*s,conststructdebugfs_reg32*regs,intnregs,void__iomem*base,char*prefix);

debugfs_print_regs32()中的base參數(shù)可能為0,但可能希望使用__stringify構(gòu)建reg32數(shù)組,許多寄存器名(宏)實際上是寄存器基數(shù)上的字節(jié)偏移量。

10、創(chuàng)建u32數(shù)組的文件

如果想在debugfs中轉(zhuǎn)儲一個u32數(shù)組,可使用以下API:

structdebugfs_u32_array{
u32*array;
u32n_elements;
};

voiddebugfs_create_u32_array(constchar*name,umode_tmode,structdentry*parent,structdebugfs_u32_array*array);

array參數(shù)包裝了一個指向數(shù)組數(shù)據(jù)及其元素數(shù)量的指針。

注意:一旦數(shù)組被創(chuàng)建,它的大小不能被改變。

11、創(chuàng)建與設(shè)備相關(guān)的seq_file

有一個助手函數(shù)可用于創(chuàng)建與設(shè)備相關(guān)的seq_file:

voiddebugfs_create_devm_seqfile(structdevice*dev,constchar*name,structdentry*parent,
int(*read_fn)(structseq_file*s,void*data));

dev參數(shù)是與這個debugfs文件相關(guān)的設(shè)備。

read_fn是一個函數(shù)指針,用于調(diào)用它來打印seq_file內(nèi)容。

12、為debugfs中的文件重命名

如果想要重命名debugfs目錄下的文件名,可使用以下API:

structdentry*debugfs_rename(structdentry*old_dir,structdentry*old_dentry,
structdentry*new_dir,constchar*new_name);

調(diào)用debugfs_rename()將為現(xiàn)有的debugfs文件(可能在不同的目錄中)提供一個新名稱,在調(diào)用debugfs_rename()之前必須不存在new_name,返回值是帶有更新后信息的old_dentry。

13、為debugfs目錄中的文件創(chuàng)建符號鏈接

符號鏈接可通過debugfs_create_symlink()創(chuàng)建:

structdentry*debugfs_create_symlink(constchar*name,structdentry*parent,constchar*target);

14、刪除debugfs創(chuàng)建的目錄或者文件

在debugfs中創(chuàng)建的所有目錄都不會自動清除。如果在沒有顯式刪除debugfs項的情況下卸載了一個模塊,這時結(jié)果將是出現(xiàn)大量過時的指針,還可能會出現(xiàn)一些奇怪的行為。因此,必須存在刪除創(chuàng)建的所有文件和目錄的操作和入口點。

可使用以下API刪除文件:

voiddebugfs_remove(structdentry*dentry);

如果dentry值是NULL或錯誤值,這時候?qū)⒉粫h除任何內(nèi)容。

使用下列API可以刪除整個目錄層級結(jié)構(gòu),在調(diào)試的時候可以使用:

voiddebugfs_remove_recursive(structdentry*dentry);

如果將指向與頂級目錄對應(yīng)的dentry的指針傳遞給該debugfs_remove_recursive(),這時候該目錄下的整個層次結(jié)構(gòu)將被刪除。

更多API可參見文末附上的參考鏈接。

四、實驗代碼

在本小節(jié)中,將使用上述提到的API在debugfs中創(chuàng)建目錄,并導(dǎo)出相應(yīng)的參數(shù)描述文件,然后在命令行中對其進行查看,首先設(shè)計代碼:

/**
*@filedebugfs_demo.c
*@authoryourname(you@domain.com)
*@briefdebugfsapiusage
*@version0.1
*@date2023-08-17
*
*@copyrightCopyright(c)2023
*
*/
#include
#include
#include
#include
#include
#include

#include
#include
#include

#defineBUFFER_SIZE256
staticcharbuffer[BUFFER_SIZE];

staticstructdentry*debugfs_demo_dir;
staticu8u8data=90;
staticu32boolData=false;

staticstructdentry*general_file,*u8data_dentry,*x8data_dentry,*bool_dentry;


staticintgeneral_file_open(structinode*inode,structfile*file)
{
printk(KERN_INFO"dogeneral_file_openops
");

return0;
}


staticssize_tgeneral_file_read(structfile*file,char__user*ubuf,size_tsize,loff_t*loff)
{
returnsimple_read_from_buffer(ubuf,size,loff,buffer,BUFFER_SIZE);
}



staticssize_tgeneral_file_write(structfile*file,constchar__user*ubuf,size_tsize,loff_t*loff)
{
if(size>BUFFER_SIZE)return-EINVAL;
returnsimple_write_to_buffer(buffer,BUFFER_SIZE,loff,ubuf,size);
}

staticstructfile_operationsgeneral_file_ops=
{
.open=general_file_open,
.read=general_file_read,
.write=general_file_write
};


staticchardata[4]={0x01,0x05,0x12,0x23};
staticstructdebugfs_blob_wrapperblobData={data,4};

staticint__initdebugfs_demo_init(void)
{
//1、createdebugfs_demo_dirdirindebugfs
debugfs_demo_dir=debugfs_create_dir("debugfs_demo_dir",NULL);
if(!debugfs_demo_dir){
pr_err("failedtocreatedebugfsentrydebugfs_demo_dir
");
return-1;
}

//2、creategeneral_fileindebugfs_demo_dir
general_file=debugfs_create_file("general_file",0644,debugfs_demo_dir,NULL,&general_file_ops);

//3、createu8dataindebugfs
u8data_dentry=debugfs_create_u8("u8data",0644,debugfs_demo_dir,&u8data);

//4、createx8dataindebugfs
x8data_dentry=debugfs_create_x8("x8data",0644,debugfs_demo_dir,&u8data);

//5、createboolDataindebugfs
bool_dentry=debugfs_create_bool("boolData",0644,debugfs_demo_dir,&boolData);

//6、createblobDataindebugfs
debugfs_create_blob("blobData",0644,debugfs_demo_dir,&blobData);

printk(KERN_INFO"debugfsdemocreatesuccessful
");

return0;
}

staticvoid__exitdebugfs_demo_exit(void)
{
debugfs_remove_recursive(debugfs_demo_dir);

printk(KERN_INFO"debugfs_demo_exit
");
}

module_init(debugfs_demo_init);
module_exit(debugfs_demo_exit);

MODULE_AUTHOR("iriczhao");
MODULE_LICENSE("GPL");

在上述代碼中,將在debugfs中創(chuàng)建一個名為debugfs_demo_dir的目錄,并且在該目錄中導(dǎo)出五種類型的數(shù)據(jù):

1、通用文件數(shù)據(jù):general_file,值默認(rèn)沒指定

2、以十進制導(dǎo)出數(shù)據(jù):u8data,值為90

3、以十六進制導(dǎo)出數(shù)據(jù):x8data,值為0x5a

4、布爾類型數(shù)據(jù):boolData,值為N

5、blob類型數(shù)據(jù):blobData,值為0x01,0x05,0x12,0x23

將上述代碼以模塊方式構(gòu)建后(模塊名debugfs_demo.ko)拷貝到目標(biāo)平臺中,使用mount命令查看目前已掛載的文件系統(tǒng):

af55e4b4-3fb9-11ee-ac96-dac502259ad0.png

發(fā)現(xiàn)并沒有掛載debugfs,這時候使用以下命令可以手動掛載debugfs:

mount-tdebugfsdebugfs/sys/kernel/debug/
af89f272-3fb9-11ee-ac96-dac502259ad0.png

接著將debugfs_demo.ko加載進內(nèi)核,完成后將路徑切換進/sys/kernel/debug:

afc97f8c-3fb9-11ee-ac96-dac502259ad0.png

這時候看到期望的debugfs目錄debugfs_demo_dir導(dǎo)出成功,然后切換進該目錄中:

afe6f670-3fb9-11ee-ac96-dac502259ad0.png

看見了在驅(qū)動程序中創(chuàng)建的五個文件,分別查看一下數(shù)據(jù):

b023cb22-3fb9-11ee-ac96-dac502259ad0.png

從輸出結(jié)果分析,數(shù)據(jù)符合驅(qū)動程序運行后預(yù)期的結(jié)果!






審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5343

    瀏覽量

    120365
  • Linux系統(tǒng)
    +關(guān)注

    關(guān)注

    4

    文章

    593

    瀏覽量

    27397
  • 十六進制
    +關(guān)注

    關(guān)注

    2

    文章

    32

    瀏覽量

    37744
  • LINUX內(nèi)核
    +關(guān)注

    關(guān)注

    1

    文章

    316

    瀏覽量

    21650
  • gpl
    gpl
    +關(guān)注

    關(guān)注

    0

    文章

    26

    瀏覽量

    2181

原文標(biāo)題:linux內(nèi)核中的debugfs原來可以這樣玩!

文章出處:【微信號:嵌入式小生,微信公眾號:嵌入式小生】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    在Boost電源怎樣選擇電容的型號和電容容量?

    我們之前了解過電容的作用,不外乎儲能、濾波等作用。那么在Boost電源又該怎樣選擇電容的型號和電容容量?
    發(fā)表于 08-14 15:44 ?3013次閱讀
    在Boost電源<b class='flag-5'>中</b><b class='flag-5'>該</b><b class='flag-5'>怎樣</b><b class='flag-5'>去</b>選擇電容的型號和電容容量<b class='flag-5'>呢</b>?

    怎樣移植linux內(nèi)核

    怎樣移植linux內(nèi)核?有哪些操作流程?
    發(fā)表于 10-19 09:40

    內(nèi)核 uC/OS-II 怎樣移植

    uC/OS-II內(nèi)核結(jié)構(gòu)是如何構(gòu)成的?微內(nèi)核 uC/OS-II 的任務(wù)到底是什么?微內(nèi)核 uC/OS-II
    發(fā)表于 10-29 07:21

    怎樣使用Cortex-M內(nèi)核的精確延時方法

    為什么要學(xué)習(xí)這種Cortex-M內(nèi)核的精確延時方法?怎樣使用Cortex-M內(nèi)核
    發(fā)表于 11-30 06:00

    嵌入式Linux操作系統(tǒng)怎樣使用

    嵌入式Linux操作系統(tǒng)怎樣使用?嵌入式Linux操作系統(tǒng)的命令有哪些
    發(fā)表于 12-23 08:06

    FreeRtos消息隊列API的調(diào)用怎樣實現(xiàn)

    消息隊列是什么?消息隊列有何作用?FreeRtos消息隊列API的調(diào)用怎樣實現(xiàn)?
    發(fā)表于 01-20 07:04

    socket通信怎樣實現(xiàn)

    socket通信怎樣實現(xiàn)怎樣實現(xiàn)socket AES-CBC加密
    發(fā)表于 01-20 07:41

    ROS服務(wù)數(shù)據(jù)怎樣使用

    ROS服務(wù)數(shù)據(jù)是怎樣定義的?ROS服務(wù)數(shù)據(jù)怎樣使用?
    發(fā)表于 02-14 06:20

    Ubuntu固件的編譯怎樣使用

    怎樣編譯Ubuntu固件?Ubuntu固件的編譯怎樣使用
    發(fā)表于 02-15 06:18

    怎樣編譯Linux內(nèi)核

    怎樣編譯Linux內(nèi)核?有哪些編譯步驟?
    發(fā)表于 03-03 13:04

    怎樣解決RK3399內(nèi)核編譯出錯的問題

    怎樣解決RK3399內(nèi)核編譯出錯的問題?
    發(fā)表于 03-07 06:10

    怎樣Linux內(nèi)核源代碼

    怎樣Linux內(nèi)核源代碼
    發(fā)表于 10-25 10:15 ?13次下載
    <b class='flag-5'>怎樣</b><b class='flag-5'>去</b>讀<b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>源代碼

    你知道Linux內(nèi)核里的DebugFS

    DebugFS,顧名思義,是一種用于內(nèi)核調(diào)試的虛擬文件系統(tǒng),內(nèi)核開發(fā)者通過debugfs和用戶空間交換數(shù)據(jù)。
    發(fā)表于 04-25 18:55 ?1884次閱讀
    你知道<b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>里的<b class='flag-5'>DebugFS</b>?

    要學(xué)會調(diào)試內(nèi)核打印debugfs

    name是創(chuàng)建的目錄名字,parent是目錄的父目錄。如果填NULL,則直接出現(xiàn)在debugfs的根目錄。
    發(fā)表于 04-27 19:01 ?1198次閱讀

    Linux驅(qū)動debugfs接口代碼實現(xiàn)

    實現(xiàn)效果 在 /sys/kernel/debug/ 目錄下創(chuàng)建一個 ion/test 文件,通過 cat 、 echo 的方式進行讀寫操作: 前期準(zhǔn)備 內(nèi)核配置打開debugfs
    的頭像 發(fā)表于 09-27 11:12 ?478次閱讀
    <b class='flag-5'>Linux</b>驅(qū)動<b class='flag-5'>debugfs</b>接口代碼實現(xiàn)