V mém předchozím článku jsem vysvětlil, jak používat ftrace
ke sledování funkcí jádra. Pomocí ftrace
zápis a čtení ze souborů může být zdlouhavé, takže jsem kolem toho použil obal ke spouštění příkazů s možnostmi povolení a zakázání trasování, nastavení filtrů, zobrazení výstupu, vymazání výstupu a další.
Příkaz trace-cmd je nástroj, který vám s tím pomůže. V tomto článku používám trace-cmd
k provádění stejných úkolů, jaké jsem dělal ve svém ftrace
článek. Vzhledem k tomu, že se na tento článek často vracím, doporučuji, abyste si jej přečetli dříve, než přečtete tento.
Instalovat trace-cmd
Příkazy v tomto článku spouštím jako uživatel root.
ftrace
mechanismus je zabudován do jádra a jeho aktivaci můžete ověřit pomocí:
Musíte však nainstalovat trace-cmd
nástroj ručně.
# dnf install trace-cmd -y
Seznam dostupných sledovacích prostředků
Při použití ftrace
, musíte zobrazit obsah souboru, abyste viděli, jaké sledovací prvky jsou k dispozici. Ale pomocí trace-cmd
, tyto informace můžete získat pomocí:
# trace-cmd list -t
hwlat blk mmiotrace function_graph wakeup_dl wakeup_rt funkce probuzení nop
Povolte sledování funkcí
Ve svém dřívějším článku jsem použil dva sledovače a zde udělám totéž. Povolte svůj první tracer, function
, s:
$ trace-cmd start -p funkce
plugin 'function'
Zobrazit výstup trasování
Jakmile je tracer povolen, můžete zobrazit výstup pomocí show
argumenty. Toto zobrazuje pouze prvních 20 řádků, aby byl příklad krátký (vysvětlení výstupu viz můj dřívější článek):
# trace-cmd zobrazit | head -20
## tracer:funkce
#
# záznamy ve vyrovnávací paměti/zapsané záznamy:410142/3380032 #P:8
#
# -----=> irqs-off
# / _----=> potřeba změnit
# | / _---=> hardirq/softirq
# || / _--=> preempt-depth
# ||| / zpoždění
# TASK-PID CPU# |||| FUNKCE TIMESTAMP
# | | | |||| | |
gdbus-2606 [004] ..s. 10520.538759:__msecs_to_jiffies <-rebalance_domains
gdbus-2606 [004] ..s. 10520.538760:load_balance <-rebalance_domains
gdbus-2606 [004] ..s. 10520.538761:idle_cpu <-load_balance
gdbus-2606 [004] ..s. 10520.538762:group_balance_cpu <-load_balance
gdbus-2606 [004] ..s. 10520.538762:find_busiest_group <-load_balance
gdbus-2606 [004] ..s. 10520.538763:update_group_capacity <-update_sd_lb_stats.constprop.0
gdbus-2606 [004] ..s. 10520.538763:__msecs_to_jiffies <-update_group_capacity
gdbus-2606 [004] ..s. 10520.538765:idle_cpu <-update_sd_lb_stats.constprop.0
gdbus-2606 [004] ..s. 10520.538766:__msecs_to_jiffies <-rebalance_domains
Zastavit trasování a vymazat vyrovnávací paměť
Trasování pokračuje na pozadí a můžete pokračovat v prohlížení výstupu pomocí show
.
Chcete-li zastavit trasování, spusťte trace-cmd
pomocí stop
argument:
# trace-cmd stop
Chcete-li vymazat vyrovnávací paměť, spusťte ji pomocí clear
argument:
# trace-cmd clear
Povolit sledování function_graph
Povolte druhý sledovač, function_graph
, spuštěním:
# trace-cmd start -p function_graph
plugin 'function_graph'
Ještě jednou si prohlédněte výstup pomocí show
argument. Podle očekávání se výstup mírně liší od výstupu prvního trasování. Tentokrát obsahuje function calls
řetěz:
# trace-cmd zobrazit | head -20
## tracer:function_graph
#
# CPU DOBA TRVÁNÍ VOLÁNÍ FUNKCE
# | | | | | | |
4) 0,079 us | } /* rcu_all_qs */
4) 0,327 us | } /* __cond_resched */
4) 0,081 us | rcu_read_unlock_strict();
4) | __cond_resched() {
4) 0,078 us | rcu_all_qs();
4) 0,243 us | }
4) 0,080 us | rcu_read_unlock_strict();
4) | __cond_resched() {
4) 0,078 us | rcu_all_qs();
4) 0,241 us | }
4) 0,080 us | rcu_read_unlock_strict();
4) | __cond_resched() {
4) 0,079 us | rcu_all_qs();
4) 0,235 us |
4) 0,095 us | rcu_read_unlock_strict();
4) | __cond_resched() {
Použijte stop
a clear
příkazy k zastavení trasování a vymazání vyrovnávací paměti:
# trace-cmd stop
# trace-cmd clear
Vylepšením trasování zvýšíte hloubku
Pokud chcete vidět větší hloubku ve volání funkcí, můžete vyladit tracer:
# trace-cmd start -p function_graph --max-graph-depth 5
plugin 'function_graph'
Když nyní porovnáte tento výstup s tím, co jste viděli dříve, měli byste vidět více vnořených volání funkcí:
# trace-cmd zobrazit | head -20
## tracer:function_graph
#
# CPU DOBA TRVÁNÍ VOLÁNÍ FUNKCE
# | | | | | | |
6) | __fget_light() {
6) 0,804 us | __fget_files();
6) 2,708 us |
6) 3 650 us | } /* __fdget */
6) 0,547 us | eventfd_poll();
6) 0,535 us | fput();
6) | __fdget() {
6) | __fget_light() {
6) 0,946 us | __fget_files();
6) 1 895 us |
6) 2 849 us |
6) | sock_poll() {
6) 0,651 us | unix_poll();
6) 1 905 us |
6) 0,475 us | fput();
6) | __fdget() {
Naučte se dostupné funkce ke sledování
Pokud chcete sledovat pouze určité funkce a zbytek ignorovat, musíte znát přesné názvy funkcí. Můžete je získat pomocí list
argument následovaný -f
. Tento příklad hledá společnou funkci jádra kmalloc
, který se používá k alokaci paměti v jádře:
# seznam trace-cmd -f | grep kmalloc
bpf_map_kmalloc_node
mempool_kmalloc
__traceiter_kmalloc
__traceiter_kmalloc_node
kmalloc_slab
kmalloc_order
kmalloc_order_malloc_trace
>__kmalloc_track_caller
__kmalloc_node
__kmalloc_node_track_caller
[...]
Zde je celkový počet funkcí dostupných v mém testovacím systému:
# seznam trace-cmd -f | wc -l
63165
Sledování funkcí souvisejících s modulem jádra
Můžete také sledovat funkce související s konkrétním modulem jádra. Představte si, že chcete trasovat kvm
funkce související s modulem jádra. Ujistěte se, že je modul načten:
# lsmod | grep kvm_intel
kvm_intel 335872 0
kvm 987136 1 kvm_intel
Spusťte trace-cmd
znovu pomocí list
argument a z výstupu grep
pro řádky, které končí ]
. Tím se odfiltrují moduly jádra. Poté grep
modul jádra kvm_intel
a měli byste vidět všechny funkce související s tímto modulem jádra:
# seznam trace-cmd -f | grep ]$ | grep kvm_intel
vmx_can_emulate_instruction [kvm_intel]
vmx_update_emulated_instruction [kvm_intel]
vmx_setup_uret_msr [kvm_intel]
vmx_set_identity_m_mapintel_addr] [handkvx_set_identity_mtriintel_addr] [handkvx_set_identity_mtriintel_addr] [handkv
vmx_patch_hypercall [kvm_intel]
[...]
vmx_dump_dtsel [kvm_intel]
vmx_dump_sel [kvm_intel]
Další zdroje pro Linux
- Cheat pro příkazy Linuxu
- Cheat sheet pro pokročilé příkazy systému Linux
- Bezplatný online kurz:Technický přehled RHEL
- Síťový cheat pro Linux
- Cheat sheet SELinux
- Cheat pro běžné příkazy pro Linux
- Co jsou kontejnery systému Linux?
- Naše nejnovější články o Linuxu
Sledování specifických funkcí
Nyní, když víte, jak najít funkce, které vás zajímají, použijte tyto znalosti na příkladu. Stejně jako v předchozím článku zkuste vysledovat funkce související se souborovým systémem. Souborový systém, který jsem měl na svém testovacím systému, byl ext4
.
Tento postup je mírně odlišný; místo start
, spustíte příkaz s record
argument následovaný "vzorem" funkcí, které chcete trasovat. Musíte také určit sledovač, který chcete; v tomto případě je to function_graph
. Příkaz pokračuje v záznamu trasování, dokud jej nezastavíte pomocí Ctrl+C . Po několika sekundách tedy stiskněte Ctrl+C pro zastavení sledování:
# seznam trace-cmd -f | grep ^ext4_
# záznam trace-cmd -l ext4_* -p function_graph
plugin 'function_graph'
K zastavení nahrávání stiskněte Ctrl^C
^C
Data CPU0 zaznamenaná s offsetem=0x856000
Velikost 8192 bajtů
[...]
Zobrazit zaznamenanou trasu
Chcete-li zobrazit trasování, které jste zaznamenali dříve, spusťte příkaz s report
argument. Z výstupu je jasné, že filtr fungoval a vidíte pouze trasování funkce související s ext4:
# zpráva trace-cmd | head -20
[...]
cpus=8
trace-cmd-12697 [000] 11303.928103:funcgraph_entry: | ext4_show_options() {
trace-cmd-12697 [000] 11303.928104:funcgraph_entry: 0,187 us | ext4_get_dummy_policy();
trace-cmd-12697 [000] 11303.928105:funcgraph_exit: 1 583 us | }
trace-cmd-12697 [000] 11303.928122:funcgraph_entry: | ext4_create() {
trace-cmd-12697 [000] 11303.928122:funcgraph_entry: | ext4_alloc_inode() {
trace-cmd-12697 [000] 11303.928123:funcgraph_entry: 0,101 us | ext4_es_init_tree();
trace-cmd-12697 [000] 11303.928123:funcgraph_entry: 0,083 us | ext4_init_pending_tree();
trace-cmd-12697 [000] 11303.928123:funcgraph_entry: 0,141 us | ext4_fc_init_inode();
trace-cmd-12697 [000] 11303.928123:funcgraph_exit: 0,931 us | }
trace-cmd-12697 [000] 11303.928124:funcgraph_entry: 0,081 us | ext4_get_dummy_policy();
trace-cmd-12697 [000] 11303.928124:funcgraph_entry: 0,133 us | ext4_get_group_desc();
trace-cmd-12697 [000] 11303.928124:funcgraph_entry: 0,115 us | ext4_free_inodes_count();
trace-cmd-12697 [000] 11303.928124:funcgraph_entry: 0,114 us | ext4_get_group_desc();
Sledování konkrétního PID
Řekněme, že chcete sledovat funkce související s konkrétním trvalým identifikátorem (PID). Otevřete další terminál a poznamenejte si PID běžícího shellu:
# echo $$
10885
Spusťte record
znovu a předejte PID pomocí -P
volba. Tentokrát nechte terminál běžet (tj. netiskněte Ctrl+C ještě):
# trace-cmd record -P 10885 -p function_graph
plugin 'function_graph'
K zastavení nahrávání stiskněte Ctrl^C
Spusťte nějakou aktivitu na shellu
Přejděte zpět na druhý terminál, kde jste měli spuštěný shell se specifickým PID, a spusťte libovolný příkaz, např. ls
pro výpis souborů:
# ls
Temp-9b61f280-fdc1-4512-9211-5c60f764d702
tracker-extract-3-files.1000
v8-compile-cache-1000
[. ..]
Přejděte zpět do terminálu, kde jste povolili trasování, a stiskněte Ctrl+C pro zastavení sledování:
# záznam trace-cmd -P 10885 -p function_graph
plugin 'function_graph'
Stisknutím Ctrl^C záznam zastavíte
^C
Data CPU1 zaznamenaná s offsetem=0x856000
Velikost 618496 bajtů
[...]
Ve výstupu trasování můžete vidět PID a shell Bash vlevo a volání funkcí s nimi související vpravo. To může být docela užitečné pro zúžení trasování:
# zpráva trace-cmd | head -20
cpus=8
-0 [001] 11555.380581:funcgraph_entry: | switch_mm_irqs_off() {
-0 [001] 11555.380583:funcgraph_entry: 1.703 us | load_new_mm_cr3();
-0 [001] 11555,380586:funcgraph_entry: 0,493 us | switch_ldt();
-0 [001] 11555.380587:funcgraph_exit: 7.235 us | }
bash-10885 [001] 11555.380589:funcgraph_entry: 1.046 us | finish_task_switch.isra.0();
bash-10885 [001] 11555.380591:funcgraph_entry: | __fdget() {
bash-10885 [001] 11555.380592:funcgraph_entry: 2.036 us | __fget_light();
bash-10885 [001] 11555.380594:funcgraph_exit: 3.256 us | }
bash-10885 [001] 11555.380595:funcgraph_entry: | tty_poll() {
bash-10885 [001] 11555.380597:funcgraph_entry: | tty_ldisc_ref_wait() {
bash-10885 [001] 11555.380598:funcgraph_entry: | ldsem_down_read() {
bash-10885 [001] 11555.380598:funcgraph_entry: | __cond_resched() {
Vyzkoušejte to
Tyto krátké příklady ukazují, jak používat trace-cmd
místo základního ftrace
mechanismus se snadno používá a je bohatý na funkce, včetně mnoha, které jsem zde nepopsal. Chcete-li se dozvědět více a zlepšit se v něm, podívejte se na jeho manuálovou stránku a vyzkoušejte jeho další užitečné příkazy.