GNU/Linux >> Belajar Linux >  >> Linux

Pelacakan kernel dengan trace-cmd

Pada artikel saya sebelumnya, saya menjelaskan cara menggunakan ftrace untuk melacak fungsi kernel. Menggunakan ftrace dengan menulis dan membaca dari file bisa menjadi membosankan, jadi saya menggunakan pembungkus di sekitarnya untuk menjalankan perintah dengan opsi untuk mengaktifkan dan menonaktifkan pelacakan, menyetel filter, melihat keluaran, menghapus keluaran, dan banyak lagi.

Perintah trace-cmd adalah utilitas yang membantu Anda melakukan hal ini. Dalam artikel ini, saya menggunakan trace-cmd untuk melakukan tugas yang sama seperti yang saya lakukan di ftrace artikel. Karena saya sering merujuk kembali ke artikel itu, saya sarankan Anda membacanya sebelum membaca yang ini.

Instal trace-cmd

Saya menjalankan perintah dalam artikel ini sebagai pengguna root.

ftrace mekanisme dibangun ke dalam kernel, dan Anda dapat memverifikasinya diaktifkan dengan:

# mount | grep tracefs
none on /sys/kernel/tracing type tracefs (rw,relatime,seclabel)

Namun, Anda perlu menginstal trace-cmd utilitas secara manual.

# dnf install trace-cmd -y

Daftar pelacak yang tersedia

Saat menggunakan ftrace , Anda harus melihat konten file untuk melihat pelacak apa yang tersedia. Tetapi dengan trace-cmd , Anda bisa mendapatkan informasi ini dengan:

# trace-cmd list -t
hwlat blk mmiotrace function_graph wakeup_dl wakeup_rt wakeup function nop

Aktifkan pelacak fungsi

Dalam artikel saya sebelumnya, saya menggunakan dua pelacak, dan saya akan melakukan hal yang sama di sini. Aktifkan pelacak pertama Anda, function , dengan:

$ trace-cmd start -p function
  plugin 'function'

Melihat keluaran jejak

Setelah pelacak diaktifkan, Anda dapat melihat output dengan menggunakan show argumen. Ini hanya menunjukkan 20 baris pertama untuk membuat contoh singkat (lihat artikel saya sebelumnya untuk penjelasan tentang output):

# 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

Berhenti melacak dan menghapus buffer

Pelacakan terus berjalan di latar belakang, dan Anda dapat terus melihat output menggunakan show .

Untuk menghentikan pelacakan, jalankan trace-cmd dengan stop argumen:

# trace-cmd stop

Untuk menghapus buffer, jalankan dengan clear argumen:

# trace-cmd clear

Aktifkan pelacak function_graph

Aktifkan pelacak kedua, function_graph , dengan menjalankan:

# trace-cmd start -p function_graph
  plugin 'function_graph'

Sekali lagi, lihat output menggunakan show argumen. Seperti yang diharapkan, outputnya sedikit berbeda dari output jejak pertama. Kali ini termasuk function calls rantai:

# 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() {

Gunakan stop dan clear perintah untuk berhenti melacak dan menghapus buffer:

# trace-cmd stop
# trace-cmd clear

Tweak tracing untuk menambah kedalaman

Jika Anda ingin melihat lebih dalam panggilan fungsi, Anda dapat mengubah pelacak:

# trace-cmd start -p function_graph --max-graph-depth 5
  plugin 'function_graph'

Sekarang ketika Anda membandingkan output ini dengan apa yang Anda lihat sebelumnya, Anda akan melihat lebih banyak panggilan fungsi bersarang:

# 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() {

Pelajari fungsi yang tersedia untuk dilacak

Jika Anda hanya ingin melacak fungsi tertentu dan mengabaikan yang lainnya, Anda perlu mengetahui nama fungsi yang tepat. Anda bisa mendapatkannya dengan list argumen diikuti oleh -f . Contoh ini mencari fungsi kernel umum kmalloc , yang digunakan untuk mengalokasikan memori di kernel:

# 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
[...]

Berikut jumlah total fungsi yang tersedia di sistem pengujian saya:

# trace-cmd list -f | wc -l
63165

Anda juga dapat melacak fungsi yang terkait dengan modul kernel tertentu. Bayangkan Anda ingin melacak kvm fungsi terkait modul kernel. Pastikan modul dimuat:

# lsmod  | grep kvm_intel
kvm_intel             335872  0
kvm                   987136  1 kvm_intel

Jalankan trace-cmd lagi dengan list argumen, dan dari output, grep untuk baris yang diakhiri dengan ] . Ini akan menyaring modul kernel. Kemudian grep modul kernel kvm_intel , dan Anda akan melihat semua fungsi yang terkait dengan modul kernel tersebut:

# 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]

Lebih banyak sumber daya Linux

  • Lembar contekan perintah Linux
  • Lembar contekan perintah Linux tingkat lanjut
  • Kursus online gratis:Ikhtisar Teknis RHEL
  • Lembar contekan jaringan Linux
  • Lembar contekan SELinux
  • Lembar contekan perintah umum Linux
  • Apa itu container Linux?
  • Artikel Linux terbaru kami

Melacak fungsi tertentu

Sekarang setelah Anda tahu cara menemukan fungsi yang menarik, gunakan pengetahuan itu dengan sebuah contoh. Seperti pada artikel sebelumnya, coba lacak fungsi terkait sistem file. Sistem file yang saya miliki di sistem pengujian saya adalah ext4 .

Prosedur ini sedikit berbeda; alih-alih start , Anda menjalankan perintah dengan record argumen diikuti oleh "pola" fungsi yang ingin Anda lacak. Anda juga perlu menentukan pelacak yang Anda inginkan; dalam hal ini, itu function_graph . Perintah terus merekam jejak hingga Anda menghentikannya dengan Ctrl+C . Jadi setelah beberapa detik, tekan Ctrl+C untuk berhenti melacak:

# 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
[...]

Melihat rekaman jejak

Untuk melihat jejak yang Anda rekam sebelumnya, jalankan perintah dengan report argumen. Dari output, jelas bahwa filter berfungsi, dan Anda hanya melihat jejak fungsi terkait ext4:

# 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();

Lacak PID tertentu

Katakanlah Anda ingin melacak fungsi yang terkait dengan pengenal persisten (PID) tertentu. Buka terminal lain dan catat PID dari shell yang sedang berjalan:

# echo $$
10885

Jalankan record perintah lagi dan berikan PID menggunakan -P pilihan. Kali ini, biarkan terminal berjalan (yaitu, jangan tekan Ctrl+C belum):

# trace-cmd record -P 10885 -p function_graph
  plugin 'function_graph'
Hit Ctrl^C to stop recording

Jalankan beberapa aktivitas di shell

Kembali ke terminal lain tempat Anda menjalankan shell dengan PID tertentu dan jalankan perintah apa pun, mis., ls untuk membuat daftar file:

# ls
Temp-9b61f280-fdc1-4512-9211-5c60f764d702
tracker-extract-3-files.1000
v8-compile-cache-1000
[...]

Kembali ke terminal tempat Anda mengaktifkan pelacakan dan tekan Ctrl+C untuk berhenti melacak:

# 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
[...]

Dalam keluaran jejak, Anda dapat melihat PID dan shell Bash di sebelah kiri dan pemanggilan fungsi yang terkait dengannya di sebelah kanan. Ini bisa sangat berguna untuk mempersempit penelusuran Anda:

# 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() {

Cobalah

Contoh singkat ini menunjukkan bagaimana menggunakan trace-cmd alih-alih ftrace yang mendasarinya mekanisme mudah digunakan dan kaya fitur, termasuk banyak yang tidak saya bahas di sini. Untuk mempelajari lebih lanjut dan menjadi lebih baik, lihat halaman manualnya dan coba perintah berguna lainnya.


Linux
  1. Menambal Biner Dengan Dd?

  2. Memblokir Pembaruan Kernel Dengan Dpkg?

  3. Cara Menulis Modul Kernel Linux Anda Sendiri dengan Contoh Sederhana

  1. CentOS / RHEL :Pengecualian dengan Yum Untuk Pembaruan Kernel

  2. Bagaimana cara men-debug kernel Linux dengan GDB dan QEMU?

  3. Bisakah saya membangun distro linux dengan libc, bukan glibc

  1. Analisis kernel Linux dengan ftrace

  2. Debugging Kernel Linux dengan QEMU

  3. Linux Centos dengan stempel waktu dmesg