簡(jiǎn)介
Ftrace是Linux Kernel的官方tracing系統(tǒng),支持Function trace、靜態(tài)tracepoint、動(dòng)態(tài)Tracepoint的跟蹤,還提供各種Tracer,用于統(tǒng)計(jì)最大irq延遲、最大函數(shù)調(diào)用棧大小、調(diào)度事件等。
Ftrace還提供了強(qiáng)大的過(guò)濾、快照snapshot、實(shí)例(instance)等功能,可以靈活配置。
內(nèi)核配置Ftrace后,如果功能不打開(kāi),對(duì)性能幾乎沒(méi)有影響。打開(kāi)事件記錄后,由于是在percpu buffer中記錄log,各CPU無(wú)需同步,引入的負(fù)載不大,非常適合在性能敏感的場(chǎng)景中使用。
相比kernle的log_buf和dynamic_debug機(jī)制,F(xiàn)trace的buffer大小可以靈活配置,可以生成快照,也有一定的優(yōu)勢(shì)。
ftrace 框架
整個(gè)ftrace框架可以分為幾部分:ftrace核心框架,RingBuffer,debugfs,Tracepoint,各種Tracer。
ftrace框架是整個(gè)ftrace功能的紐帶,包括對(duì)內(nèi)核的修改,Tracer的注冊(cè),RingBuffer的控制等等。
RingBuffer是靜態(tài)動(dòng)態(tài)ftrace的載體。
debugfs則提供了用戶空間對(duì)ftrace設(shè)置接口。
Tracepoint是靜態(tài)trace,他需要提前編譯進(jìn)內(nèi)核;可以定制打印內(nèi)容,自由添加;并且內(nèi)核對(duì)主要subsystem提供了Tracepoint。
Tracer有很多種,主要幾大類:
函數(shù)類:function, function_graph, stack
延時(shí)類:irqsoff, preemptoff, preemptirqsoff, wakeup, wakeup_rt, waktup_dl
其他類:nop, mmiotrace, blk
Trace文件系統(tǒng)
配置內(nèi)核支持ftrace需要開(kāi)啟以下宏定義。
CONFIG_FTRACE=y CONFIG_STACK_TRACER=y CONFIG_FUNCTION_TRACER=y CONFIG_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_IRQSOFF_TRACER=y CONFIG_SCHED_TRACER=y CONFIG_FTRACE_SYSCALLS=y CONFIG_PREEMPTIRQ_EVENTS=y CONFIG_TRACER_SNAPSHOT=y
Ftrace使用tracefs文件系統(tǒng)去保存控制文件和顯示輸出的文件。
當(dāng)tracefs被配置進(jìn)內(nèi)核時(shí),目錄/sys/kernel/tracing將會(huì)被創(chuàng)建。為了掛載這個(gè)目錄,你可以在/etc/fstab文件中添加以下信息:
tracefs/sys/kernel/tracingtracefsdefaults00
或者在運(yùn)行時(shí)掛在:
mount-ttracefsnodev/sys/kernel/tracing
為了快速訪問(wèn)這個(gè)目錄可以創(chuàng)建一個(gè)軟鏈接::
ln-s/sys/kernel/tracing/tracing
注意:
在4.1版本之前,所有的ftrace跟蹤控制文件都在debugfs文件系統(tǒng)中,該文件系統(tǒng)通常位于/sys/kernel/debug/tracing。
為了向后兼容,當(dāng)掛載debugfs文件系統(tǒng)時(shí),tracefs文件系統(tǒng)將自動(dòng)掛載在/sys/kernel/debug/tracing。位于tracefs文件系統(tǒng)中的所有文件也將位于debugfs文件系統(tǒng)目錄中。
任何選定的ftrace選項(xiàng)也將創(chuàng)建tracefs文件系統(tǒng)。文檔中的操作都在ftrace的目錄中(/sys/kernel/tracing或者/sys/kernel/debug/tracing)。
在mount tracefs后,即可訪問(wèn)ftrace的控制和輸出文件。以下是一些關(guān)鍵文件的列表:
root@firefly:/sys/kernel/debug/tracing#ls READMEkprobe_profileset_graph_function available_eventsmax_graph_depthset_graph_notrace available_filter_functionsoptionssnapshot available_tracersper_cputrace buffer_size_kbprintk_formatstrace_clock buffer_total_size_kbsaved_cmdlinestrace_marker current_tracersaved_cmdlines_sizetrace_options dyn_ftrace_total_infosaved_tgidstrace_pipe enabled_functionsset_eventtracing_cpumask eventsset_event_pidtracing_max_latency free_bufferset_ftrace_filtertracing_on instancesset_ftrace_notracetracing_thresh kprobe_eventsset_ftrace_pid
available_events
用于設(shè)置或顯示當(dāng)前使用的跟蹤器;使用 echo 將跟蹤器名字寫(xiě)入該文件可以切換到不同的跟蹤器。系統(tǒng)啟動(dòng)后,其缺省值為 nop ,即不做任何跟蹤操作。在執(zhí)行完一段跟蹤任務(wù)后,可以通過(guò)向該文件寫(xiě)入 nop 來(lái)重置跟蹤器。
available_filter_functions
記錄了當(dāng)前可以跟蹤的內(nèi)核函數(shù)。對(duì)于不在該文件中列出的函數(shù),無(wú)法跟蹤其活動(dòng)。
available_tracers
記錄了當(dāng)前編譯進(jìn)內(nèi)核的跟蹤器的列表,可以通過(guò) cat 查看其內(nèi)容;寫(xiě) current_tracer 文件時(shí)用到的跟蹤器名字必須在該文件列出的跟蹤器名字列表中。
buffer_size_kb
用于設(shè)置單個(gè) CPU 所使用的跟蹤緩存的大小。跟蹤器會(huì)將跟蹤到的信息寫(xiě)入緩存,每個(gè) CPU 的跟蹤緩存是一樣大的。跟蹤緩存實(shí)現(xiàn)為環(huán)形緩沖區(qū)的形式,如果跟蹤到的信息太多,則舊的信息會(huì)被新的跟蹤信息覆蓋掉。注意,要更改該文件的值需要先將 current_tracer 設(shè)置為 nop 才可以。
buffer_total_size_kb
顯示所有的跟蹤緩存大小,不同之處在于buffer_size_kb是單個(gè)CPU的,buffer_total_size_kb是所有CPU的和。
trace_pipe
輸出和trace一樣的內(nèi)容,輸出實(shí)時(shí)tracing日志,這樣就避免了RingBuffer的溢出。cat trace_pipe > trace.txt &保存文件,但是cat時(shí)候會(huì)帶來(lái)一些性能損耗。
trace_options
控制Trace打印內(nèi)容格式或者設(shè)置跟蹤器,可以通過(guò)trace_options添加很多附加信息。
current_tracer
設(shè)置和顯示當(dāng)前正在使用的跟蹤器。使用echo命令可以把跟蹤器的名字寫(xiě)入current_tracer文件,從而切換不同的跟蹤器。
dyn_ftrace_total_info
debug使用,顯示available_filter_functins中跟中函數(shù)的數(shù)目,兩者一致。
enabled_functions
顯示有回調(diào)附著的函數(shù)名稱。這個(gè)文件更多的是用于調(diào)試ftrace,但也可以用于查看是否有任何函數(shù)附加了回調(diào)。不僅ftrace框架使用ftrace函數(shù)tracing,其他子系統(tǒng)也可能使用。該文件顯示所有附加回調(diào)的函數(shù),以及附加回調(diào)的數(shù)量。注意,一個(gè)回調(diào)也可以調(diào)用多個(gè)函數(shù),這些函數(shù)不會(huì)在這個(gè)計(jì)數(shù)中列出。
如果回調(diào)被一個(gè)帶有"save regs"屬性的函數(shù)注冊(cè)tracing(這樣開(kāi)銷更大),一個(gè)’R’將顯示在與返回寄存器的函數(shù)的同一行上。
如果回調(diào)被一個(gè)帶有"ip modify"屬性的函數(shù)注冊(cè)tracing(這樣regs->ip就可以被修改),'I’將顯示在可以被覆蓋的函數(shù)的同一行上。
如果體系架構(gòu)支持,它還將顯示函數(shù)直接調(diào)用的回調(diào)。如果計(jì)數(shù)大于1,則很可能是ftrace_ops_list_func()。
如果函數(shù)的回調(diào)跳轉(zhuǎn)到特定于回調(diào)而不是標(biāo)準(zhǔn)的"跳轉(zhuǎn)點(diǎn)"的跳轉(zhuǎn)點(diǎn),它的地址將和跳轉(zhuǎn)點(diǎn)調(diào)用的函數(shù)一起打印。
events
系統(tǒng)Trace events目錄,在每個(gè)events下面都有enable、filter和fotmat。enable是開(kāi)關(guān);format是events的格式,然后根據(jù)格式設(shè)置 filter。
free_buffer
在關(guān)閉該文件時(shí),ring buffer將被調(diào)整為其最小大小。如果有一個(gè)tracing的進(jìn)程也打開(kāi)了這個(gè)文件,當(dāng)該進(jìn)程退出,該文件的描述符將被關(guān)閉,在此過(guò)程,ring bufer也將被"freed"。
如果options/disable_on_free選項(xiàng)被設(shè)置將會(huì)停止tracing。
kprobe_events
激活 dynamic trace opoints。參考內(nèi)核文檔Documentation/trace/kprobetrace.rst。
kprobe_profile
Dynamic trace points 統(tǒng)計(jì)信息。 參考內(nèi)核文檔Documentation/trace/kprobetrace.rst。
max_graph_depth
被用于function_graph tracer。這是tracing一個(gè)函數(shù)的最大深度。將其設(shè)置為1將只顯示從用戶空間調(diào)用的第一個(gè)內(nèi)核函數(shù)。
options
目錄文件,里面是每個(gè)trace options的文件,和trace_options對(duì)應(yīng),可以通過(guò)echo 0/1使能options。
per_cpu:包含跟蹤 per_cpu 信息的目錄。
per_cpu/cpu0/buffer_size_kb:配置per_cpu的buffer空間
per_cpu/cpu0/trace:當(dāng)前CPU的trace文件。
per_cpu/cpu0/trace_pipe:當(dāng)前CPU的trace_pipe文件。
per_cpu/cpu0/trace_pipe_raw:當(dāng)前CPU的trace_pipe_raw
per_cpu/cpu0/snapshot:當(dāng)前CPU的snapshot
per_cpu/cpu0/snapshot_raw:當(dāng)前CPU的snapshot_raw
per_cpu/cpu0/stats:當(dāng)前CPU的trace統(tǒng)計(jì)信息
printk_formats
提供給工具讀取原始格式trace的文件。如果環(huán)形緩沖區(qū)中的事件引用了一個(gè)字符串,則只有指向該字符串的指針被記錄到緩沖區(qū)中,而不是字符串本身。這可以防止工具知道該字符串是什么。該文件顯示字符串和字符串的地址,允許工具將指針映射到字符串的內(nèi)容。
saved_cmdlines
ftrace會(huì)存放pid的comms在一個(gè)pid mappings,在顯示event時(shí)候同時(shí)顯示comm,這里可以配置pid對(duì)應(yīng)的comm,如果配置,顯示類似
saved_cmdlines_size
saved_cmdlines的數(shù)目,默認(rèn)為128
saved_tgids
如果設(shè)置了選項(xiàng)“record-tgid”,則在每個(gè)調(diào)度上下文切換時(shí),任務(wù)的任務(wù)組 ID 將保存在將線程的 PID 映射到其 TGID 的表中。默認(rèn)情況下,“record-tgid”選項(xiàng)被禁用。
set_event
也可以在系統(tǒng)特定事件觸發(fā)的時(shí)候打開(kāi)跟蹤。為了啟用某個(gè)事件,你需要:echo sys_enter_nice >> set_event(注意你是將事件的名字追加到文件中去,使用>>追加定向器,不是>)。要禁用某個(gè)事件,需要在名字前加上一個(gè)“!”號(hào):echo '!sys_enter_nice' >> set_event。以下三種方式都可以啟用事件
echosched:sched_switch>>/debug/tracing/set_event echosched_switch>>/debug/tracing/set_event echo1>/debug/tracing/events/sched/sched_switch/enable
set_event_pid
tracer將只追蹤寫(xiě)入此文件PID的對(duì)應(yīng)進(jìn)程的event。"event-fork" option設(shè)置后,pid對(duì)應(yīng)進(jìn)程創(chuàng)建的子進(jìn)程event也會(huì)自動(dòng)跟蹤。
set_ftrace_filter 和 set_ftrace_notrace
在編譯內(nèi)核時(shí)配置了動(dòng)態(tài) ftrace (選中 CONFIG_DYNAMIC_FTRACE 選項(xiàng))后使用。前者用于顯示指定要跟蹤的函數(shù),后者則作用相反,用于指定不跟蹤的函數(shù)。
如果一個(gè)函數(shù)名同時(shí)出現(xiàn)在這兩個(gè)文件中,則這個(gè)函數(shù)的執(zhí)行狀況不會(huì)被跟蹤。這些文件還支持簡(jiǎn)單形式的含有通配符的表達(dá)式,這樣可以用一個(gè)表達(dá)式一次指定多個(gè)目標(biāo)函數(shù);注意,要寫(xiě)入這兩個(gè)文件的函數(shù)名必須可以在文件 available_filter_functions 中看到。
缺省為可以跟蹤所有內(nèi)核函數(shù),文件 set_ftrace_notrace 的值則為空。甚至可以對(duì)函數(shù)的名字使用通配符。例如,要用所有的vmalloc_函數(shù),通過(guò)echo vmalloc_* > set_ftrace_filter進(jìn)行設(shè)置。
set_ftrace_pid
tracer將只追蹤寫(xiě)入此文件PID的對(duì)應(yīng)的進(jìn)程。"function-fork" option設(shè)置后,pid對(duì)應(yīng)進(jìn)程創(chuàng)建的子進(jìn)程也會(huì)自動(dòng)跟蹤。
set_graph_function
設(shè)置要清晰顯示調(diào)用關(guān)系的函數(shù),顯示的信息結(jié)構(gòu)類似于 C 語(yǔ)言代碼,這樣在分析內(nèi)核運(yùn)作流程時(shí)會(huì)更加直觀一些。在使用 function_graph 跟蹤器時(shí)使用;缺省為對(duì)所有函數(shù)都生成調(diào)用關(guān)系序列,可以通過(guò)寫(xiě)該文件來(lái)指定需要特別關(guān)注的函數(shù)。
echofunction_graph>current_tracer echo__do_fault>set_graph_function//跟蹤__do_fault
snapshot
是對(duì)trace的snapshot。
echo 0清空緩存,并釋放對(duì)應(yīng)內(nèi)存。
echo 1進(jìn)行對(duì)當(dāng)前trace進(jìn)行snapshot,如沒(méi)有內(nèi)存則分配。
echo 2清空緩存,不釋放也不分配內(nèi)存。
trace
文件提供了查看獲取到的跟蹤信息的接口。可以通過(guò) cat 等命令查看該文件以查看跟蹤到的內(nèi)核活動(dòng)記錄,也可以將其內(nèi)容保存為記錄文件以備后續(xù)查看。
trace_clock
每當(dāng)一個(gè)事件被記錄到環(huán)形緩沖區(qū)中時(shí),都會(huì)添加一個(gè)“時(shí)間戳”。此標(biāo)記來(lái)自指定的時(shí)鐘。默認(rèn)情況下,ftrace 使用“本地”時(shí)鐘。本地時(shí)鐘可能與其他 CPU 上的本地時(shí)鐘不同步。
local:默認(rèn)時(shí)鐘,在每CPU中快速且精準(zhǔn),但是可能不會(huì)在各個(gè)CPU之間同步;
global:各CPU間同步,但是比local慢;
counter:并不是時(shí)鐘,而是一個(gè)原子計(jì)數(shù)器。數(shù)值一直+1,但是所有cpu是同步的。主要用處是分析不同cpu發(fā)生的events
uptime:time stamp和jiffies counter根據(jù)boot time;
perf:clock跟perf使用一致。
x86-tsc:非系統(tǒng)自己時(shí)鐘。比如x86有TSC cycle clock;
ppc-tb:使用powerpc的基礎(chǔ)時(shí)鐘寄存器值;
mono:使用fast monotonic clock (CLOCK_MONOTONIC)
mono_raw:使用raw monotonic clock (CLOCK_MONOTONIC_RAW)
boot:使用boot clock (CLOCK_BOOTTIME)。
trace_marker
用于將用戶空間與內(nèi)核空間中發(fā)生的事件同步。將字符串寫(xiě)入該文件將被寫(xiě)入ftrace緩沖區(qū)。
在應(yīng)用程序中,應(yīng)用程序開(kāi)始打開(kāi)這個(gè)文件并引用文件描述符::
voidtrace_write(constchar*fmt,...) { va_listap; charbuf[256]; intn; if(trace_fd0) ??return; ?va_start(ap,?fmt); ?n?=?vsnprintf(buf,?256,?fmt,?ap); ?va_end(ap); ?write(trace_fd,?buf,?n); }
開(kāi)始:
trace_fd=open("trace_marker",WR_ONLY);
注意:寫(xiě)入trace_marker文件也可以觸發(fā)寫(xiě)入/sys/kernel/tracing/events/ftrace/print/trigger的觸發(fā)器。詳細(xì)看內(nèi)核文檔Documentation/trace/histogram.rst (Section 3.)。
trace_options
此文件允許用戶控制在上述輸出文件之一中顯示的數(shù)據(jù)量。還存在用于修改跟蹤器或事件的工作方式(堆棧跟蹤、時(shí)間戳等)的選項(xiàng)。
trace_pipe:"trace_pipe"輸出與"trace"文件相同的內(nèi)容,但是對(duì)跟蹤的影響不同。每次從"trace_pipe"讀取都會(huì)被消耗。這意味著后續(xù)的讀取將有所不同。跟蹤是動(dòng)態(tài)的:
#echofunction>current_tracer #cattrace_pipe>/tmp/trace.out& [1]4153 #echo1>tracing_on #usleep1 #echo0>tracing_on #cattrace #tracer:function # #entries-in-buffer/entries-written:0/0#P:4 # #_-----=>irqs-off #/_----=>need-resched #|/_---=>hardirq/softirq #||/_--=>preempt-depth #|||/delay #TASK-PIDCPU#||||TIMESTAMPFUNCTION #||||||||| # #cat/tmp/trace.out bash-1994[000]....5281.568961:mutex_unlock<-rb_simple_write ?????????????bash-1994??[000]?....??5281.568963:?__mutex_unlock_slowpath?<-mutex_unlock ?????????????bash-1994??[000]?....??5281.568963:?__fsnotify_parent?<-fsnotify_modify ?????????????bash-1994??[000]?....??5281.568964:?fsnotify?<-fsnotify_modify ?????????????bash-1994??[000]?....??5281.568964:?__srcu_read_lock?<-fsnotify ?????????????bash-1994??[000]?....??5281.568964:?add_preempt_count?<-__srcu_read_lock ?????????????bash-1994??[000]?...1??5281.568965:?sub_preempt_count?<-__srcu_read_lock ?????????????bash-1994??[000]?....??5281.568965:?__srcu_read_unlock?<-fsnotify ?????????????bash-1994??[000]?....??5281.568967:?sys_dup2?<-system_call_fastpath
注意,讀取"trace_pipe"文件將會(huì)阻塞,直到添加更多輸入。這與"trace"文件相反。如果任何進(jìn)程打開(kāi)"trace"文件進(jìn)行讀取,它實(shí)際上將禁用tracing并阻止添加新條目。"trace_pipe"文件沒(méi)有這個(gè)限制。
tracing_cpumask
可以通過(guò)此文件設(shè)置跟蹤指定CPU,二進(jìn)制格式。
tracing_max_latency
記錄某些Tracer的最大延時(shí)。比如interrupts的最大延時(shí)關(guān)閉后,會(huì)記錄在這里。可以echo值到此文件,然后遇到比設(shè)置值更大的延遲才會(huì)更新。
tracing_on
用于控制跟蹤的暫停。有時(shí)候在觀察到某些事件時(shí)想暫時(shí)關(guān)閉跟蹤,可以將 0 寫(xiě)入該文件以停止跟蹤,這樣跟蹤緩沖區(qū)中比較新的部分是與所關(guān)注的事件相關(guān)的;寫(xiě)入 1 可以繼續(xù)跟蹤。
tracing_thresh
延時(shí)記錄Trace的閾值,當(dāng)延時(shí)超過(guò)此值時(shí)才開(kāi)始記錄Trace。單位是ms,只有非0才起作用。
跟蹤器使用方法
blk跟蹤器
blktrace應(yīng)用程序使用的跟蹤程序。
blk tracer比較特別,需要設(shè)置/sys/block/xxx/trace/enable 才工作,可參考https://lwn.net/Articles/315508/
echo1>/sys/block/mmcblk0/trace/enable echoblk>/sys/kernel/debug/tracing/current_tracer echo1>/sys/kernel/debug/tracing/tracing_on cat/sys/kernel/debug/tracing/trace #tracer:blk # jbd2/mmcblk0p9--1100[001]...1679.901410:179,0AWS323710+8<-?(179,9)?265048 ?jbd2/mmcblk0p9--1100??[001]?...1???679.901428:?179,0????Q??WS?323710?+?8?[jbd2/mmcblk0p9-] ?jbd2/mmcblk0p9--1100??[001]?...1???679.901469:?179,0????G??WS?323710?+?8?[jbd2/mmcblk0p9-] ?jbd2/mmcblk0p9--1100??[001]?...1???679.901474:?179,0????P???N?[jbd2/mmcblk0p9-] ?jbd2/mmcblk0p9--1100??[001]?...1???679.901491:?179,0????A??WS?323718?+?8?<-?(179,9)?265056 ?????????mmcqd/0-998???[000]?...1???679.901627:?179,0????m???N?cfq1100SN?dispatch_insert ?????????mmcqd/0-998???[000]?...1???679.901635:?179,0????m???N?cfq1100SN?dispatched?a?request ?????????mmcqd/0-998???[000]?...1???679.901641:?179,0????m???N?cfq1100SN?activate?rq,?drv=1 ?????????mmcqd/0-998???[000]?...2???679.901645:?179,0????D??WS?323710?+?16?[mmcqd/0] ?????????mmcqd/0-998???[000]?...1???679.902979:?179,0????C??WS?323710?+?16?[0]
function跟蹤器
追蹤所有的內(nèi)核函數(shù)
查看可追蹤的內(nèi)核函數(shù)
root@firefly:~#cd/sys/kernel/debug/tracing/ root@firefly:/sys/kernel/debug/tracing#catavailable_filter_functions
顯示和配置當(dāng)前的tracer
catavailable_tracers blkfunction_graphwakeup_dlwakeup_rtwakeupirqsofffunctionnop catcurrent_tracer nop echofunction>current_tracer echodo_sys_open>set_ftrace_filter echo1>tracing_on echo0>tracing_on cattrace echonop>current_tracer echo>set_ftrace_filter
輸出
11/11
跟蹤條目11個(gè)
#P16
表示當(dāng)前系統(tǒng)可用的CPU有16個(gè)
TASK-PID
進(jìn)程名字-PID
CPU#
進(jìn)程運(yùn)行在那個(gè)CPU上
irqs-off
中斷開(kāi)關(guān)狀態(tài)
need-resched
可以設(shè)置為以下值
N:表示進(jìn)程設(shè)置了TIF_NEED_RESCHED和PREEMPT_NEED_RESCHED標(biāo)志位,說(shuō)明需要被調(diào)度。
n:表示進(jìn)程僅設(shè)置了TIF_NEED_RESCHED標(biāo)志
p:表示進(jìn)程僅設(shè)置了PREEMPT_NEED_RESCHED標(biāo)志
.:表示不需要調(diào)度
hardirq/softirq
可以設(shè)置為以下值
H:表示在一次軟中斷中發(fā)生了硬件中斷
h:表示硬件中斷的發(fā)生
s:表示軟件中斷的發(fā)生
.:表示沒(méi)有中斷發(fā)生
preempt-depth
表示搶占關(guān)閉的嵌套層級(jí)
delay
用特殊符號(hào)表示延時(shí)時(shí)間
$:大于1s
@:大于100ms
*:大于10ms
#:大于1000us
?。捍笥?00us
+:大于10us
TIMESTATION
時(shí)間戳。如果打開(kāi)了latency-format選項(xiàng),表示相對(duì)時(shí)間,即從開(kāi)始跟蹤算起。否則,使用絕對(duì)時(shí)間。
FUNCTION
表示函數(shù)名稱
function_graph跟蹤器
和“function tracer”比較類似,但它除了探測(cè)函數(shù)的入口還探測(cè)函數(shù)的出口。它可以畫(huà)出一個(gè)圖形化的函數(shù)調(diào)用,類似于c源代碼風(fēng)格。
echofunction_graph>current_tracer echodo_sys_open>set_graph_function echo1>tracing_on echo0>tracing_on cattrace echonop>current_tracer echo>set_graph_function
function_graph 和function跟蹤器在Linux version 4.4.194的開(kāi)發(fā)板上發(fā)現(xiàn)無(wú)法生效,給set_graph_function echo 特定函數(shù)后,仍會(huì)跟蹤所有函數(shù)。但是在Linux version 5.4.0-135 ubuntu18.04中是生效的。不知道是不是內(nèi)核版本差異的原因?
irqsoff跟蹤器
當(dāng)關(guān)閉中斷時(shí),CPU 會(huì)延遲對(duì)設(shè)備的狀態(tài)變化做出反應(yīng),有時(shí)候這樣做會(huì)對(duì)系統(tǒng)性能造成比較大的影響。
irqsoff 跟蹤器可以對(duì)中斷被關(guān)閉的狀況進(jìn)行跟蹤,有助于發(fā)現(xiàn)導(dǎo)致較大延遲的代碼;
當(dāng)出現(xiàn)最大延遲時(shí),跟蹤器會(huì)記錄導(dǎo)致延遲的跟蹤信息,文件 tracing_max_latency 則記錄中斷被關(guān)閉的最大延時(shí),遇到比設(shè)置值更大的延遲才會(huì)更新。
echoirqsoff>current_tracer echo0>tracing_max_latency echo1>tracing_on echo0>tracing_on cattrace
latency表示當(dāng)前最大的中斷延時(shí)為372us,跟蹤條目總和為4個(gè)。
started at 和 ended at 顯示發(fā)生中斷的開(kāi)始函數(shù)和結(jié)束函數(shù)分別為run_timer_softirq。
latency顯示中斷延時(shí)為372us,但是在stack trace 顯示為306us,這是因?yàn)樵谟涗涀畲笱舆t信息時(shí)需要花費(fèi)一些時(shí)間。
其他參數(shù)說(shuō)明可參考function跟蹤器。
wakeup/wakeup_rt/wakeup_dl跟蹤器
wakeup:顯示進(jìn)程從woken到wake up的延時(shí),包括所有進(jìn)程。
wakeup_dl:顯示SCHED_DEADLINE類型調(diào)度延時(shí)。
wakeup_rt:顯示實(shí)時(shí)進(jìn)程的調(diào)度延時(shí)。
echowakeup>current_tracer echo0>tracing_max_latency echo1>tracing_on echo0>tracing_on cattrace
stack跟蹤器
內(nèi)核棧大小是有限的,為了跟蹤內(nèi)核棧的使用情況,可以使用ftrace stack trace。
使能跟蹤一段時(shí)間后,可以查看最大棧占用情況,stack_max_size這里打印的是最長(zhǎng)棧的size。而在stack_trace 中打印的是最長(zhǎng)棧的每個(gè)函數(shù)占用棧大小的情況,注意這里也只會(huì)記錄的最長(zhǎng)的棧情況。
echostack>current_tracer echodo_sys_open>stack_trace_filter echo1>/proc/sys/kernel/stack_tracer_enabled echo0>/proc/sys/kernel/stack_tracer_enabled catstack_max_size catstack_trace
488 表示堆棧大小為488字節(jié),其中el0_svc_naked使用了最大的??臻g360。
小結(jié)
總結(jié)下ftrace 跟蹤器的三步法為:1,設(shè)置tracer類型;2,設(shè)置tracer參數(shù);3,使能tracer
trace event 用法
ftrace中的跟蹤機(jī)制主要有兩種,分別是函數(shù)和跟蹤點(diǎn)。前者屬于簡(jiǎn)單操作,后者可以理解為L(zhǎng)inux內(nèi)核的占位符函數(shù)。
tracepoint可以輸出開(kāi)發(fā)者想要的參數(shù)、局部變量等信息。
跟蹤點(diǎn)的位置比較固定,一般為內(nèi)核開(kāi)發(fā)者添加,可以理解為C語(yǔ)言中的#if DEBUG部分。如果運(yùn)行時(shí)不開(kāi)啟DEBUG,不占用任何系統(tǒng)開(kāi)銷。
trace event使用方法
set_event接口
/sys/kernel/debug/tracing/available_events定義了當(dāng)前支持的trace event。
root@firefly:/sys/kernel/debug/tracing#catavailable_events raw_syscalls:sys_exit raw_syscalls:sys_enter ipi:ipi_exit ipi:ipi_entry ipi:ipi_raise emulation:instruction_emulation kvm:kvm_halt_poll_ns kvm:kvm_age_page kvm:kvm_fpu kvm:kvm_mmio kvm:kvm_ack_irq kvm:kvm_set_irq kvm:kvm_vcpu_wakeup kvm:kvm_userspace_exit kvm:kvm_toggle_cache .....
啟用特定event,如sched_wakeup,echo到 /sys/kernel/debug/tracing/set_event。例如:
echosched_wakeup>>/sys/kernel/debug/tracing/set_event
注意:需要使用>>,否則會(huì)首先disable所有的events。
關(guān)閉特定event,在echo event name到set_event之前設(shè)置一個(gè)!前綴,比如
echo'!sched_wakeup'>>/sys/kernel/debug/tracing/set_event
使能所有event,echo *:* or *:到set_event中:
echo*:*>set_event
關(guān)閉所有event,echo一個(gè)空行到set_event中
echo>set_event
events 通常以subsystems的形式展現(xiàn),例如ext4, irq, sched等等。一個(gè)完整的event name類似nfs4format。
subsystem name是可選的,但是它會(huì)顯示在available_events文件中。一個(gè)subsystem中所有的events可以通過(guò) :*語(yǔ)法來(lái)表示,
例如:enable所有的irq event:
echo'irq:*'>set_event
enable接口
所有有效的trace event同時(shí)會(huì)在/sys/kernel/debug/tracing/events/文件夾中列出。
enable event ‘sched_wakeup’:
echo1>/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable
disable:
echo0>/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable
enable sched subsystem中所有的events:
echo1>/sys/kernel/debug/tracing/events/sched/enable
enable所有的events:
echo1>/sys/kernel/debug/tracing/events/enable
當(dāng)讀enable文件時(shí),可能會(huì)有以下4種結(jié)果:
0-alleventsthisfileaffectsaredisabled 1-alleventsthisfileaffectsareenabled X-thereisamixtureofeventsenabledanddisabled ?-thisfiledoesnotaffectanyevent
為了早期啟動(dòng)時(shí)調(diào)試,可以使用以下boot選項(xiàng):
trace_event=[event-list]
event-list是逗號(hào)分隔的event列表。
event格式
每個(gè)trace event都有一個(gè)與它相關(guān)聯(lián)的format文件,該文件包含log event中每個(gè)字段的描述。這個(gè)信息用來(lái)解析二進(jìn)制的trace流,其中的字段也可以在event filter中找到對(duì)它的使用。
它還顯示用于在文本模式下打印事件的格式字符串,以及用于分析的事件名稱和ID。
每個(gè)event都有一系列通用的字段,全部都以common_作為前綴。其他的字段都需要在TRACE_EVENT()中定義。
format中的每個(gè)字段都有如下形式:
field:field-typefield-name;offset:N;size:N;
offset是字段在trace record中的offset,size是數(shù)據(jù)項(xiàng)的size,都是byte單位。
舉例, sched_wakeup event的format信息:
cat/sys/kernel/debug/tracing/events/sched/sched_wakeup/format name:sched_wakeup ID:60 format: field:unsignedshortcommon_type;offset:0;size:2; field:unsignedcharcommon_flags;offset:2;size:1; field:unsignedcharcommon_preempt_count;offset:3;size:1; field:intcommon_pid;offset:4;size:4; field:intcommon_tgid;offset:8;size:4; field:charcomm[TASK_COMM_LEN];offset:12;size:16; field:pid_tpid;offset:28;size:4; field:intprio;offset:32;size:4; field:intsuccess;offset:36;size:4; field:intcpu;offset:40;size:4; printfmt:"task%s:%d[%d]success=%d[%03d]",REC->comm,REC->pid, REC->prio,REC->success,REC->cpu
這個(gè)event包含10個(gè)字段,5個(gè)通用字段5個(gè)自定義字段。除了COMM是一個(gè)字符串,此事件的所有字段都是數(shù)字,這對(duì)于事件過(guò)濾非常重要。
event 過(guò)濾
trace event支持 filter expressions式的過(guò)濾。一旦trace event被記錄到trace buffer中,其字段就針對(duì)與該event類型相關(guān)聯(lián)的filter expressions進(jìn)行檢查。
如果event匹配filter將會(huì)被記錄,否則將會(huì)被丟棄。如果event沒(méi)有配置filter,那么在任何時(shí)刻都是匹配的,event默認(rèn)就是no filter配置。
語(yǔ)法
一個(gè)filter expression由多個(gè) predicates組成,使用邏輯操作符&&、||組合在一起。
field-namerelational-operatorvalue
數(shù)字類的操作符包括:
==,!=,<,?<=,?>,>=,&
字符類的操作符包括:
==,!=,~
約等于操作符(~)接受通配符形式 (*,?)和字符類 ([)。舉例:
prev_comm~"*sh" prev_comm~"sh*" prev_comm~"*sh*" prev_comm~"ba*sh"
配置filters
通過(guò)將filter expressions寫(xiě)入給定event的filter文件來(lái)設(shè)置單個(gè)event的filter。
例如
echo'pid>1000'>/sys/kernel/debug/tracing/events/sched/sched_wakeup/filter#pid大于100的事件 echo1>/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable cat/sys/kernel/debug/tracing/trace
過(guò)濾進(jìn)程名為rcu_sched的事件
echo'comm=="rcu_sched"'>/sys/kernel/debug/tracing/events/sched/sched_wakeup/filter echo1>/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable cat/sys/kernel/debug/tracing/trace
如果表達(dá)式中存在錯(cuò)誤,則在設(shè)置時(shí)會(huì)得到一個(gè)Invalid argument錯(cuò)誤,錯(cuò)誤的字符串連同錯(cuò)誤消息可以通過(guò)查看過(guò)濾器來(lái)查看,例如:
cd/sys/kernel/debug/tracing/events/signal/signal_generate echo'((sig>=10&&sig15)?||?dsig?==?17)?&&?comm?!=?"bash"'??>filter -bash:echo:writeerror:Invalidargument catfilter ((sig>=10&&sig15)?||?dsig?==?17)?&&?comm?!=?bash ^ parse_error:?Field?not?found
清除filters
清除某個(gè)event的filter,echo 0 到對(duì)應(yīng)event的filter文件。
清除某個(gè)subsystem中所有events的filter,echo 0 到對(duì)應(yīng)subsystem的filter文件。
echo0>/sys/kernel/debug/tracing/events/sched/sched_wakeup/filter echo0>/sys/kernel/debug/tracing/events/sched/filter
子系統(tǒng)filters
為了方便起見(jiàn),可以將子系統(tǒng)中的每個(gè)事件的過(guò)濾器作為一個(gè)組來(lái)設(shè)置或清除,將一個(gè)過(guò)濾器表達(dá)式寫(xiě)入子系統(tǒng)根目錄下的過(guò)濾器文件中。
如果子系統(tǒng)內(nèi)的任何事件的過(guò)濾器缺少子系統(tǒng)過(guò)濾器中指定的字段,或者如果過(guò)濾器不能應(yīng)用于任何其他原因,則該事件的過(guò)濾器將保留其以前的設(shè)置。只有引用公共字段的過(guò)濾器才能保證成功地傳播到所有事件。
舉例:
清除sched subsystem中所有events的filter:
echo0>/sys/kernel/debug/tracing/events/sched/filter cat/sys/kernel/debug/tracing/events/sched_switch/filter none cat/sys/kernel/debug/tracing/events/sched_wakeup/filter none
使用sched subsystem中所有events都有的通用字段來(lái)設(shè)置filter(所有event將以同樣的filter結(jié)束):
echo'common_pid==0'>/sys/kernel/debug/tracing/events/sched/filter cat/sys/kernel/debug/tracing/events/sched/sched_switch/filter common_pid==0 cat/sys/kernel/debug/tracing/events/sched/sched_wakeup/filter common_pid==0
嘗試使用sched subsystem中非所有events通用字段來(lái)配置filter(所有沒(méi)有prev_pid字段的event將保留原有的filter):
echoprev_pid==0>/sys/kernel/debug/tracing/events/sched/filter cat/sys/kernel/debug/tracing/events/sched/sched_switch/filter prev_pid==0 cat/sys/kernel/debug/tracing/events/sched/sched_wakeup/filter common_pid==0
PID filters
頂級(jí)文件夾下的set_event_pid 文件,可以給所有event配置PID過(guò)濾:
echo$$>/sys/kernel/debug/tracing/set_event_pid echo1>/sys/kernel/debug/tracing/events/enable
以上配置將會(huì)只追蹤當(dāng)前進(jìn)程。
追加PID使用>>:
echo1232441>>set_event_pid
Event triggers
跟蹤事件可以有條件地調(diào)用trigger commands,每當(dāng)調(diào)用具有附加觸發(fā)器的trace event時(shí),就會(huì)調(diào)用與該event相關(guān)聯(lián)的 trigger commands。
任何給定的觸發(fā)器還可以具有與它相關(guān)聯(lián)的事件過(guò)濾中描述的相同形式的事件過(guò)濾器。如果調(diào)用的事件通過(guò)關(guān)聯(lián)的篩選器,則該命令將被調(diào)用。
給定的event可以有任意數(shù)量的trigger與它相關(guān)聯(lián),個(gè)別命令可能在這方面有所限制。
Event triggers是在“soft”模式上實(shí)現(xiàn)的,這意味如果一個(gè)event有一個(gè)或者多個(gè)trigger與之相關(guān)聯(lián),即使該event是disable狀態(tài),但實(shí)質(zhì)上已經(jīng)被actived,然后在“soft”模式中被disable。
也就是說(shuō),tracepoint 將被調(diào)用,但將不會(huì)被跟蹤,除非它被正式的enable。該方案允許即使disable的event也可以調(diào)用trigger,并且還允許當(dāng)前event filter實(shí)現(xiàn)用于有條件地調(diào)用trigger。
設(shè)置event triggers的語(yǔ)法類似于設(shè)置set_ftrace_filter ftrace filter commands 的語(yǔ)法(可以參考‘Filter commands’ section of Documentation/trace/ftrace.txt),但存在很大的差異。
語(yǔ)法
使用echo command 到‘trigger’文件的形式來(lái)增加Trigger:
echo'command[:count][iffilter]'>trigger
移除Trigger使用同樣的命令,但是加上了 ‘!’ 前綴:
echo'!command[:count][iffilter]'>trigger
filter部分的語(yǔ)法和上一節(jié) ‘Event 過(guò)濾’ 中描述的相同。
為了方便使用,當(dāng)前filter只支持使用>增加或刪除單條trigger,必須使用!命令逐條移除。
支持的命令
enable_event/disable_event
當(dāng)triggering event被命中時(shí),這些命令可以enable or disable其他的trace event。當(dāng)這些命令被注冊(cè),trace event變?yōu)閍ctive。
但是在“soft” mode下disable。這時(shí),tracepoint會(huì)被調(diào)用但是不會(huì)被trace。這些event tracepoint一直保持在這種模式中,直到trigger被觸發(fā)。
舉例,當(dāng)一個(gè)read系統(tǒng)調(diào)用進(jìn)入,以下的trigger導(dǎo)致kmalloc events被trace,:1 表明該行為只發(fā)生一次:
echo'enable_eventkmalloc:1'> /sys/kernel/debug/tracing/events/syscalls/sys_enter_read/trigger
當(dāng)一個(gè)read系統(tǒng)調(diào)用退出,以下的trigger導(dǎo)致kmalloc events被disable trace,每次退出都會(huì)調(diào)用:
echo'disable_eventkmalloc'>/sys/kernel/debug/tracing/events/syscalls/sys_exit_read/trigger
命令格式如下:
enable_event:: [:count] disable_event: : [:count]
移除命令:
echo'!enable_eventkmalloc:1'>/sys/kernel/debug/tracing/events/syscalls/sys_enter_read/trigger echo'!disable_eventkmalloc'>/sys/kernel/debug/tracing/events/syscalls/sys_exit_read/trigger
注意:每個(gè) triggering event可以有任意多個(gè)觸發(fā)動(dòng)作,但是每種觸發(fā)動(dòng)作只能有一個(gè)。
例如,sys_enter_read可以觸發(fā)enable kmem:kmalloc和sched:sched_switch,但是kmem:kmalloc不能有兩個(gè)版本kmem:kmalloc and kmem1或者是kmem:kmalloc if bytes_req == 256 and kmem:kmalloc if bytes_alloc == 256。
stacktrace
在triggering event發(fā)生時(shí),這個(gè)命令在trace buffer中dump出堆棧調(diào)用。
舉例,在每次kmalloc tracepoint被命中,以下的trigger dump出堆棧調(diào)用,
echo'stacktrace'>/sys/kernel/debug/tracing/events/kmem/kmalloc/trigger
以下的trigger dump出堆棧調(diào)用,在kmalloc請(qǐng)求bytes_req >= 800的前2次
echo'stacktrace:2ifbytes_req>=800'>/sys/kernel/debug/tracing/events/kmem/kmalloc/trigger
命令格式如下:
stacktrace[:count]
移除命令:
echo'!stacktrace'>/sys/kernel/debug/tracing/events/kmem/kmalloc/trigger echo'!stacktrace:2ifbytes_req>=800'>/sys/kernel/debug/tracing/events/kmem/kmalloc/trigger
后者也可以通過(guò)下面的(沒(méi)有過(guò)濾器)更簡(jiǎn)單地去除:
echo'!stacktrace:2'>/sys/kernel/debug/tracing/events/kmem/kmalloc/trigger
注意:每個(gè)trace event只能有一個(gè)stacktrace觸發(fā)器。
snapshot
當(dāng)triggering event發(fā)生時(shí),這個(gè)命令會(huì)觸發(fā)snapshot。
只有進(jìn)程名為snapd才會(huì)創(chuàng)建一個(gè)snapshot。
如果你想trace一系列的events or functions,在 trigger event發(fā)生時(shí),snapshot trace buffer將會(huì)抓住這些events:
echo'snapshotifcomm=="snapd"'>/sys/kernel/debug/tracing/events/kmem/kmalloc/trigger#配置trigger,只有進(jìn)程名為snapd才會(huì)snapshot echo'enable_eventkmalloc:1'>/sys/kernel/debug/tracing/events/syscalls/sys_enter_read/trigger#觸發(fā)kmalloc cat/sys/kernel/debug/tracing/snapshot#查看快照
只snapshot一次:
echo'snapshot:1ifcomm=="snapd"'>/sys/kernel/debug/tracing/events/kmem/kmalloc/trigger echo'enable_eventkmalloc:1'>/sys/kernel/debug/tracing/events/syscalls/sys_enter_read/trigger#觸發(fā)kmalloc cat/sys/kernel/debug/tracing/snapshot#查看快照
移除命令:
echo'!snapshotifcomm=="snapd"'>/sys/kernel/debug/tracing/events/kmem/kmalloc/trigger echo'!snapshot:1ifcomm=="snapd"'>/sys/kernel/debug/tracing/events/kmem/kmalloc/trigger
注意:每個(gè)trace event只能有一個(gè)snapshot觸發(fā)器。
traceon/traceoff
這個(gè)命令將會(huì)把整個(gè)trace tracing on/off當(dāng)event被命中。parameter 決定了系統(tǒng) turned on/off 多少次。沒(méi)有描述就是無(wú)限制。
以下命令將 turns tracing off 在block request queue第一次unplugged并且depth > 1,如果您當(dāng)時(shí)正在跟蹤一組事件或函數(shù),則可以檢查跟蹤緩沖區(qū),以查看導(dǎo)致觸發(fā)事件的事件序列:
echo'traceoff:1ifnr_rq>1'>/sys/kernel/debug/tracing/events/block/block_unplug/trigger
一直disable tracing 當(dāng)nr_rq > 1:
echo'traceoffifnr_rq>1'>/sys/kernel/debug/tracing/events/block/block_unplug/trigger
移除命令:
echo'!traceoff:1ifnr_rq>1'>/sys/kernel/debug/tracing/events/block/block_unplug/trigger echo'!traceoffifnr_rq>1'>/sys/kernel/debug/tracing/events/block/block_unplug/trigger
注意:每個(gè)trace event只能有一個(gè)traceon or traceoff觸發(fā)器。
hist
組合觸發(fā)。這個(gè)命令聚合多個(gè)trace event的字段到一個(gè)hash表中。
echo'hist:key=id.syscall,common_pid.execname:val=hitcount:sort=id,hitcountifid==16'>/sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/trigger cat/sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/hist
審核編輯:劉清
-
ECHO
+關(guān)注
關(guān)注
1文章
73瀏覽量
27166 -
PID控制
+關(guān)注
關(guān)注
10文章
460瀏覽量
40091 -
跟蹤器
+關(guān)注
關(guān)注
0文章
131瀏覽量
20026 -
nop
+關(guān)注
關(guān)注
0文章
9瀏覽量
1924
原文標(biāo)題:【調(diào)試】ftrace(一)基本使用方法
文章出處:【微信號(hào):嵌入式與Linux那些事,微信公眾號(hào):嵌入式與Linux那些事】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論