In meinem vorherigen Artikel habe ich erklärt, wie man ftrace
verwendet um Kernel-Funktionen zu verfolgen. Verwenden von ftrace
durch das Schreiben und Lesen von Dateien kann mühsam werden, also habe ich einen Wrapper darum verwendet, um Befehle mit Optionen zum Aktivieren und Deaktivieren der Ablaufverfolgung, zum Festlegen von Filtern, zum Anzeigen der Ausgabe, zum Löschen der Ausgabe und mehr auszuführen.
Der Befehl trace-cmd ist ein Dienstprogramm, das Ihnen dabei hilft. In diesem Artikel verwende ich trace-cmd
um die gleichen Aufgaben auszuführen, die ich in meinem ftrace
gemacht habe Artikel. Da ich häufig auf diesen Artikel zurückgreife, empfehle ich Ihnen, ihn zu lesen, bevor Sie diesen lesen.
trace-cmd installieren
Ich führe die Befehle in diesem Artikel als Root-Benutzer aus.
Der ftrace
Mechanismus ist in den Kernel eingebaut, und Sie können überprüfen, ob er aktiviert ist mit:
# mount | grep tracefsein
none on /sys/kernel/tracing type tracefs (rw,relatime,seclabel)
Sie müssen jedoch das trace-cmd
installieren Dienstprogramm manuell.
# dnf install trace-cmd -y
Verfügbare Tracer auflisten
Bei Verwendung von ftrace
, müssen Sie den Inhalt einer Datei anzeigen, um zu sehen, welche Tracer verfügbar sind. Aber mit trace-cmd
, erhalten Sie diese Informationen mit:
# trace-cmd list -t
hwlat blk mmiotrace function_graph wakeup_dl wakeup_rt wakeup function nop
Funktions-Tracer aktivieren
In meinem früheren Artikel habe ich zwei Tracer verwendet, und ich werde das Gleiche hier tun. Aktivieren Sie Ihren ersten Tracer, function
, mit:
$ trace-cmd start -p function
plugin 'function'
Trace-Ausgabe anzeigen
Sobald der Tracer aktiviert ist, können Sie die Ausgabe mit show
anzeigen Argumente. Dies zeigt nur die ersten 20 Zeilen, um das Beispiel kurz zu halten (siehe meinen früheren Artikel für eine Erklärung der Ausgabe):
# trace-cmd show | head -20
## tracer: function
#
# entries-in-buffer/entries-written: 410142/3380032 #P:8
#
# _-----=> irqs-off
# / _----=> need-resched
# | / _---=> hardirq/softirq
# || / _--=> preempt-depth
# ||| / delay
# TASK-PID CPU# |||| TIMESTAMP FUNCTION
# | | | |||| | |
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
Beenden Sie die Ablaufverfolgung und leeren Sie den Puffer
Die Ablaufverfolgung läuft im Hintergrund weiter, und Sie können die Ausgabe weiterhin mit show
anzeigen .
Um die Ablaufverfolgung zu beenden, führen Sie trace-cmd
aus mit der stop
Argument:
# trace-cmd stop
Um den Puffer zu löschen, führen Sie ihn mit clear
aus Argument:
# trace-cmd clear
Funktionsgraph-Tracer aktivieren
Aktivieren Sie den zweiten Tracer, function_graph
, indem Sie Folgendes ausführen:
# trace-cmd start -p function_graph
plugin 'function_graph'
Sehen Sie sich die Ausgabe erneut mit show
an Streit. Wie erwartet weicht die Ausgabe etwas von der ersten Trace-Ausgabe ab. Diesmal enthält es einen function calls
Kette:
# trace-cmd show | head -20
## tracer: function_graph
#
# CPU DURATION FUNCTION CALLS
# | | | | | | |
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() {
Verwenden Sie die stop
und clear
Befehle zum Stoppen der Ablaufverfolgung und zum Löschen des Puffers:
# trace-cmd stop
# trace-cmd clear
Optimieren Sie die Ablaufverfolgung, um die Tiefe zu erhöhen
Wenn Sie mehr Tiefe in den Funktionsaufrufen sehen möchten, können Sie den Tracer anpassen:
# trace-cmd start -p function_graph --max-graph-depth 5
plugin 'function_graph'
Wenn Sie nun diese Ausgabe mit dem vergleichen, was Sie vorher gesehen haben, sollten Sie mehr verschachtelte Funktionsaufrufe sehen:
# trace-cmd show | head -20
## tracer: function_graph
#
# CPU DURATION FUNCTION CALLS
# | | | | | | |
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() {
Lernen Sie verfügbare Funktionen zum Tracen
Wenn Sie nur bestimmte Funktionen verfolgen und den Rest ignorieren möchten, müssen Sie die genauen Funktionsnamen kennen. Sie können sie mit der list
abrufen Argument gefolgt von -f
. Dieses Beispiel sucht nach der allgemeinen Kernel-Funktion kmalloc
, die verwendet wird, um Speicher im Kernel zuzuweisen:
# trace-cmd list -f | grep kmalloc
bpf_map_kmalloc_node
mempool_kmalloc
__traceiter_kmalloc
__traceiter_kmalloc_node
kmalloc_slab
kmalloc_order
kmalloc_order_trace
kmalloc_large_node
__kmalloc
__kmalloc_track_caller
__kmalloc_node
__kmalloc_node_track_caller
[...]
Hier ist die Gesamtzahl der auf meinem Testsystem verfügbaren Funktionen:
# trace-cmd list -f | wc -l
63165
Kernelmodul-bezogene Trace-Funktionen
Sie können auch Funktionen verfolgen, die sich auf ein bestimmtes Kernelmodul beziehen. Stellen Sie sich vor, Sie möchten kvm
verfolgen Kernel-Modul-bezogene Funktionen. Stellen Sie sicher, dass das Modul geladen ist:
# lsmod | grep kvm_intel
kvm_intel 335872 0
kvm 987136 1 kvm_intel
Führen Sie trace-cmd
aus wieder mit der list
Argument und aus der Ausgabe grep
für Zeilen, die auf ]
enden . Dadurch werden die Kernelmodule herausgefiltert. Dann grep
das Kernelmodul kvm_intel
, und Sie sollten alle Funktionen sehen, die sich auf dieses Kernelmodul beziehen:
# trace-cmd list -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_map_addr [kvm_intel]
handle_machine_check [kvm_intel]
handle_triple_fault [kvm_intel]
vmx_patch_hypercall [kvm_intel]
[...]
vmx_dump_dtsel [kvm_intel]
vmx_dump_sel [kvm_intel]
Weitere Linux-Ressourcen
- Spickzettel für Linux-Befehle
- Spickzettel für fortgeschrittene Linux-Befehle
- Kostenloser Online-Kurs:RHEL Technical Overview
- Spickzettel für Linux-Netzwerke
- SELinux-Spickzettel
- Spickzettel für allgemeine Linux-Befehle
- Was sind Linux-Container?
- Unsere neuesten Linux-Artikel
Verfolgen Sie bestimmte Funktionen
Jetzt, da Sie wissen, wie man interessante Funktionen findet, wenden Sie dieses Wissen an einem Beispiel an. Versuchen Sie wie im vorherigen Artikel, dateisystembezogene Funktionen zu verfolgen. Das Dateisystem, das ich auf meinem Testsystem hatte, war ext4
.
Dieses Verfahren ist etwas anders; statt start
, führen Sie den Befehl mit dem record
aus -Argument, gefolgt vom "Muster" der Funktionen, die Sie verfolgen möchten. Sie müssen auch den gewünschten Tracer angeben; in diesem Fall ist das function_graph
. Der Befehl zeichnet den Trace so lange auf, bis Sie ihn mit Strg+C stoppen . Drücken Sie also nach ein paar Sekunden Strg+C So beenden Sie die Ablaufverfolgung:
# trace-cmd list -f | grep ^ext4_
# trace-cmd record -l ext4_* -p function_graph
plugin 'function_graph'
Hit Ctrl^C to stop recording
^C
CPU0 data recorded at offset=0x856000
8192 bytes in size
[...]
Aufgezeichneten Trace ansehen
Um die zuvor aufgezeichnete Ablaufverfolgung anzuzeigen, führen Sie den Befehl mit report
aus Streit. Aus der Ausgabe geht hervor, dass der Filter funktioniert hat, und Sie sehen nur die ext4-bezogene Funktionsablaufverfolgung:
# trace-cmd report | 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();
Verfolge eine bestimmte PID
Angenommen, Sie möchten Funktionen nachverfolgen, die sich auf einen bestimmten persistenten Bezeichner (PID) beziehen. Öffnen Sie ein weiteres Terminal und notieren Sie sich die PID der laufenden Shell:
# echo $$
10885
Führen Sie den record
aus Befehl erneut und übergeben Sie die PID mit -P
Möglichkeit. Lassen Sie diesmal das Terminal laufen (d. h. drücken Sie nicht Strg+C noch):
# trace-cmd record -P 10885 -p function_graph
plugin 'function_graph'
Hit Ctrl^C to stop recording
Führen Sie eine Aktivität auf der Shell aus
Gehen Sie zurück zum anderen Terminal, wo Sie eine Shell mit einer bestimmten PID ausgeführt haben, und führen Sie einen beliebigen Befehl aus, z. B. ls
Dateien auflisten:
# ls
Temp-9b61f280-fdc1-4512-9211-5c60f764d702
tracker-extract-3-files.1000
v8-compile-cache-1000
[...]
Gehen Sie zurück zu dem Terminal, in dem Sie die Ablaufverfolgung aktiviert haben, und drücken Sie Strg+C So beenden Sie die Ablaufverfolgung:
# trace-cmd record -P 10885 -p function_graph
plugin 'function_graph'
Hit Ctrl^C to stop recording
^C
CPU1 data recorded at offset=0x856000
618496 bytes in size
[...]
In der Ausgabe des Trace sehen Sie links die PID und die Bash-Shell und rechts die zugehörigen Funktionsaufrufe. Dies kann sehr praktisch sein, um Ihre Ablaufverfolgung einzugrenzen:
# trace-cmd report | head -20
cpus=8
<idle>-0 [001] 11555.380581: funcgraph_entry: | switch_mm_irqs_off() {
<idle>-0 [001] 11555.380583: funcgraph_entry: 1.703 us | load_new_mm_cr3();
<idle>-0 [001] 11555.380586: funcgraph_entry: 0.493 us | switch_ldt();
<idle>-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() {
Probieren Sie es aus
Diese kurzen Beispiele zeigen die Verwendung von trace-cmd
anstelle des zugrunde liegenden ftrace
Der Mechanismus ist sowohl einfach zu bedienen als auch reich an Funktionen, darunter viele, die ich hier nicht behandelt habe. Um mehr zu erfahren und besser darin zu werden, konsultieren Sie die Manpage und probieren Sie die anderen nützlichen Befehle aus.