オペレーティングシステムのカーネルは、世の中で最もとらえどころのないソフトウェアの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に基づいてファイルから生成されたトレース出力を読み取ります。
- ファイルから以前の出力またはバッファをクリアします。
- 特定のユースケース(トレースするカーネル関数)に絞り込み、手順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
nopfunction_graphトレーサーを有効にする
次に、
function_graph
という2番目のトレーサーを試してください。 。以前と同じ手順を使用してこれを有効にできます:writefunction_graph
current_tracer
へ ファイル:#echo function_graph> current_tracer
#cat current_tracer
function_graphfunction_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