GNU/Linux >> Linux の 問題 >  >> Linux

Linuxカーネルをftraceで分析する

オペレーティングシステムのカーネルは、世の中で最もとらえどころのないソフトウェアの1つです。システムの電源がオンになったときから、常にバックグラウンドで実行されています。すべてのユーザーは、カーネルの助けを借りてコンピューティング作業を実行しますが、カーネルと直接対話することはありません。カーネルとの相互作用は、システムコールを行うか、ユーザーが日常的に使用するさまざまなライブラリやアプリケーションによってユーザーに代わってそれらのコールを行うことによって発生します。

straceを使用してシステムコールをトレースする方法については、以前の記事で説明しました。 。ただし、straceでは 、視界が制限されています。これにより、特定のパラメーターで呼び出されたシステムコールを表示し、作業が完了した後、それらが成功したか失敗したかを示す戻り値またはステータスを確認できます。しかし、この間にカーネル内で何が起こったのかはわかりませんでした。システムコールを提供するだけでなく、カーネル内で気付かない他の多くのアクティビティが発生しています。

Ftraceの紹介

その他のLinuxリソース

  • Linuxコマンドのチートシート
  • 高度なLinuxコマンドのチートシート
  • 無料のオンラインコース:RHELの技術概要
  • Linuxネットワーキングのチートシート
  • SELinuxチートシート
  • Linuxの一般的なコマンドのチートシート
  • Linuxコンテナとは何ですか?
  • 最新のLinux記事

この記事は、ftraceと呼ばれるメカニズムを使用して、カーネル関数のトレースに光を当てることを目的としています。 。 Linuxユーザーなら誰でもカーネルトレースに簡単にアクセスできるようになり、Linuxカーネルの内部について多くのことを学ぶことができます。

ftraceによって生成されるデフォルトの出力 カーネルが常にビジーであることを考えると、多くの場合、大規模です。スペースを節約するために、出力を最小限に抑え、多くの場合、出力を完全に切り捨てました。

これらの例ではFedoraを使用していますが、最新のLinuxディストリビューションのいずれでも動作するはずです。

ftraceの有効化

Ftrace は現在Linuxカーネルの一部であり、使用するために何もインストールする必要はありません。最近のLinuxOSを使用している場合は、ftrace すでに有効になっています。 ftraceを確認するには ファシリティが使用可能になったら、mountコマンドを実行して、tracefsを検索します。 。以下のような出力が表示された場合は、ftrace が有効になっており、この記事の例を簡単にたどることができます。これらのコマンドは、rootユーザー(sudo)として実行する必要があります 不十分です。)

#マウント| grep tracefs 
/ sys / kernel / traceing type tracefs(rw、relatime、seclabel)にはありません

ftraceを利用するには 、最初に、上記のmountコマンドで指定されている特別なディレクトリに移動する必要があります。そこから、記事の残りのコマンドを実行します。

 # cd /sys/kernel/tracing 

一般的なワークフロー

まず、トレースをキャプチャして出力を取得する一般的なワークフローを理解する必要があります。 ftraceを使用している場合 直接、特別なftrace-はありません 実行する特定のコマンド。代わりに、基本的に、標準のコマンドラインLinuxユーティリティを使用して、いくつかのファイルに書き込み、いくつかのファイルから読み取ります。

一般的な手順:

  1. 特定のファイルに書き込んで、トレースを有効/無効にします。
  2. 特定のファイルに書き込んで、フィルタを設定/設定解除し、トレースを微調整します。
  3. 1と2に基づいてファイルから生成されたトレース出力を読み取ります。
  4. ファイルから以前の出力またはバッファをクリアします。
  5. 特定のユースケース(トレースするカーネル関数)に絞り込み、手順1、2、3、4を繰り返します。

利用可能なトレーサーの種類

利用できるトレーサーにはいくつかの種類があります。前述のように、これらのコマンドを実行する前に、特定のディレクトリにいる必要があります。これは、対象のファイルがそこに存在するためです。例では、(絶対パスではなく)相対パスを使用しています。

available_tracersの内容を表示できます 利用可能なすべてのタイプのトレーサーを確認するためのファイル。以下にリストされているいくつかを見ることができます。まだそれらすべてについて心配する必要はありません:

#pwd 
/ sys / kernel / traceing

#cat available_tracers
hwlat blk mmiotrace function_graph wakeup_dl wakeup_rt wakeup function nop

与えられたすべてのトレーサーのうち、私は3つの特定のトレーサーに焦点を当てています:function およびfunction_graph トレースを有効にするには、nop トレースを無効にします。

現在のトレーサーを特定する

通常、デフォルトでは、トレーサーはnopに設定されています 。つまり、特殊ファイルcurrent_tracerの「操作なし」です。 、これは通常、トレースが現在オフになっていることを意味します:

#pwd 
/ sys / kernel / traceing

#cat current_tracer
nop

トレース出力の表示

トレースを有効にする前に、トレース出力が保存されるファイルを確認してください。 traceという名前のファイルの内容を表示できます catコマンドの使用:

#cat trace 

#tracer:nop

#entries-in-buffer / items-written:0/0 #P:8

#_----- => irqs-off
#/ _----=>必要性
hardirq / softirq
#|| / _-- => preempt-depth
#||| / delay
#TASK-PID CPU#||||タイムスタンプ機能
#| | | |||| | |

関数トレーサーを有効にする

functionと呼ばれる最初のトレーサーを有効にすることができます functionを書くことによって current_tracerファイルに (以前のコンテンツはnopでした 、トレースがオフになったことを示します。)この操作は、トレースを有効にする方法と考えてください。

#pwd 
/ sys / kernel / traceing

#cat current_tracer
nop

#echo function> current_tracer

#cat current_tracer
function

関数トレーサーの更新されたトレース出力を表示する

トレースを有効にしたので、次は出力を表示します。 traceの内容を表示する場合 ファイルには、大量のデータが継続的に書き込まれているのがわかります。私は出力をパイプ処理し、現在、管理しやすいように上位20行のみを表示しています。左側の出力のヘッダーをたどると、どのタスクとプロセスIDがどのCPUで実行されているかを確認できます。出力の右側に、正確なカーネル関数が実行され、その後にその親関数が続くことがわかります。中央にはタイムスタンプ情報もあります:

#sudo cat trace |ヘッド-20

#トレーサー:関数

#entries-in-buffer / items-written:409936/4276216 #P:8

#_----- => irqs-off
#/ _---- => need-resched
# / _--- => hardirq / softirq
#|| / _-- => preempt-depth
#||| / delay
#TASK-PID CPU#||||タイムスタンプ機能
#| | | |||| | |
-0 [000] d ... 2088.841739:tsc_verify_tsc_adjust <-arch_cpu_idle_enter
-0 [000] d ... _ n <アイドル>-0[000] d ... 2088.841740:rcu_nocb_flush_deferred_wakeup <-do_idle
-0 [000] d ... 2088.841740:tick_check_broadcast_expired <-do_idle <-do_idle <-do_idle
-0 [000] d ... 2088.841740:cpuidle_not_available <-do_idle
000 [idle> -0 :cpuidle_select <-do_idle
-0 [000] d ... 2088.841741:menu_select <-do_idle
-0 [000] d ...

トレースがオンになっていることを忘れないでください。つまり、トレースをオフにするまで、トレースの出力はトレースファイルに書き込まれ続けます。

トレースをオフにする

トレースをオフにするのは簡単です。あなたがしなければならないのはfunctionを置き換えることだけです nopを使用したトレーサー current_tracerで ファイルとトレースがオフになります:

#cat current_tracer 
function

#echo nop> current_tracer

#cat current_tracer
nop

function_graphトレーサーを有効にする

次に、function_graphという2番目のトレーサーを試してください。 。以前と同じ手順を使用してこれを有効にできます:write function_graph current_tracerへ ファイル:

#echo function_graph> current_tracer 

#cat current_tracer
function_graph

function_graphトレーサーの出力のトレース

traceの出力形式に注意してください ファイルが変更されました。これで、CPUIDとカーネル関数の実行期間を確認できます。次に、関数の始まりとその中から呼び出された他の関数を示す中括弧が表示されます。

#猫のトレース|ヘッド-20

#トレーサー:function_graph

#CPU DURATION FUNCTION CALLS
#| | | | | | |
6)| n_tty_write(){
6)| down_read(){
6)| __cond_resched(){
6)0.341 us | rcu_all_qs();
6)1.057 us | }
6)1.807 us | }
6)0.402 us | process_echoes();
6)| add_wait_queue(){
6)0.391 us | _raw_spin_lock_irqsave();
6)0.359 us | _raw_spin_unlock_irqrestore();
6)1.757 us | }
6)0.350 us | tty_hung_up_p();
6)| mutex_lock(){
6)| __cond_resched(){
6)0.404 us | rcu_all_qs();
6)1.067 us | }

トレース設定を有効にして、トレースの深さを増やします

以下の手順を使用して、いつでもトレーサーを微調整して、関数呼び出しの詳細を確認できます。その後、traceの内容を表示できます ファイルを作成し、出力が少し詳細になっていることを確認します。読みやすくするために、この例の出力は省略されています:

#cat max_graph_depth 
0

#echo 1> max_graph_depth ##または:
#echo 2> max_graph_depth

#sudo cat trace

トレースする関数の検索

上記の手順は、トレースを開始するのに十分です。ただし、生成される出力の量は膨大であり、関心のあるアイテムを見つけようとしているときに迷子になることがよくあります。多くの場合、特定の機能のみをトレースし、残りを無視する機能が必要です。しかし、正確な名前がわからない場合、どのプロセスをトレースするかをどのようにして知ることができますか?これに役立つファイルがあります— available_filter_functions トレースに使用できる関数のリストを提供します:

#wc -l available_filter_functions 
63165 available_filter_functions

一般的なカーネル関数を検索する

次に、知っている単純なカーネル関数を検索してみてください。ユーザースペースにmallocがあります カーネルにkmallocがある間、メモリを割り当てます 同様の機能を提供する関数。以下はすべてのkmallocです 関連機能:

#grep kmalloc available_filter_functions 
debug_kmalloc
mempool_kmalloc
kmalloc_slab
kmalloc_order
kmalloc_order_trace
kmalloc_fix_flags
kmalloc_large_node
__ kmalloc> __ kmalloc_track_caller
__ kmalloc_node
__ kmalloc_node_track_caller
[...]

カーネルモジュールまたはドライバー関連の機能を検索する

available_filter_functionsの出力から 、[kvm_intel]のように、角かっこで囲まれたテキストで終わる行がいくつか表示されます。 以下の例では。これらの関数は、カーネルモジュールkvm_intelに関連しています。 、現在ロードされています。 lsmodを実行できます 確認するコマンド:

#grep kvm available_filter_functions | tail 
__ pi_post_block [kvm_intel]
vmx_vcpu_pi_load [kvm_intel]
vmx_vcpu_pi_put [kvm_intel]
pi_pre_block [kvm_intel]
pi_post_block [kvm_intel]
pi br /> pi_has_pending_interrupt [kvm_intel]
pi_update_irte [kvm_intel]
vmx_dump_dtsel [kvm_intel]
vmx_dump_sel [kvm_intel]

#lsmod | grep -i kvm
kvm_intel 335872 0
kvm 987136 1 kvm_intel
irqbypass 16384 1 kvm

トレース固有の機能のみ

特定の機能またはパターンのトレースを有効にするには、set_ftrace_filterを利用できます。 上記の出力からトレースする関数を指定するファイル。

このファイルは、*も受け入れます。 パターン。指定されたパターンの追加機能を含むように拡張されます。例として、私はext4を使用しています 私のマシン上のファイルシステム。 ext4を指定できます 次のコマンドを使用してトレースする特定のカーネル関数:

#マウント| grep home 
/ dev / mapper / fedora-home on / home type ext4(rw、relatime、seclabel)

#pwd
/ sys / kernel / traceing

#cat set_ftrace_filter

####すべての機能が有効になっています####
$
$ echo ext4_ *> set_ftrace_filter
$
$ cat set_ftrace_filter
ext4_has_free_clusters
ext4_validate_block_bitmap
ext4_get_group_number
ext4_get_group_no_and_offset
ext4_get_group_desc
[...]

これで、トレース出力を表示すると、関数ext4のみが表示されます。 以前にフィルターを設定したカーネル関数に関連します。他のすべての出力は無視されます:

#cat trace | head -20 

## tracer:function

#entries-in-buffer / items-written:3871/3871#P:8

#_----- => irqs-off
#br /> _ ---- => / _--- => hardirq / softirq
#|| / _-- => preempt-depth
#||| / delay
#TASK-PID CPU#||||タイムスタンプ機能
#| | | |||| | |
cupsd-1066 [004] .... 3308.989545:ext4_file_getattr <-vfs_fstat
cupsd-1066 [004] .... 3308.989547:ext4_getattr <-ext ] .... 3308.989552:ext4_file_getattr <-vfs_fstat
cupsd-1066 [004] .... 3308.989553:ext4_getattr <-ext4_file_getattr
900 .. do_dentry_open
cupsd-1066 [004] .... 3308.990111:ext4_file_getattr <-vfs_fstat
get cupsd-1066 [004] .... 3308.990111:ext4 _ get ] .... 3308.990122:ext4_llseek <-ksys_lseek
cupsd-1066 [004] .... 3308.990130:ext4_file_read_iter <-new_sync_read

関数のトレースを除外する

何をトレースしたいのかを常に知っているわけではありませんが、何をトレースしたくないのかは確かにわかっています。そのために、適切な名前のset_ftrace_notraceという名前のこのファイルがあります。 —そこに「いいえ」があることに注意してください。このファイルに希望のパターンを書き込んでトレースを有効にすると、上記のパターン以外のすべてがトレースされます。これは、出力を乱雑にする一般的な機能を削除するのに役立つことがよくあります。

#cat set_ftrace_notrace 
####無効になっている機能はありません####

ターゲットトレース

これまで、カーネルで発生したすべてのことを追跡してきました。ただし、特定のコマンドに関連するイベントを追跡する場合は、役に立ちません。これを実現するには、オンデマンドでトレースのオンとオフを切り替え、その間に、選択したコマンドを実行して、トレース出力で余分な出力が得られないようにします。 1と書くと、トレースを有効にできます tracing_onへ 、および0 オフにするには:

#cat trace_on 
0

#echo 1> trace_on

#cat trace_on
1

## #ここでトレースしたい特定のコマンドを実行します###

#echo 0> trace_on

#cat trace_on
0

特定のPIDのトレース

すでに実行されている特定のプロセスに関連するアクティビティをトレースする場合は、そのPIDをset_ftrace_pidという名前のファイルに書き込むことができます。 次に、トレースを有効にします。このように、トレースはこのPIDのみに制限されます。これは、場合によっては非常に役立ちます。

 # echo $PID > set_ftrace_pid 

結論

Ftrace Linuxカーネルの内部動作についてさらに学ぶための優れた方法です。少し練習すれば、ftraceを微調整する方法を学ぶことができます。 検索を絞り込みます。 ftraceを理解するには 詳細とその高度な使用法については、ftraceのコア作成者によって書かれたこれらの優れた記事を参照してください。 自分自身—スティーブン・ロステット。

  • Linuxカーネルのデバッグ、パート1
  • Linuxカーネルのデバッグ、パート2
  • Linuxカーネルのデバッグ、パート3

Linux
  1. GNUbcを使用してLinuxシェルで数学を実行します

  2. Linuxカーネルの継続的インテグレーションテスト

  3. QEMU を使用した Linux カーネルのデバッグ

  1. Linuxcronコマンドを使用したタスクのスケジューリング

  2. Linuxカーネル:イノベーショントップ5

  3. Linuxカーネルテストのライフサイクル

  1. Linuxatコマンドでタスクをスケジュールする

  2. Linux –カーネルメーリングリストに参加していますか?

  3. GDB と QEMU を使用して Linux カーネルをデバッグするには?