在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

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

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

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

Linux內(nèi)核ftrace的學(xué)習(xí)

B4Pb_gh_6fde77c ? 來源:相遇Linux ? 作者:陳波 ? 2021-08-13 17:33 ? 次閱讀

目錄

1. 前言

2. ARM64棧幀結(jié)構(gòu)

3. 編譯階段

3.1 未開啟ftrace時(shí)的blk_update_request

3.2 開啟ftrace時(shí)的blk_update_request

4. 鏈接階段

4.1 未開啟ftrace時(shí)的blk_update_request

4.2 開啟ftrace時(shí)的blk_update_request

5. 運(yùn)行階段

5.1 ftrace_init執(zhí)行后的blk_update_request

5.2 設(shè)定trace函數(shù)blk_update_request

6. 鉤子函數(shù)的替換過程

7.總結(jié)

參考文檔

1. 前言

本文主要是根據(jù)閱碼場(chǎng) 《Linux內(nèi)核tracers的實(shí)現(xiàn)原理與應(yīng)用》視頻課程,我自己在aarch64上的實(shí)踐。通過觀察鉤子函數(shù)的創(chuàng)建過程以及替換過程,理解trace的原理。本文同樣以blk_update_request函數(shù)為例進(jìn)行說明。

kernel版本:5.10平臺(tái):arm64

2.ARM64棧幀結(jié)構(gòu)

在開始介紹arm64架構(gòu)下的ftrace之前,先來簡(jiǎn)要說明一下arm64棧幀的相關(guān)知識(shí)。arm64有31個(gè)通用寄存器r0-r30,其中r0-r7用于Parameter/result 寄存器; r29為Frame Pointer寄存器,r30為L(zhǎng)ink寄存器,指向上級(jí)函數(shù)的返回地址;SP為棧指針。將以如下代碼為例,說明它的棧幀結(jié)構(gòu):

/*

* ARCH: armv8

* GCC版本:aarch64-linux-gnu-gcc (Linaro GCC 5.4-2017.01) 5.4.1 20161213

*/

intfun2(int c,int d)

{

return0;

}

intfun1(int a,int b)

{

int c = 1;

int d = 2;

fun2(c, d);

return0;

}

intmain(int argc,char **argv)

{

int a = 0;

int b = 1;

fun1(a,b);

}

aarch64-linux-gnu-objdump -d a.out 反匯編后的結(jié)果為:

0000000000400530 《fun2》:

/* 更新sp到fun2的棧底 */

400530: d10043ff sub sp, sp, #0x10

400534: b9000fe0 str w0, [sp,#12]

400538: b9000be1 str w1, [sp,#8]

40053c: 52800000 mov w0, #0x0 // #0

400540: 910043ff add sp, sp, #0x10

400544: d65f03c0 ret

0000000000400548 《fun1》:

/* 分配48字節(jié)棧空間,先更新sp=sp-48, 再入棧x29, x30, 此時(shí)sp指向棧頂 */

400548: a9bd7bfd stp x29, x30, [sp,#-48]!

/* x29、sp指向棧頂*/

40054c: 910003fd mov x29, sp

/* 入棧fun1參數(shù)0 */

400550: b9001fa0 str w0, [x29,#28]

/* 入棧fun1參數(shù)1 */

400554: b9001ba1 str w1, [x29,#24]

/* 入棧fun1局部變量c */

400558: 52800020 mov w0, #0x1 // #1

40055c: b9002fa0 str w0, [x29,#44]

/* 入棧fun1局部變量d */

400560: 52800040 mov w0, #0x2 // #2

400564: b9002ba0 str w0, [x29,#40]

400568: b9402ba1 ldr w1, [x29,#40]

40056c: b9402fa0 ldr w0, [x29,#44]

/* 跳轉(zhuǎn)到fun2 */

400570: 97fffff0 bl 400530 《fun2》

400574: 52800000 mov w0, #0x0 // #0

400578: a8c37bfd ldp x29, x30, [sp],#48

40057c: d65f03c0 ret

0000000000400580 《main》:

/* 分配48字節(jié)棧空間,先更新sp=sp-48, 再入棧x29, x30, 此時(shí)sp指向棧頂*/

400580: a9bd7bfd stp x29, x30, [sp,#-48]!

/* x29、sp指向棧頂*/

400584: 910003fd mov x29, sp

/* 入棧main參數(shù)0 */

400588: b9001fa0 str w0, [x29,#28]

/* 入棧main參數(shù)1 */

40058c: f9000ba1 str x1, [x29,#16]

/* 入棧變量a */

400590: b9002fbf str wzr, [x29,#44]

400594: 52800020 mov w0, #0x1 // #1

/* 入棧變量b */

400598: b9002ba0 str w0, [x29,#40]

40059c: b9402ba1 ldr w1, [x29,#40]

4005a0: b9402fa0 ldr w0, [x29,#44]

/* 跳轉(zhuǎn)到fun1 */

4005a4: 97ffffe9 bl 400548 《fun1》

4005a8: 52800000 mov w0, #0x0 // #0

4005ac: a8c37bfd ldp x29, x30, [sp],#48

4005b0: d65f03c0 ret

4005b4: 00000000 .inst 0x00000000 ; undefined

對(duì)應(yīng)棧幀結(jié)構(gòu)為:

f1e2a83e-fbba-11eb-9bcf-12bb97331649.png

總結(jié)一下:通過對(duì)aarch64代碼反匯編的分析,可以得出:

1. 每個(gè)函數(shù)在入口處首先會(huì)分配棧空間,且一次分配,確定棧頂,之后sp將不再變化;

2. 每個(gè)函數(shù)的棧頂部存放的是caller的棧頂指針,即fun1的棧頂存放的是main棧頂指針;

3. 對(duì)于最后一級(jí)callee函數(shù),由于x29保存了上一級(jí)caller的棧頂sp指針,因此不在需要入棧保存,如示例中fun2執(zhí)行時(shí),此時(shí)x29指向fun1的棧頂sp

下面我們將根據(jù)是否開啟ftrace配置,并區(qū)分編譯階段、鏈接階段和運(yùn)行階段,分別查看鉤子函數(shù)的替換及構(gòu)建情況。

3. 編譯階段

3.1 未開啟ftrace時(shí)的blk_update_request

00000000000012ac 《blk_update_request》:

12ac: d10183ff sub sp, sp, #0x60

12b0: a9017bfd stp x29, x30, [sp,#16]

12b4: 910043fd add x29, sp, #0x10

12b8: a90253f3 stp x19, x20, [sp,#32]

12bc: a9035bf5 stp x21, x22, [sp,#48]

12c0: a90463f7 stp x23, x24, [sp,#64]

12c4: f9002bf9 str x25, [sp,#80]

12c8: aa0003f6 mov x22, x0

12cc: 53001c38 uxtb w24, w1

12d0: 2a0203f5 mov w21, w2

12d4: 2a1803e0 mov w0, w24

12d8: 94000000 bl 12c 《blk_status_to_errno》

...

在未使能內(nèi)核配置項(xiàng)CONFIG_FTRACE時(shí),反匯編blk_update_request函數(shù)可以看出,不包含鉤子函數(shù)。

3.2 開啟ftrace時(shí)的blk_update_request

0000000000003f10 《blk_update_request》:

3f10: d10183ff sub sp, sp, #0x60

3f14: a9017bfd stp x29, x30, [sp,#16]

3f18: 910043fd add x29, sp, #0x10

3f1c: a90253f3 stp x19, x20, [sp,#32]

3f20: a9035bf5 stp x21, x22, [sp,#48]

3f24: a90463f7 stp x23, x24, [sp,#64]

3f28: f9002bf9 str x25, [sp,#80]

3f2c: aa0003f6 mov x22, x0

3f30: 53001c38 uxtb w24, w1

3f34: 2a0203f5 mov w21, w2

3f38: aa1e03e0 mov x0, x30

3f3c: 94000000 bl 0 《_mcount》

...

在使能內(nèi)核配置項(xiàng)CONFIG_FTRACE時(shí),可以看到blk_update_request函數(shù)增加了如下部分:

3f3c: 94000000 bl 0 《_mcount》

那么 bl 0 《_mcount》 是由誰在何時(shí)插入的呢? 答案是編譯器在編譯時(shí)插入,編譯選項(xiàng)-pg -mrecord-mcoun會(huì)在編譯時(shí)在每個(gè)可trace函數(shù)插入bl 0 《_mcount》,并將所有可trace的函數(shù)放到一個(gè)__mcount_loc的section中。

通過查看blk-core.o的可重定位段,可以看到有大量的地址需要定位到_mcount函數(shù),其中3f3c地址正是位于blk_update_request,它會(huì)在鏈接階段被重定位到_mcount函數(shù)的地址。

ubuntu@VM-0-9-ubuntu:~/qemu/kernel/linux/block$ aarch64-linux-gnu-objdump -r blk-core.o | grep _mcount

0000000000000014 R_AARCH64_CALL26 _mcount

000000000000005c R_AARCH64_CALL26 _mcount

00000000000000ac R_AARCH64_CALL26 _mcount

0000000000000108 R_AARCH64_CALL26 _mcount

0000000000000164 R_AARCH64_CALL26 _mcount

00000000000001bc R_AARCH64_CALL26 _mcount

0000000000000214 R_AARCH64_CALL26 _mcount

...

0000000000003f3c R_AARCH64_CALL26 _mcount

...

我們還可以看到,blk-core.o有一個(gè).rela__mcount_loc的可重定位段,里面存放了所有需要可trace函數(shù)中需要重定位到函數(shù)_mcount的地址。

ubuntu@VM-0-9-ubuntu:~/qemu/kernel/linux/block$ aarch64-linux-gnu-objdump -r blk-core.o

...

RELOCATION RECORDS FOR [__mcount_loc]:

OFFSET TYPE VALUE

0000000000000000 R_AARCH64_ABS64 .text+0x0000000000000014

0000000000000008 R_AARCH64_ABS64 .text+0x000000000000005c

0000000000000010 R_AARCH64_ABS64 .text+0x00000000000000ac

0000000000000018 R_AARCH64_ABS64 .text+0x0000000000000108

...

00000000000001b8 R_AARCH64_ABS64 .text+0x0000000000003f3c

...

4. 鏈接階段

4.1 未開啟ftrace時(shí)的blk_update_request

未使能內(nèi)核配置項(xiàng)CONFIG_FTRACE時(shí),鏈接階段與編譯階段一樣,反匯編blk_update_request函數(shù)可以看出,不包含鉤子函數(shù)

4.2 開啟ftrace時(shí)的blk_update_request

ffff8000104e43c8 《blk_update_request》:

ffff8000104e43c8: d10183ff sub sp, sp, #0x60

ffff8000104e43cc: a9017bfd stp x29, x30, [sp,#16]

ffff8000104e43d0: 910043fd add x29, sp, #0x10

ffff8000104e43d4: a90253f3 stp x19, x20, [sp,#32]

ffff8000104e43d8: a9035bf5 stp x21, x22, [sp,#48]

ffff8000104e43dc: a90463f7 stp x23, x24, [sp,#64]

ffff8000104e43e0: f9002bf9 str x25, [sp,#80]

ffff8000104e43e4: aa0003f6 mov x22, x0

ffff8000104e43e8: 53001c38 uxtb w24, w1

ffff8000104e43ec: 2a0203f5 mov w21, w2

ffff8000104e43f0: aa1e03e0 mov x0, x30

ffff8000104e43f4: 97ed1fde bl ffff80001002c36c 《_mcount》

ffff8000104e43f8: 2a1803e0 mov w0, w24

ffff8000104e43fc: 97fff432 bl ffff8000104e14c4 《blk_status_to_errno》

...

在鏈接階段,使能內(nèi)核配置項(xiàng)CONFIG_FTRACE時(shí),可以看到編譯階段的如下代碼

3f3c: 94000000 bl 0 《_mcount》

在鏈接階段已經(jīng)被替換為:

ffff8000104e43f4: 97ed1fde bl ffff80001002c36c 《_mcount》

其中_mcount函數(shù)反匯編為:

ffff80001002c36c 《_mcount》:

ffff80001002c36c: d65f03c0 ret

5. 運(yùn)行階段

5.1ftrace_init執(zhí)行后的blk_update_request

(gdb) x/20i blk_update_request

0xffff8000104e43c8 《blk_update_request》: sub sp, sp, #0x60

0xffff8000104e43cc 《blk_update_request+4》: stp x29, x30, [sp,#16]

0xffff8000104e43d0 《blk_update_request+8》: add x29, sp, #0x10

0xffff8000104e43d4 《blk_update_request+12》: stp x19, x20, [sp,#32]

0xffff8000104e43d8 《blk_update_request+16》: stp x21, x22, [sp,#48]

0xffff8000104e43dc 《blk_update_request+20》: stp x23, x24, [sp,#64]

0xffff8000104e43e0 《blk_update_request+24》: str x25, [sp,#80]

0xffff8000104e43e4 《blk_update_request+28》: mov x22, x0

0xffff8000104e43e8 《blk_update_request+32》: uxtb w24, w1

0xffff8000104e43ec 《blk_update_request+36》: mov w21, w2

0xffff8000104e43f0 《blk_update_request+40》: mov x0, x30

0xffff8000104e43f4 《blk_update_request+44》: nop

0xffff8000104e43f8 《blk_update_request+48》: mov w0, w24

0xffff8000104e43fc 《blk_update_request+52》: bl 0xffff8000104e14c4 《blk_status_to_errno》

內(nèi)核在start_kernel執(zhí)行時(shí),會(huì)調(diào)用ftrace_init,它會(huì)將所有可trace函數(shù)中的_mcount進(jìn)行替換,如上可以看出鏈接階段的 bl ffff80001002c36c 《_mcount》 已經(jīng)被替換為nop指令

5.2 設(shè)定trace函數(shù)blk_update_request

執(zhí)行如下命令來trace函數(shù)blk_update_request

ubuntu@VM-0-9-ubuntu:~$echo blk_update_request 》 /sys/kernel/debug/tracing/set_ftrace_filter

ubuntu@VM-0-9-ubuntu:~$echo function 》 /sys/kernel/debug/tracing/current_tracer

我們?cè)賮聿榭碽lk_update_request反匯編代碼

(gdb) x/20i blk_update_request

0xffff8000104e43c8 《blk_update_request》: sub sp, sp, #0x60

0xffff8000104e43cc 《blk_update_request+4》: stp x29, x30, [sp,#16]

0xffff8000104e43d0 《blk_update_request+8》: add x29, sp, #0x10

0xffff8000104e43d4 《blk_update_request+12》: stp x19, x20, [sp,#32]

0xffff8000104e43d8 《blk_update_request+16》: stp x21, x22, [sp,#48]

0xffff8000104e43dc 《blk_update_request+20》: stp x23, x24, [sp,#64]

0xffff8000104e43e0 《blk_update_request+24》: str x25, [sp,#80]

0xffff8000104e43e4 《blk_update_request+28》: mov x22, x0

0xffff8000104e43e8 《blk_update_request+32》: uxtb w24, w1

0xffff8000104e43ec 《blk_update_request+36》: mov w21, w2

0xffff8000104e43f0 《blk_update_request+40》: mov x0, x30

0xffff8000104e43f4 《blk_update_request+44》: bl 0xffff80001002c370 《ftrace_caller》

0xffff8000104e43f8 《blk_update_request+48》: mov w0, w24

0xffff8000104e43fc 《blk_update_request+52》: bl 0xffff8000104e14c4 《blk_status_to_errno》

可以看到之前在blk_update_request的nop指令被替換成

bl 0xffff80001002c370 《ftrace_caller》

繼續(xù)反匯編ftrace_caller得到如下的匯編代碼:

(gdb) disassemble ftrace_caller

Dump of assembler code for function ftrace_caller:

0xffff80001002c374 《+0》: stp x29, x30, [sp,#-16]!

0xffff80001002c378 《+4》: mov x29, sp

// x30是blk_update_request的lr,-4是當(dāng)前執(zhí)行函數(shù)的入口地址,也就是ftrace_caller的ip

// 它將作為參數(shù)0傳遞給ftrace_ops_no_ops

0xffff80001002c37c 《+8》: sub x0, x30, #0x4

// 參考前面arm64棧幀結(jié)構(gòu),x29指向上一級(jí)函數(shù)blk_update_request棧頂

//[x29]指向blk_mq_end_request函數(shù)的棧頂

//[[x29]+8]為blk_mq_end_request的ip(實(shí)際是ip的下條指令)

0xffff80001002c380 《+12》: ldr x1, [x29]

0xffff80001002c384 《+16》: ldr x1, [x1,#8]

0xffff80001002c388 《+20》: bl 0xffff800010188ffc 《ftrace_ops_no_ops》

0xffff80001002c38c 《+24》: nop

0xffff80001002c390 《+28》: ldp x29, x30, [sp],#16

0xffff80001002c394 《+32》: ret

End of assembler dump.

可以看到ftrace_caller會(huì)調(diào)用ftrace_ops_no_ops,我們?cè)趂trace_ops_no_ops源碼中看到它會(huì)遍歷ftrace_ops_list鏈表,并執(zhí)行這個(gè)鏈表上的回調(diào)函數(shù),這里看下ftrace_ops_list上都鏈接了哪些func

(gdb) p *ftrace_ops_list

$4 = {

func = 0xffff8000101a0b1c 《function_trace_call》, //ftrace_ops_list鏈表唯一func

next = 0xffff800011c5a438 《ftrace_list_end》, //說明ftrace_ops_list鏈表只有一個(gè)func

flags = 8273,

private = 0xffff800011cf94e8 《global_trace》,

saved_func = 0xffff8000101a0b1c 《function_trace_call》,

local_hash = {

notrace_hash = 0xffff800010cf7118 《empty_hash》,

filter_hash = 0xffff00000720af80,

regex_lock = {

owner = {

counter = 0

},

......

從ftrace_ops_list鏈表中可以看到只有一個(gè)function_trace_call函數(shù)組成,因此可以說ftrace_caller最終會(huì)調(diào)用到function_trace_call。

通過前面的分析,我們一步步找到了blk_update_request的鉤子函數(shù)function_trace_call,其函數(shù)原型如下,其中參數(shù)ip指向ftrace_caller,參數(shù)parent_ip指向blk_mq_end_request:

staticvoid

function_trace_call(unsignedlong ip, unsignedlong parent_ip,

struct ftrace_ops *op, struct pt_regs *pt_regs)

下一節(jié)我們將追蹤鉤子函數(shù)的構(gòu)造以及替換過程。

6. 鉤子函數(shù)的替換過程

前面我們看到blk_update_request的nop指令被替換成bl ftrace_caller,那么此處的ftrace_caller是在哪里定義的呢?我們可以看到arch/arm64/kernel/entry-ftrace.S有如下的定義:

/*

* void ftrace_caller(unsigned long return_address)

* @return_address: return address to instrumented function

*

* This function is a counterpart of _mcount() in ‘static’ ftrace, and

* makes calls to:

* - tracer function to probe instrumented function‘s entry,

* - ftrace_graph_caller to set up an exit hook

*/

SYM_FUNC_START(ftrace_caller)

mcount_enter

mcount_get_pc0 x0 // function’s pc

mcount_get_lr x1 // function‘s lr

SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL) // tracer(pc, lr);

nop // This will be replaced with “bl xxx”

// where xxx can be any kind of tracer.

#ifdef CONFIG_FUNCTION_GRAPH_TRACER

SYM_INNER_LABEL(ftrace_graph_call, SYM_L_GLOBAL) // ftrace_graph_caller();

nop // If enabled, this will be replaced

// “b ftrace_graph_caller”

#endif

mcount_exit

SYM_FUNC_END(ftrace_caller)

通過 gdb可以看到ftrace_caller的反匯編代碼如下:

(gdb) disassemble ftrace_caller

Dump of assembler code for function ftrace_caller:

0xffff80001002c370 《+0》: stp x29, x30, [sp,#-16]!

0xffff80001002c374 《+4》: mov x29, sp

0xffff80001002c378 《+8》: sub x0, x30, #0x4

0xffff80001002c37c 《+12》: ldr x1, [x29]

0xffff80001002c380 《+16》: ldr x1, [x1,#8]

0xffff80001002c384 《+20》: nop /*ftrace_call*/

0xffff80001002c388 《+24》: nop /*ftrace_graph_call,暫不討論*/

0xffff80001002c38c 《+28》: ldp x29, x30, [sp],#16

0xffff80001002c390 《+32》: ret

End of assembler dump.

當(dāng)執(zhí)行echo blk_update_request 》set_ftrace_filter時(shí)相當(dāng)于使能了blk_update_request的鉤子替換標(biāo)志,當(dāng)執(zhí)行echo function 》current_tracer時(shí)會(huì)檢查這個(gè)標(biāo)志,并執(zhí)行替換,它會(huì)產(chǎn)生如下的調(diào)用鏈:

/sys/kernel/debug/tracing # echo function 》 current_tracer

[ 45.632002] CPU: 0 PID: 111 Comm: sh Not tainted 5.10.0-dirty #35

[ 45.632457] Hardware name: linux,dummy-virt (DT)

[ 45.632697] Call trace:

[ 45.632981] dump_backtrace+0x0/0x1f8

[ 45.633169] show_stack+0x2c/0x7c

[ 45.634039] ftrace_modify_all_code+0x38/0x118

[ 45.634269] arch_ftrace_update_code+0x10/0x18

[ 45.634495] ftrace_run_update_code+0x2c/0x48

[ 45.634727] ftrace_startup_enable+0x40/0x4c

[ 45.634943] ftrace_startup+0xec/0x11c

[ 45.635137] register_ftrace_function+0x68/0x84

[ 45.635369] function_trace_init+0xa0/0xc4

[ 45.635574] tracer_init+0x28/0x34

[ 45.635768] tracing_set_tracer+0x11c/0x17c

[ 45.635982] tracing_set_trace_write+0x124/0x170

[ 45.636224] vfs_write+0x16c/0x368

[ 45.636409] ksys_write+0x74/0x10c

[ 45.636594] __arm64_sys_write+0x28/0x34

[ 45.636923] el0_svc_common+0xf0/0x174

[ 45.637138] do_el0_svc+0x84/0x90

[ 45.637330] el0_svc+0x1c/0x28

[ 45.637510] el0_sync_handler+0x3c/0xac

[ 45.637721] el0_sync+0x140/0x180

進(jìn)一步查看ftrace_modify_all_code的代碼,我們可以看到如下的調(diào)用流程:

ftrace_modify_all_code(command)

--ftrace_update_ftrace_func(ftrace_ops_list_func)

|--pc = (unsignedlong)&ftrace_call

| //此處ftrace_ops_list_func為ftrace_ops_no_ops,

| //因此會(huì)返回bl ftrace_ops_no_ops給new*/

|--new = aarch64_insn_gen_branch_imm(pc, (unsignedlong)ftrace_ops_list_func,

| AARCH64_INSN_BRANCH_LINK);

--ftrace_modify_code(pc, 0, new, false)

如上,ftrace_modify_code通過修改text段,將指令ftrace_call替換為bl ftrace_ops_no_ops,此處是第一次替換;

ftrace_modify_all_code(command)

--ftrace_replace_code(mod_flags | FTRACE_MODIFY_ENABLE_FL);

--do_for_each_ftrace_rec(pg, rec) {

__ftrace_replace_code(rec, enable);

} while_for_each_ftrace_rec();

如上,會(huì)遍歷每一個(gè)可trace的函數(shù),對(duì)于使能了替換標(biāo)記的函數(shù),將其nop替換為bl ftrace_caller,此處是第二次替換,ftrace_caller也就是我們所認(rèn)為的鉤子函數(shù)。

7.總結(jié)

到此我們已經(jīng)分析完了ftrace的各個(gè)階段的行為,以及鉤子函數(shù)的替換過程,基本上包含如下過程:

1. 編譯階段。通過編譯選項(xiàng) -pg -mrecord-mcount 在每個(gè)支持ftrace的函數(shù)中插入bl 0 《_mcount》指令

2. 鏈接階段。會(huì)根據(jù)重定位段將bl 0 《_mcount》指令地址重定位為_mcount函數(shù)地址。

3. 運(yùn)行階段 (1)ftrace_init:會(huì)將可trace函數(shù)中的bl _mcount替換為nop指令;(2)執(zhí)行echo blk_update_request 》set_ftrace_filter:會(huì)使能blk_update_request的鉤子函數(shù)替換標(biāo)記(nop替換為ftrace_caller); (3)執(zhí)行echofunction 》 current_tracer:觸發(fā)兩步替換:第一步,ftrace_caller中ftrace_call被替換為ftrace_ops_no_ops;第二步,blk_update_request中的nop被替換為ftrace_caller。ftrace_caller最終會(huì)調(diào)用到function_trace_call,它會(huì)記錄函數(shù)調(diào)用堆棧信息,并將結(jié)果寫入 ring buffer,用戶可以通過/sys/kernel/debug/tracing/trace文件讀取該 ring buffer 中的內(nèi)容。

最后,給出一個(gè)通過ftrace跟蹤dd寫入操作的例子,腳本為ftrace.sh

#!/bin/bash

debugfs=/sys/kernel/debug

echo nop 》 $debugfs/tracing/current_tracer

echo 0 》 $debugfs/tracing/tracing_on

echo $$ 》 $debugfs/tracing/set_ftrace_pid

echo function 》 $debugfs/tracing/current_tracer

#replace test_proc_show by your function name

echo ksys_write 》 $debugfs/tracing/set_ftrace_filter

echo 1 》 $debugfs/tracing/tracing_on

exec “$@”

ubuntu@VM-0-9-ubuntu:$ 。/ftrace.sh dd if=/dev/zero of=test bs=512 count=1048576

執(zhí)行結(jié)果:

root@VM-0-9-ubuntu:# cat /sys//kernel/debug/tracing/trace

# tracer: function

#

# entries-in-buffer/entries-written: 102454/1048579 #P:2

#

# _-----=》 irqs-off

# / _----=》 need-resched

# | / _---=》 hardirq/softirq

# || / _--=》 preempt-depth

# ||| / delay

# TASK-PID CPU# |||| TIMESTAMP FUNCTION

# | | | |||| | |

dd-32307 [000] .... 1380661.568624: vfs_write 《-SyS_write

dd-32307 [000] .... 1380661.568626: vfs_write 《-SyS_write

dd-32307 [000] .... 1380661.568630: vfs_write 《-SyS_write

dd-32307 [000] .... 1380661.568632: vfs_write 《-SyS_write

......

責(zé)任編輯:haq

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

    關(guān)注

    87

    文章

    11329

    瀏覽量

    209967

原文標(biāo)題:ftrace學(xué)習(xí)筆記

文章出處:【微信號(hào):gh_6fde77c41971,微信公眾號(hào):FPGA干貨】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    騰訊云內(nèi)核團(tuán)隊(duì)修復(fù)Linux關(guān)鍵Bug

    騰訊云操作系統(tǒng)(Tencent OS)內(nèi)核團(tuán)隊(duì)近日在Linux社區(qū)取得了顯著成果。他們提交的兩項(xiàng)改進(jìn)方案,成功解決了自2021年以來一直困擾眾多一線廠商,并在近期讓多個(gè)Linux頂級(jí)
    的頭像 發(fā)表于 12-31 10:58 ?222次閱讀

    嵌入式學(xué)習(xí)-飛凌嵌入式ElfBoard ELF 1板卡-Linux內(nèi)核移植之內(nèi)核簡(jiǎn)介

    學(xué)到本章節(jié),大家應(yīng)該對(duì)Linux操作系統(tǒng)都有了一定的了解,但可能還不知道我們拿到手的內(nèi)核源碼都經(jīng)歷了什么。linux有一個(gè)龐大的開源社區(qū),每個(gè)人都可以向開源社區(qū)提交代碼。由于linux
    發(fā)表于 12-16 13:08

    飛凌嵌入式ElfBoard ELF 1板卡-Linux內(nèi)核移植之內(nèi)核簡(jiǎn)介

    學(xué)到本章節(jié),大家應(yīng)該對(duì)Linux操作系統(tǒng)都有了一定的了解,但可能還不知道我們拿到手的內(nèi)核源碼都經(jīng)歷了什么。linux有一個(gè)龐大的開源社區(qū),每個(gè)人都可以向開源社區(qū)提交代碼。由于linux
    發(fā)表于 12-13 09:03

    deepin社區(qū)亮相第19屆中國Linux內(nèi)核開發(fā)者大會(huì)

    中國 Linux 內(nèi)核開發(fā)者大會(huì),作為中國 Linux 內(nèi)核領(lǐng)域最具影響力的峰會(huì)之一,一直以來都備受矚目。
    的頭像 發(fā)表于 10-29 16:35 ?542次閱讀

    linux內(nèi)核中通用HID觸摸驅(qū)動(dòng)

    linux內(nèi)核中,為HID觸摸面板實(shí)現(xiàn)了一個(gè)通用的驅(qū)動(dòng)程序,位于/drivers/hid/hid-multitouch.c文件中。hid觸摸驅(qū)動(dòng)是以struct hid_driver實(shí)現(xiàn),首先定義一個(gè)描述hid觸摸驅(qū)動(dòng)的結(jié)構(gòu)mt_driver。
    的頭像 發(fā)表于 10-29 10:55 ?842次閱讀
    <b class='flag-5'>linux</b><b class='flag-5'>內(nèi)核</b>中通用HID觸摸驅(qū)動(dòng)

    詳解linux內(nèi)核的uevent機(jī)制

    linux內(nèi)核中,uevent機(jī)制是一種內(nèi)核和用戶空間通信的機(jī)制,用于通知用戶空間應(yīng)用程序各種硬件更改或其他事件,比如插入或移除硬件設(shè)備(如USB驅(qū)動(dòng)器或網(wǎng)絡(luò)接口)。uevent表示“用戶空間
    的頭像 發(fā)表于 09-29 17:01 ?840次閱讀

    linux驅(qū)動(dòng)程序如何加載進(jìn)內(nèi)核

    Linux系統(tǒng)中,驅(qū)動(dòng)程序是內(nèi)核與硬件設(shè)備之間的橋梁。它們?cè)试S內(nèi)核與硬件設(shè)備進(jìn)行通信,從而實(shí)現(xiàn)對(duì)硬件設(shè)備的控制和管理。 驅(qū)動(dòng)程序的編寫 驅(qū)動(dòng)程序的編寫是Linux驅(qū)動(dòng)開發(fā)的基礎(chǔ)。在編
    的頭像 發(fā)表于 08-30 15:02 ?532次閱讀

    Linux內(nèi)核測(cè)試技術(shù)

    Linux 內(nèi)核Linux操作系統(tǒng)的核心部分,負(fù)責(zé)管理硬件資源和提供系統(tǒng)調(diào)用接口。隨著 Linux 內(nèi)核的不斷發(fā)展和更新,其復(fù)雜性和代碼規(guī)
    的頭像 發(fā)表于 08-13 13:42 ?536次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>測(cè)試技術(shù)

    Linux內(nèi)核中的頁面分配機(jī)制

    Linux內(nèi)核中是如何分配出頁面的,如果我們站在CPU的角度去看這個(gè)問題,CPU能分配出來的頁面是以物理頁面為單位的。也就是我們計(jì)算機(jī)中常講的分頁機(jī)制。本文就看下Linux內(nèi)核是如何管
    的頭像 發(fā)表于 08-07 15:51 ?321次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>中的頁面分配機(jī)制

    歡創(chuàng)播報(bào) 華為宣布鴻蒙內(nèi)核已超越Linux內(nèi)核

    1 華為宣布鴻蒙內(nèi)核已超越Linux內(nèi)核 ? 6月21日,在華為開發(fā)者大會(huì)上, HarmonyOS NEXT(鴻蒙NEXT)——真正獨(dú)立于安卓和iOS的鴻蒙操作系統(tǒng),正式登場(chǎng)。這是HarmonyOS
    的頭像 發(fā)表于 06-27 11:30 ?874次閱讀

    QNX與Linux基礎(chǔ)差異對(duì)比

    對(duì)于QNX系統(tǒng)和Linux系統(tǒng)的內(nèi)核差異,我們拋開宏內(nèi)核、微內(nèi)核之類的爭(zhēng)議不談。單純從開發(fā)應(yīng)用的角度而言,QNX和Linux系統(tǒng)的差異到底有
    發(fā)表于 04-17 10:52 ?849次閱讀

    使用 PREEMPT_RT 在 Ubuntu 中構(gòu)建實(shí)時(shí) Linux 內(nèi)核

    盟通技術(shù)干貨構(gòu)建實(shí)時(shí)Linux內(nèi)核簡(jiǎn)介盟通技術(shù)干貨Motrotech如果需要在Linux中實(shí)現(xiàn)實(shí)時(shí)計(jì)算性能,進(jìn)而有效地將Linux轉(zhuǎn)變?yōu)镽TOS,那么大多數(shù)發(fā)行版都可以打上名為PREE
    的頭像 發(fā)表于 04-12 08:36 ?2641次閱讀
    使用 PREEMPT_RT 在 Ubuntu 中構(gòu)建實(shí)時(shí) <b class='flag-5'>Linux</b> <b class='flag-5'>內(nèi)核</b>

    C++在Linux內(nèi)核開發(fā)中從爭(zhēng)議到成熟

    Linux 內(nèi)核郵件列表中一篇已有六年歷史的老帖近日再次引發(fā)激烈討論 —— 主題是建議將 Linux 內(nèi)核的開發(fā)語言從 C 轉(zhuǎn)換為更現(xiàn)代的 C++。
    的頭像 發(fā)表于 01-31 14:11 ?655次閱讀
    C++在<b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>開發(fā)中從爭(zhēng)議到成熟

    Ubuntu 24.04 LTS選用Linux 6.8為默認(rèn)內(nèi)核

    關(guān)于Ubuntu 24.04 LTS使用何種內(nèi)核版本,一直備受關(guān)注。Canonical工程師Andrea Righi昨日宣布,Ubuntu 24.04將默認(rèn)搭載Linux 6.8內(nèi)核
    的頭像 發(fā)表于 01-29 11:27 ?1180次閱讀

    linux內(nèi)核主要由哪幾個(gè)部分組成,作用是什么

    Linux內(nèi)核主要由以下幾個(gè)部分組成: 進(jìn)程管理:Linux內(nèi)核負(fù)責(zé)管理和調(diào)度系統(tǒng)中的進(jìn)程。它通過進(jìn)程調(diào)度算法來決定哪個(gè)進(jìn)程在什么時(shí)間運(yùn)行以及如何分配系統(tǒng)資源。 內(nèi)存管理:
    的頭像 發(fā)表于 01-22 14:34 ?2747次閱讀
    主站蜘蛛池模板: 国产视频分类| 啪啪免费看| 午夜合集| 高清一区二区三区四区五区| 国产在线啪| 美女扒开尿口给男人看的让 | 国产视频二区| www.五月婷婷.com| 天天综合天天色| 久久福利影视| 国产h在线观看| re99热| 中文字幕亚洲一区二区va在线 | 天天色综| 伊人狼人综合网| 天天拍夜夜添久久精品免费| 精品国产理论在线观看不卡| 美国69bj| 中国美女毛片| 四虎4hu| 性 色 黄 一级| 日本黄色高清视频网站| 色婷婷六月丁香在线观看| 性夜影院午夜看片| 日韩美a一级毛片| 色噜噜狠狠狠色综合久| 欧美成人生活片| xxxxxx日本人免费| 91在线电影| 人人干视频在线观看| 神马午夜影院| 网站黄色在线观看| 69精品在线观看| 欧洲妇女成人淫片aaa视频| 成人淫片| 国产伦一区二区三区免费| 午夜精品久久久久久| 特黄特色的视频免费播放| 黄色日本视频网站| 手机在线看福利| 婷婷激情久久|