Red Hat Training

A Red Hat training course is available for Red Hat Enterprise Linux

SystemTap ビギナーズガイド

Red Hat Enterprise Linux 7

SystemTap の概要

William Cohen

Red Hat Software Engineering

Don Domingo

Red Hat Customer Content Services

Vladimír Slávik

Red Hat Customer Content Services

Robert Kratky

Red Hat Customer Content Services

Jacquelynn East

Red Hat Customer Content Services

概要

本ガイドでは、SystemTap を使用して Red Hat Enterprise Linux 7 の各種サブシステムを監視する基本的な手順を説明します。『『SystemTap ビギナーズガイド』は https://www.redhat.com/en/services/training/ex200-red-hat-certified-system-administrator-rhcsa-exam、RHCSA』 試験を取得した場合や、Red Hat Enterprise Linux 7 と同様のレベルの専門知識を持つユーザーに推奨されます。

第1章 はじめに

SystemTap は、オペレーティングシステム(特にカーネル)の動作を詳細に観察および監視できる追跡およびプロービングのツールです。これは、netstat、ps、top 、iostat などのツールの出力に似た情報を提供します。ただし、SystemTap は収集した情報に対して、より多くのフィルタリングと分析オプションを提供するように設計されています。
SystemTap は、システム管理者により、Red Hat Enterprise Linux 5 以降のパフォーマンス監視ツールとして使用できます。これは、その他の類似ツールがシステムのボトルネックを正確に特定できない場合に役立ちます。したがって、システムアクティビティーの深い分析が必要になります。同様に、アプリケーション開発者は SystemTap を使用して、アプリケーションが Linux システム内でどのように動作するかを詳細に監視することもできます。

1.1. 本ガイドの目的

SystemTap は、分析を詳細に行うために、稼働中の Linux システムを監視するインフラストラクチャーを提供します。これは、管理者や開発者がバグやパフォーマンス問題の根本的な原因を特定する手助けとなります。
SystemTap を使用しないで、実行中のカーネルのアクティビティーを監視しようとすると、インストルメント化、再コンパイル、インストール、および再起動という面倒なプロセスが必要になります。SystemTap はこれを回避し、ユーザーが作成する SystemTap スクリプトを実行するだけで同じ情報を収集できるように設計されました。
ただし、SystemTap は当初、Linux カーネルに関する詳細な知識を持つユーザー向けに設計されました。これにより、SystemTap は、カーネルに関する知識や経験があまりない管理者または開発者にとって少なくなります。さらに、既存の SystemTap ドキュメントのほとんどは、同様に知識と経験のあるユーザーを対象としています。
このバリアを軽減するために、SystemTap ビギナーズガイドでは』、以下の目的が書かれています。
  • SystemTap の概要を紹介するほか、ユーザーにアーキテクチャーについて説明し、すべてのカーネルタイプの設定手順を提供します。
  • 異なるコンポーネントのシステムで詳細なアクティビティーを監視するための事前作成された SystemTap スクリプトを提供し、それらの実行方法と出力の分析方法を提供します。

1.2. SystemTap の機能

SystemTap は当初、dprobe Linux Trace Toolkit などの以前の Linux のプローブツールと同様の Red Hat Enterprise Linux の機能を提供するために開発されました。SystemTap は、カーネルアクティビティーを追跡するインフラストラクチャーを使ってユーザーを提供することで、Linux 監視ツールの既存のスイートを補完することを目的としています。また、SystemTap はこの機能を 2 つの属性と組み合わせます。
  • 柔軟性 - SystemTap のフレームワークを使用すると、ユーザーは各種のカーネル機能、システムコール、カーネルスペースで発生するその他のイベントについて調査および監視目的のシンプルなスクリプトを開発できます。つまり、SystemTap はツールというよりも、独自のカーネル固有のフォレンジックおよび監視ツールの開発を可能にするシステムといえます。
  • 容易な使用: 上記で説明したように SystemTap を使用すると、ユーザーはカーネルプロセスのインストルメント化、再コンパイル、インストール、および再起動という面倒なプロセスをやり直すことなく、カーネルスペースのイベントをプローブできるようになります。
「」で挙げられている SystemTap スクリプトのほとんどは、他の同様のツール (top、OProfile、ps など) 4章便利な SystemTap スクリプトこれらのスクリプトは、SystemTap のアプリケーションの豊富な例を示すために提供されており、これにより、独自の SystemTap スクリプト作成時に使用可能な機能について学ぶことができます。

第2章 SystemTap の使用

本章では、SystemTap のインストール方法と SystemTap スクリプトの実行方法を説明します。

2.1. インストールと設定

SystemTap をデプロイするには、SystemTap パッケージと対応するカーネルの -devel-debuginfo、および -debuginfo-common-arch パッケージがインストールされている必要があります。システムに複数のカーネルがインストールされている複数のカーネルで SystemTap を使用するには、それらのカーネルバージョンごとに -devel および -debuginfo パッケージをインストールします。
これらの手順は、以下のセクションで詳細に説明します。
重要
多くのユーザーは、-debug パッケージと -debuginfo を混同します。SystemTap のデプロイに必要となるのは、カーネルの -debuginfo パッケージのインストールであって、カーネルの -debug バージョンではない点に注意してください。

2.1.1. SystemTap のインストール

SystemTap をデプロイするには、root で以下のコマンドを実行して systemtap および systemtap-runtime パッケージをインストールします。
~]# yum install -y systemtap systemtap-runtime

2.1.2. 必要なカーネル情報パッケージのインストール

SystemTap は、カーネル内にインストルメンテーションを配置する(プローブする)ためにカーネルの情報が必要になります。この情報は、SystemTap がインストルメンテーションのコードを生成することを可能にし、一致する kernel-develkernel-debuginfo パッケージ、および kernel-debuginfo-common-arch パッケージに含まれています(arch はシステムのハードウェアプラットフォームであり 、uname -m コマンドを実行して判断することができます)。
kernel-devel パッケージはデフォルトの Red Hat Enterprise Linux リポジトリーから利用できますが、kernel-debuginfo および kernel-debuginfo-common-arch パッケージはデバッグリポジトリーから入手できます
必要なパッケージをインストールするには、システムのデバッグリポジトリーを有効にします
~]# subscription-manager repos --enable=rhel-7-variant-debug-rpms
上記のコマンドでは、使用している Red Hat Enterprise Linux システムのバリアントに応じて、variant を serverworkstation、または client に置き換えます。バリアントを確認するには、次のコマンドを使用します。
~]# cat /etc/redhat-release
Red Hat Enterprise Linux Server release 7.2 (Maipo)
kernel-develkernel-debuginfo、および kernel-debuginfo-common-arch パッケージのバージョン、バリアント、アーキテクチャーは、SystemTap とプローブされるカーネルと完全に一致する必要があります。現在システムが実行中のカーネルを確認するには、以下のコマンドを実行します。
uname -r
3.10.0-327.el7.x86_64
たとえば、AMD64 または Intel 64 マシン上のカーネルバージョン 3.10.0-327.4.4.el7 で SystemTap を使用する場合は、以下のパッケージをインストールする必要があります。
  • kernel-debuginfo-3.10.0-327.4.4.el7.x86_64.rpm
  • kernel-debuginfo-common-x86_64-3.10.0-327.4.4.el7.x86_64.rpm
  • kernel-devel-3.10.0-327.4.4.el7.x86_64.rpm
yum パッケージマネージャーを使用して、現在のカーネルで SystemTap の実行に必要なパッケージをインストールするには、root で以下のコマンドを実行します。
~]# yum install -y kernel-devel-$(uname -r) \
kernel-debuginfo-$(uname -r) \
kernel-debuginfo-common-$(uname -m)-$(uname -r)

2.1.3. 初期テスト

SystemTap でプローブするカーネルが現在使用中であれば、デプロイメントが成功したかどうかを直ちにテストできます。別のカーネルをプローブする場合は、再起動して適切なカーネルを読み込みます。
テストを開始するには、以下のコマンドを実行します。
stap -v -e 'probe vfs.read {printf("read performed\n"); exit()}'
このコマンドは単に、SystemTap に read performed を出力するように指示して、仮想ファイルシステムの読み込みが検出されたら適切に終了します。SystemTap が正常にデプロイされていれば、以下のような出力になります。
Pass 1: parsed user script and 45 library script(s) in 340usr/0sys/358real ms.
Pass 2: analyzed script: 1 probe(s), 1 function(s), 0 embed(s), 0 global(s) in 290usr/260sys/568real ms.
Pass 3: translated to C into "/tmp/stapiArgLX/stap_e5886fa50499994e6a87aacdc43cd392_399.c" in 490usr/430sys/938real ms.
Pass 4: compiled C into "stap_e5886fa50499994e6a87aacdc43cd392_399.ko" in 3310usr/430sys/3714real ms.
Pass 5: starting run.
read performed
Pass 5: run completed in 10usr/40sys/73real ms.
出力の最後の 3 行( Pass 5で開始)は、SystemTap がカーネルをプローブするインストルメンテーションを正常に作成できたこと、インストルメンテーションを実行したこと、プローブしているイベントを検出(今回の場合は仮想ファイルシステムの読み込み)、および有効なハンドラーを実行したこと(テキストをプリントし、エラーなしで終了)していることを示しています。

2.2. 他のコンピューター用のインストルメンテーション生成

ユーザーが SystemTap スクリプトを実行すると、そのスクリプトからカーネルモジュールが構築されます。次に SystemTap はモジュールをカーネルに読み込み、カーネルから直接指定されたデータを抽出できるようにします 手順3.1「SystemTap セッション」 )。
通常、SystemTap スクリプトは、SystemTap 「インストールと設定」。つまり、SystemTap を 10 台のシステムで実行するには、これら すべての システムに SystemTap をデプロイする必要があります。場合によっては、これは実現不可能または望ましくないこともあります。たとえば、企業のポリシーで管理者が、特定のマシンにコンパイラーやデバッグ情報を提供するパッケージのインストールが禁止され、SystemTap のデプロイメントができなくなります。
この問題を回避するには、クロスインストルメンテーション を使用します。これは、1 台のコンピューター上の SystemTap スクリプトから別のコンピューターで使用する SystemTap インストルメンテーションモジュールを生成するプロセスです。このプロセスは、以下の利点をもたらします。
  • 各種マシンのカーネル情報パッケージを単一のホストマシン にインストールできます。
  • 生成された SystemTap インストルメンテーションモジュールを使用するために各ターゲットマシンには 1 つのパッケージのみをインストールする必要があります: systemtap-runtime
重要
構築された インストルメンテーションモジュール が機能するには、ホストシステム と同じ Linux ディストリビューションを使用してホスト システム として同じ Linux ディストリビューションを実行している必要があります。
注記
本セクションでは分かりやすくするために、以下の用語を使用します。
インストルメンテーションモジュール
SystemTap スクリプトから構築したカーネルモジュール。SystemTap モジュールは ホストシステム 上に構築され、ターゲットシステム の ターゲットカーネル に読み込まれます。
ホストシステム
ターゲットシステムに読み込むために(SystemTap スクリプトから)インストルメンテーションモジュールをコンパイルするシステム
ターゲットシステム
(SystemTap スクリプトから) インストルメンテーションモジュール を構築するシステム。
ターゲットカーネル
ターゲットシステム のカーネル。このカーネルが インストルメンテーションモジュール の読み込み、実行を行います

手順2.1 ホストシステムとターゲットシステムの設定

  1. ターゲットシステムsystemtap-runtime パッケージをインストールします。
  2. ターゲットシステム で uname -r を実行して、各 ターゲットシステム で実行しているカーネルを確認します。
  3. SystemTap を ホストシステム にインストールします。インストルメンテーションモジュール は、ホストシステム 上でターゲットシステム用に構築されますSystemTap 「SystemTap のインストール」
  4. 上記で確認した ターゲットカーネル バージョンを使用して、説明した方法で ターゲットシステム にターゲットカーネルと関連パッケージをインストールします 「必要なカーネル情報パッケージのインストール」 。複数の ターゲットシステム で異なる ターゲットカーネル を使用している場合は、ターゲットシステム で使用しているカーネルごとにこのステップを繰り返します。
その後、(いずれの 手順2.1「ホストシステムとターゲットシステムの設定」 インストルメンテーションモジュール を ホストシステム に構築します。
インストルメンテーションモジュール を構築するには、ホストシステム で以下のコマンドを実行します(適切な値を指定してください)。
stap -r kernel_version script -m module_name -p4
ここでは、kernel_versionターゲットカーネルのバージョン (ターゲットマシンの uname -r の出力) を指し、script は インストルメンテーションモジュール に変換され、module _name はインストルメンテーションモジュール の任意の名前になります。
インストルメンテーションモジュール のコンパイルが完了したら、ターゲットシステムにコピーして、以下のコマンドを使用して読み込みます。
staprun module_name.ko
たとえば、simple.ko インストルメンテーションモジュール 3.10.0-327.4.4.el7 ターゲットカーネル用に simple.stp という名前の SystemTap スクリプトから作成するには、以下のコマンドを使用します。
stap -r 2.6.32-53.el6 -e 'probe vfs.read {exit()}' -m simple -p4
これにより、simple.ko という名前のモジュールが作成されます。simple.ko インストルメンテーションモジュールを使用するには 、ターゲットシステム にコピーして、(ターゲットシステム 上で)以下のコマンドを実行します
staprun simple.ko

2.3. SystemTap スクリプトの実行

SystemTap スクリプトは、stap コマンドで実行されます。stap は、標準入力またはファイルから SystemTap スクリプトを実行できます。
stap および staprun を実行するには、システムに対する権限の昇格が必要になります。ただし、すべてのユーザーが SystemTap 実行のためだけに root アクセスを付与されるわけではありません。たとえば、権限のないユーザーが自身のマシン上で SystemTap インストルメンテーションを実行する必要がある場合もあります。
通常のユーザーが root アクセスなしで SystemTap を実行できるようにするには、ユーザーを以下の両方のユーザーグループに追加します。
stapdev
このグループのメンバーは stap を使用して SystemTap スクリプトを実行したり、staprun を使用して SystemTap インストルメンテーションモジュールを実行したりできます。
stap の実行では、SystemTap スクリプトがカーネルモジュールにコンパイルされ、それがカーネルに読み込まれます。これにはシステムに対する権限の昇格が必要となり、stapdev メンバーにはそれが付与されます。ただし、この権限は stapdev メンバーに有効な root アクセスも付与することになります。そのため、stapdev グループのメンバーシップは、root アクセスを信頼して付与できるメンバーにのみ許可してください。
stapusr
このグループのメンバーが SystemTap インストルメンテーションモジュールの実行に使用できるのは、staprun のみです。さらに、これらのモジュールは /lib/modules/kernel_version/systemtap/ からしか実行できません。このディレクトリーを所有できるのは root ユーザーのみで、書き込みが可能なのは root ユーザーのみでなければならない点に注意してください。
SystemTap スクリプトの実行
SystemTap スクリプトを実行するには、ユーザーは stapdev と stapusr の両方のグループに属する必要があります
以下は、一般的に使用される stap オプションの一覧です。
-v
SystemTap セッションの出力をさらに詳細なものにします。このオプション (たとえば、stap -vvv script.stp)は繰り返し繰り返し、スクリプトの実行に関する詳細情報を提供します。スクリプトの実行中にエラーが発生すると、これは特に便利です。
SystemTap スクリプトの一般的なエラーに関する詳細は、5章SystemTap のエラーを理解する
-o filename
標準出力を filename に送信します。
-s size、count
ファイルのサイズを size メガバイトに制限し、ファイル数を count の数に制限します。ファイル名には、連続番号の接尾辞が付きます。このオプションは、SystemTap に logrotate 演算を実装します。
-o と併用すると、-S はログファイルのサイズを制限します。
-x process ID
SystemTap ハンドラー関数の target() を指定されたプロセス ID に設定します。target() の詳細は SystemTap 関数
-c command
SystemTap ハンドラー関数の target() を指定されたコマンドに設定します。指定コマンドへのフルパスを使用する必要があります。たとえば、cp を指定する代わりに、/bin/cp を使用します (stap スクリプト -c /bin/cp)。target() の詳細は、SystemTap 関数
-e 'script'
systemtap 翻訳の入力に、ファイルではなくスクリプト文字列を使用します
-F
SystemTap のフライトレコーダーモードを使用し、スクリプトをバックグラウンドプロセスにします。フライトレコーダーモードの詳細は、「SystemTap フライトレコーダーモード」
stap は、- スイッチを使用して標準入力からスクリプトを実行するように指示することも可能です。例を示します。

例2.1 標準入力からスクリプトを実行

echo "probe timer.s(1) {exit()}" | stap -
例2.1「標準入力からスクリプトを実行」 stap に対し、echo で標準入力に渡したスクリプトを実行するように指示します。使用する stap オプションは - スイッチの前に挿入する必要があります。たとえば、例2.1「標準入力からスクリプトを実行」、コマンドは以下のようになります。
echo "probe timer.s(1) {exit()}" | stap -v -
stap の詳細は、man stap を参照してください
SystemTap インストルメンテーション(クロスインストルメンテーション中に SystemTap スクリプトから構築されたカーネルモジュール)を実行するには、代わりに staprun を使用します。staprun 「他のコンピューター用のインストルメンテーション生成」
注記
stap オプション -v および -ostaprun で機能します。staprun の詳細は、staprun(1) の man ページを参照してください。

2.3.1. SystemTap フライトレコーダーモード

SystemTap のフライトレコーダーモードを使用すると、SystemTap スクリプトは長期間の実行が可能になり、最近の出力のみにフォーカスできます。フライトレコーダーモード (-F オプション)は、生成された出力の量を制限します。フライトレコーダーモードには、メモリー内モードとファイルモードという 2 つのバリエーションがあります。どちらの場合も、SystemTap スクリプトはバックグラウンドプロセスとして実行されます。

2.3.1.1. メモリー内フライトレコーダー

フライトレコーダーモード (-F オプション)がファイル名なしで使用されると、SystemTap はカーネルメモリー内のバッファーを使用してスクリプトの出力を保存します。次に、SystemTap インストルメンテーションモジュールが読み込まれてプローブの実行が開始し、インストルメンテーションが外されてバックグラウンドに置かれます。関心のあるイベントが発生すると、インストルメンテーションは再度アタッチされ、メモリーバッファー内の最近の出力と継続中の出力が表示されます。以下のコマンドは、フライトレコーダーのメモリー内モードを使用してスクリプトを開始します。
stap -F /usr/share/doc/systemtap-version/examples/io/iotime.stp
スクリプトが開始されると、実行中のスクリプトに再接続するためのコマンドを示すメッセージが表示されます。
Disconnecting from systemtap module. To reconnect, type "staprun -A stap_5dd0073edcb1f13f7565d8c343063e68_19556"
関心のあるイベントが発生したら、実行中のスクリプトに再度アタッチしてメモリーバッファー内の最近のデータを出力し、継続中の出力を得るために、以下のコマンドを使用します。
staprun -A stap_5dd0073edcb1f13f7565d8c343063e68_19556
カーネルバッファーはデフォルトで 1MB のサイズですが、バッファーのメガバイト(2 の次の機能まで)のサイズを指定する -s オプションを使用して増やすことができます。たとえば、SystemTap コマンドライン上で -s2 により、バッファーに 2MB を指定します。

2.3.1.2. ファイルフライトレコーダー

フライトレコーダーモードは、ファイルにデータを保存することもできます。保持するファイルの数とサイズは、-S オプションの後にコンマ区切りの 2 つの数字の引数を続けて制御します。最初の引数は、各出力ファイルの最大サイズ(メガバイト)です。2 つ目の引数は、保存する最新ファイルの数です。ファイル名は、-o オプションの後に名前を付けて指定します。SystemTap は数値の接尾辞をファイル名に付けてファイルの順序を示します。以下で SystemTap がファイルフライトレコーダーモードで開始され、出力は /tmp/pfaults.log.[0-9]+ という名前のファイルに保存されます。各ファイルのサイズは 1MB 以下となり、最新の 2 つのファイルが保存されます。
stap -F -o /tmp/pfaults.log -S 1,2 pfaults.stp
コマンドがプリントする数字は、プロセス ID です。プロセスに SIGTERM を送信すると、SystemTap スクリプトがシャットダウンされ、データ収集が停止します。たとえば、以前のコマンドでプロセス ID が 7590 となっている場合、以下のコマンドで SystemTap スクリプトをシャットダウンします。
kill -s SIGTERM 7590
スクリプトが生成した最新の 2 ファイルのみが保存され、それより古いファイルは削除されます。そのため、ls -sh /tmp/pfaults.log.* には、以下の 2 つのファイルのみが表示されます。
1020K /tmp/pfaults.log.5 44K /tmp/pfaults.log.6
最新のデータについて最も大きな数ファイルを確認する場合は、/tmp/pfaults.log.6 になります。

第3章 SystemTap の作動方法

SystemTap を使うとユーザーはシンプルなスクリプトを作成および再使用して、実行中の Linux システムのアクティビティーを徹底的に調べることができます。このスクリプトは、データを抽出し、フィルターをかけ、素早く安全にデータをまとめるように設計できます。これにより、複雑なパフォーマンス (または機能的な) 問題の診断が可能になります。
SystemTap スクリプトにおける本質的な考えは、イベント に名前を付け、それに ハンドラーを与えることです。SystemTap がスクリプトを実行すると、SystemTap はイベントを監視します。イベントが発生したら、Linux カーネルがハンドラーをサブルーチンとして実行し、通常の操作を再開します。
イベントには関数、タイマーの有効期限、セッション終了などはいくつかのイベントがあります。ハンドラーは一連のスクリプト言語のステートメントで、イベント発生時に実行する作業を指定します。この作業には通常、イベントコンテキストからのデータ抽出、それらの内部変数への保存、結果のプリントなどが含まれます。

3.1. アーキテクチャー

SystemTap のセッションは、SystemTap スクリプトを実行すると始まります。このセッションは、以下の順番で生じます。

手順3.1 SystemTap セッション

  1. SystemTap はまず、使用されている tapset について既存の tapset ライブラリー(通常は /usr/share/systemtap/tapset/ ディレクトリー)に対してスクリプトをチェックします。次に SystemTap は、見つかった tapset を tapset ライブラリー内の対応する定義に置き換えます。
  2. SystemTap はスクリプトを C に変換し、システム C コンパイラーを実行してそこからカーネルモジュールを作成します。このステップを実行するツールは、systemtap パッケージに含まれています 「SystemTap のインストール」 を参照してください)。
  3. SystemTap はモジュールを読み込み、スクリプト内の全プローブ(イベントおよびハンドラー)を有効にします。systemtap-runtime パッケージ内の staprun 「SystemTap のインストール」 を参照)は、この機能を提供します。
  4. イベントが発生すると、それに対応するハンドラーが実行されます。
  5. SystemTap セッションが終了すると、プローブは無効になり、カーネルモジュールはアンロードされます。
このシーケンスは、1 つのコマンドラインプログラム (stap)で実行されます。このプログラムは、SystemTap のメインのフロントエンドツールです。stap の詳細は、stap(1) の man ページ(SystemTap がマシンに適切にインストールされている)を参照してください。

3.2. SystemTap スクリプト

SystemTap スクリプトはそのほとんどにおいて、各 SystemTap セッションのベースになっています。SystemTap スクリプトが SystemTap に対してどのタイプの情報を収集するか、収集後に何をするかを指示します。
3章SystemTap の作動方法」の説明にあるように、SystemTap スクリプトは イベントハンドラー という 2 つのコンポーネントで構成されています。SystemTap セッションが開始されたら、SystemTap はオペレーティングシステムで指定されたイベントを監視し、イベントが発生したらハンドラーを実行します。
注記
イベントとそれに対応するハンドラーは、まとめて プローブ と呼ばれます。SystemTap スクリプトには複数のプローブを備えることができます。プローブのハンドラーは一般的に プローブボディー と呼ばれます。
アプリケーションの開発という面では、イベントとハンドラーの使用は診断プリントステートメントをコマンドのプログラムシーケンスに挿入するというコードのインストルメント化に似ています。診断プリントステートメントを使用すると、プログラムの実行後に発行されたコマンドの履歴をみることができます。
SystemTap スクリプトでは、コードを再コンパイルすることなくインストルメンテーションコードの挿入が可能で、ハンドラーに関する柔軟性が広がります。イベントは、ハンドラー実行の引き金となります。ハンドラーは指定されたデータを記録して、特定の方法でプリントするよう指定できます。

形式

SystemTap スクリプトは、.stp ファイル拡張子を使用し、以下の書式のプローブを含んでいます。

probe event {statements}
SystemTap はプローブごとに複数のイベントをサポートしており、複数のイベントはコンマ(,)で区切ります。1 つのプローブで複数のイベントが指定された場合、SystemTap は指定されたイベントが発生するとハンドラーを実行します。
プローブにはそれぞれ、対応する ステートメントブロック があります。このステートメントブロックは中括弧({ })で囲まれており、イベントごとに実行されるステートメントが含まれています。SystemTap はこれらのステートメントを順番に実行し、通常は複数のステートメントを分ける特別な区切り文字やターミネーターは必要ありません。
注記
SystemTap スクリプト内のステートメントブロックは、C プログラミング言語と同じ構文とセマンティクスを使用します。ステートメントブロックは、別のステートメントブロック内の入れ子状態にすることができます。
Systemtap では、多くのプローブが使用するコードを外に括り出して関数を作成することができます。そのため、複数のプローブで同じステートメントを何度も繰り返し書くのではなく、以下のように関数に命令を配置することができます
function function_name(arguments){statements}
probe event {function_name(arguments)}
in function_name のステートメントは 、イベントの実行プローブの実行時に実行されますarguments は、function に渡されるオプションの値です。
重要
「SystemTap スクリプト」 では、SystemTap スクリプトの基本を説明します。SystemTap 4章便利な SystemTap スクリプト、スクリプト、イベント、ハンドラー、および予想される出力について詳細に説明しています。

3.2.1. Event

SystemTap のイベントは大まかに、同期非同期 に分けられます。

同期イベント

同期 イベントは、プロセスがカーネルコード内の特定の場所で指示を実行する際に発生します。これは他のイベントの参照ポイントとなり、ここからさらにコンテキストデータが入手可能になります。

同期イベントの例には以下のようなものがあります。
syscall.system_call
システムコール system_call へのエントリー。システムコールの終了を希望する場合は、.return をイベントに追加すると、システムコールの終了を監視します。たとえば、close システムコールのエントリーと終了を指定するには、syscall.close および syscall.close.return をそれぞれ使用します。
vfs.file_operation
仮想ファイルシステム(VFS)の file_operation イベントへのエントリー。syscall イベントと同様に、イベントに .return を追加すると、file_operation 操作の終了を監視します。
kernel.function("function")
function カーネル関数へのエントリー。たとえば、kernel.function("sys_open") は、カーネル関数がシステム内のどのスレッドでも呼び出される際に発生するイベントを指しますsys_opensys_open カーネル関数の戻り値を指定するにはreturn 文字列をイベントステートメントに追加します。つまり、kernel.function("sys_open").return になります。
プローブイベントを定義するとき、ワイルドカードにアスタリスク(*)を使用できます。また、カーネルソースファイル内の関数のエントリーまたは終了も追跡可能です。以下の例を見てみましょう。

例3.1 wildcards.stp

probe kernel.function("*@net/socket.c") { }
probe kernel.function("*@net/socket.c").return { }
上記の例では、最初のプローブのイベントは net/socket.c カーネルソースファイル内のすべての関数のエントリーを指定します。2 つ目のプローブでは、これらすべての関数の終了を指定します。この例では、ハンドラーにステートメントがないことに注意してください。このため、情報が収集されず、表示されることもありません。
kernel.trace("tracepoint")
tracepoint の静的プローブ。最近のカーネル (2.6.30 以降) には、カーネル内の特定イベント用のインストルメンテーションが含まれています。これらのイベントは、トレースポイントで静的にマークされます。SystemTap で利用可能なトレースポイントの例としては kernel.trace("kfree_skb") があります。これは、カーネル内でネットワークバッファーが解放されるとは常に になります。
module("module").function("function")
モジュール内の関数のプローブを可能にします。以下に例を示します。

例3.2 moduleprobe.stp

probe module("ext3").function("*") { }
probe module("ext3").function("*").return { }
例3.2「moduleprobe.stp」 モジュールのすべての関数のエントリーを指しています。2 つ目のプローブは、同じモジュールのすべての関数の終了を指しています。.return の接尾辞の使用は、kernel.function() と似ています。例3.2「moduleprobe.stp」。このため、有用なデータは表示されません( 例3.1「wildcards.stp」)。
システムのカーネルモジュールは通常、/lib/modules/kernel_version にあり、kernel_version は現在読み込まれているカーネルバージョンを指します。モジュールは、ファイル名 extension.ko を使用します。

非同期イベント

非同期 イベントは、コード内の特定の指示や場所に関連付けられていません。このタイプのプローブポイントは、主にカウンターやタイマー、同様のコンストラクトで構成されています。

非同期イベントの例には以下のようなものがあります。
begin
SystemTap スクリプトが実行されるとすぐに SystemTap セッションが起動します。
終了
SystemTap セッションが終了します。
timer イベント
ハンドラーの定期実行を指定するイベントです。以下に例を示します。

例3.3 timer-s.stp

probe timer.s(4)
{
  printf("hello world\n")
}
例3.3「timer-s.stp」 は、4 秒ごとに hello world をプリントするプローブの例です。以下のような timer イベントも使用できます。
  • timer.ms(milliseconds)
  • timer.us(microseconds)
  • timer.ns(nanoseconds)
  • timer.hz(hertz)
  • timer.jiffies(jiffies)
情報を収集する他のプローブと併せて timer イベントを使用すると、定期的な更新を出力し、その情報が時間の経過と共にどのように変化するかを確認できます。
重要
SystemTap は、多数のプローブイベントの使用をサポートしています。サポートされるイベントの詳細は、stapprobes(3) の man ページを参照してください。stapprobes(3) の 『SEE ALSO』 セクションには、特定のサブシステムやコンポーネントでサポートされるイベントについて説明している他の man ページへのリンクも含まれています。

3.2.2. SystemTap ハンドラー/ボディー

以下のサンプルスクリプトを見てみましょう。

例3.4 helloworld.stp

probe begin
{
  printf ("hello world\n")
  exit ()
}
例3.4「helloworld.stp」begin イベント(セッションの開始)は { } で囲まれたハンドラーをトリガーします。これは単に hello world をプリントして新しい行を出力し、終了します。
注記
SystemTap スクリプトは、exit() 関数が実行されるまで継続されます。Ctrl+C で中断できます。

printf ( ) ステートメント

printf() ステートメントは、データの出力に関する最も簡単な関数の 1 つです。printf() 以下の形式で、多くの SystemTap 関数を使用してデータを表示するのにも使用できます。

printf ("format string\n", arguments)
format string は、引数の出力方法を指定します。の書式文字列は、SystemTap に hello world 例3.4「helloworld.stp」、書式指定子は含みません。
引数のリストに応じて、%s (文字列用)および %d (数字用)といった書式指定子を書式文字列で使用できます。書式文字列には複数の書式指定子を持て、それぞれを対応する引数に一致させます。複数の引数はコンマ(,)で区切ります。
注記
セマンティック的には、SystemTap printf 関数は、C 言語の関数に非常に似ています。上記の SystemTap の printf 関数における構文と書式は、C 言語の printf と同一のものです。
以下のプローブの例を見てみましょう。

例3.5 variables-in-printf-statements.stp

probe syscall.open
{
  printf ("%s(%d) open\n", execname(), pid())
}
例3.5「variables-in-printf-statements.stp」 では、SystemTap がシステムコールへの全エントリーをプローブするように指示し、現在の execname() (実行可能ファイル名を持つ文字列)と pid() (現在のプロセス ID 番号)の後に open という単語を出力します。このプローブ出力の抜粋は以下のようになります。
vmware-guestd(2206) open
hald(2360) open
hald(2360) open
hald(2360) open
df(3433) open
df(3433) open
df(3433) open
hald(2360) open

SystemTap 関数

SystemTap は、printf() 引数として使用できる多くの関数をサポートしています。例3.5「variables-in-printf-statements.stp」 SystemTap 関数 execname() (カーネル関数 / システム呼び出しを実行したプロセスの名前)と pid() (現在のプロセス ID)を使用します。

一般的に使用される SystemTap 関数を以下に挙げます。
tid()
現行スレッドの ID。
uid()
現行ユーザーの ID。
cpu()
現行の CPU 番号。
gettimeofday_s()
Unix epoch (1970 年 1 月 1 日) からの秒数。
ctime()
UNIX epoch からの秒数を日にちに換算。
pp()
現在処理されているプローブポイントを記述する文字列。
thread_indent()
この関数はプリント結果をうまく整理するので、便利なものです。この関数はインデント差分の引数を取ります。これは、スレッドの「インデントカウンター」に追加する、またはそこから取り除くスペースの数を示すものです。その後、適切なインデントスペースの数と一般的な追跡データの文字列を返します。
返された文字列の一般的なデータには、タイムスタンプ(スレッドの thread_indent() への最初の呼び出しからのマイクロ秒)、プロセス名、およびスレッド ID が含まれます。これによりどの関数が呼び出されたか、誰が呼び出したか、各関数呼び出しの長さが特定できます。
相互に呼び出し、即座に終了する場合は、エントリーを簡単に一致させることができます。ただし、ほとんどの場合、最初の関数呼び出しエントリーが作成されると、最初の呼び出しの終了前に他の複数の呼び出しがエントリーおよび終了することがあります。インデントカウンターは、次の関数呼び出しをインデントして、前の呼び出しが終了していない場合、エントリーと対応する終了と一致するのに役立ちます。
thread_indent() の使用例を以下に示します。

例3.6 thread_indent.stp

probe kernel.function("*@net/socket.c") 
{
  printf ("%s -> %s\n", thread_indent(1), probefunc())
}
probe kernel.function("*@net/socket.c").return 
{
  printf ("%s <- %s\n", thread_indent(-1), probefunc())
}
例3.6「thread_indent.stp」 は、各イベントでの thread_indent() および probe 関数を次の形式で出力します。
0 ftp(7223): -> sys_socketcall
1159 ftp(7223):  -> sys_socket
2173 ftp(7223):   -> __sock_create
2286 ftp(7223):    -> sock_alloc_inode
2737 ftp(7223):    <- sock_alloc_inode
3349 ftp(7223):    -> sock_alloc
3389 ftp(7223):    <- sock_alloc
3417 ftp(7223):   <- __sock_create
4117 ftp(7223):   -> sock_create
4160 ftp(7223):   <- sock_create
4301 ftp(7223):   -> sock_map_fd
4644 ftp(7223):    -> sock_map_file
4699 ftp(7223):    <- sock_map_file
4715 ftp(7223):   <- sock_map_fd
4732 ftp(7223):  <- sys_socket
4775 ftp(7223): <- sys_socketcall
このサンプル出力には、以下の情報が含まれています。
  • スレッドの最初の thread_indent() 呼び出しからの時間(マイクロ秒単位)。
  • 関数呼び出しを実施したプロセス名(およびその対応する ID)。
  • 呼び出しがエントリー(<-)か終了(->)かを示す矢印。インデントがあることで、特定の関数呼び出しのエントリーとそれに対応する終了が一致しやすくなります。
  • プロセスが呼び出した関数名。
名前
特定のシステムコールの名前を識別します。この変数は、イベント syscall.system_call を使用するプローブでのみ使用できます。
target()
以下の 2 つのコマンドのいずれかと併用されます。
stap script
-x process ID stap script -c command
プロセス ID またはコマンドの引数を取るスクリプトを指定したい場合、スクリプト内で参照先となる変数として target() を使用します。以下に例を示します。

例3.7 targetexample.stp

probe syscall.* {
  if (pid() == target())
    printf("%s/n", name)
}
argument -x プロセス ID を実行すると、( syscall.* イベントで指定された) 例3.7「targetexample.stp」
これは、特定のプロセスをターゲットとするたびに if (pid() == process ID) を指定するのと同じ効果を持ちます。ただし、target() を使用すると、スクリプトの再利用が容易になり、スクリプトを実行するたびに引数としてプロセス ID を渡すだけで済みます。以下に例を示します。
stap targetexample.stp -x process ID
サポートされる SystemTap 関数の詳細情報は、stapfuncs(3) を参照してください。

3.3. 基本的な SystemTap ハンドラーコンストラクト

SystemTap は、ハンドラーでいくつかの基本的なコンストラクトの使用をサポートしています。ほとんどのこれらのハンドラーコンストラクトの構文は、C と awk 構文に基づいています。本セクションでは、SystemTap ハンドラーコンストラクトで最も有用なものをいくつか説明します。これは、シンプルかつ便利な SystemTap スクリプトの作成を行うのに十分な情報を提供します。

3.3.1. 変数

ハンドラーでは、変数を自由に使うことができます。名前を選択し、関数もしくは式から値を割り当て、式内で値を使用します。SystemTap は、割り当てられた値のタイプに基づいて、自動的に変数が文字列か整数かを識別します。たとえば、( var = gettimeofday_s()で)変数 vargettimeofday_s() に設定した場合、var は数値として入力され、整数のフォーマット指定子(%d)を使用して printf() に出力できます。
ただしデフォルトでは、変数は使用されているプローブのみのローカルとなります。つまり、変数はプローブハンドラーが呼び出されるたびに初期化され、使用され、破棄されます。複数のプローブで変数を共有するには、プローブの外で global を使用して変数名を宣言します。以下の例を見てみましょう。

例3.8 timer-jiffies.stp

global count_jiffies, count_ms
probe timer.jiffies(100) { count_jiffies ++ }
probe timer.ms(100) { count_ms ++ }
probe timer.ms(12345)
{
  hz=(1000*count_jiffies) / count_ms
  printf ("jiffies:ms ratio %d:%d => CONFIG_HZ=%d\n",
    count_jiffies, count_ms, hz)
  exit ()
}
例3.8「timer-jiffies.stp」 jiffies およびミリ秒をカウントするタイマーを使用してカーネルの CONFIG_HZ 設定を計算し、それに応じて計算します。global ステートメントにより、スクリプトは変数 count_jiffies および count_ms (各プローブで設定)を probe timer.ms(12345) と共有できます。
注記
例3.8「timer-jiffies.stp」count_jiffies ++ および count_ms ++)の ++ 表記は、変数の値を 1 増やすために使用されます。以下のプローブで count_jiffies は、100 jiffies ごとに 1 つ増えます。
probe timer.jiffies(100) { count_jiffies ++ }
この場合、SystemTap は count_jiffies が整数であると理解します。count_jiffies には初期値が割り当てられていないため、デフォルトでは初期値はゼロになります。

3.3.2. 条件付き (conditional) ステートメント

場合によっては、SystemTap スクリプトの出力が大きすぎることがあるかもしれません。これに対処するには、スクリプトの論理を細分化して、出力をプローブに関連するもしくは有用なものにする必要があります。
これはハンドラーで 条件 を使うことで実行できます。SystemTap は以下のタイプの条件付きステートメントを受け付けます。
If/Else ステートメント
書式は以下のようになります。
if (condition)
  statement1
else
  statement2
condition 式がゼロ以外の場合、statement1 が実行されます。condition 式がゼロの場合、statement2 が実行されます。else 句(else statement2)は任意です。statement1statement2 は両方とも、ステートメントブロックになります。

例3.9 ifelse.stp

global countread, countnonread
probe kernel.function("vfs_read"),kernel.function("vfs_write")
{
  if (probefunc()=="vfs_read") 
    countread ++ 
  else 
    countnonread ++
}
probe timer.s(5) { exit() }
probe end 
{
  printf("VFS reads total %d\n VFS writes total %d\n", countread, countnonread)
}
例3.9「ifelse.stp」 は、5 秒間にシステムが実行する仮想ファイルシステムの読み込み(vfs_read)と書き込み(vfs_write)回数をカウントするスクリプトです。実行時に、プローブした関数の名前が(条件 if (probefunc()=="vfs_read")の) vfs_read と一致する場合、スクリプトは変数 countread の値を 1 つ増やします。それ以外の場合は、countnonread (else {countnonread ++})を増やします。
While ループ
書式は以下のようになります。
while (condition)
  statement
condition がゼロ以外の場合は、statement 内のステートメントのブロックが実行されます。statement はステートメントブロックであることが多く、condition が最終的にゼロとなるように値を変更する必要があります。
For ループ
書式は以下のようになります。
for (initialization; conditional; increment) statement
for ループは、単に while ループの短縮形です。以下は、同等の while ループです。
initialization
while (conditional) {
   statement
   increment
}

条件演算子

== のほかに、以下の演算子も条件付きステートメントに使用できます。

>=
より大か等しい
<=
より小か等しい
!=
等しくない

3.3.3. コマンドラインの引数

SystemTap スクリプトでは、$ または @ の直後にコマンドライン上の引数の番号を続けることで、単純なコマンドライン引数を受け付けるようにすることができます。コマンドライン引数としてユーザーが整数を入力すると思われる場合は $ を、文字列が期待される場合は @ を使用します。

例3.10 commandlineargs.stp

probe kernel.function(@1) { }
probe kernel.function(@1).return { }
例3.10「commandlineargs.stp」 例3.1「wildcards.stp」また、@1@2 のように、ユーザーが入力した順番で複数のコマンドライン引数をスクリプトが受け付けるように指定することもできます。

3.4. 連想アレイ

SystemTap は、連想アレイの使用もサポートします。通常の変数は単一の値を表しますが、連想アレイでは値の集合を表すことができます。簡単に言うと、連想アレイは一意の鍵の集合です。アレイ内のそれぞれの鍵にそれに関連する値があります。
(後で紹介するように)連想アレイは通常複数のプローブで処理されるので、SystemTap スクリプトでは global 変数として宣言する必要があります。連想アレイ内の要素にアクセスする構文は、wk の同様であり、以下のようになります
array_name[index_expression]
ここで array_name は、アレイが使用する任意の名前です。index_expression は、アレイ内の特定の一意の鍵を確認するために使用されます。例として、tomdick、および harry という 3 人の年齢(一意の鍵)を指定する、arr という名前のアレイを構築してみましょう。以下のアレイステートメントを使用して、それぞれ 23、24、25 の年齢(関連する値)を割り当てます。

例3.11 基本的なアレイステートメント

arr["tom"] = 23
arr["dick"] = 24
arr["harry"] = 25
アレイステートメントで最大 9 つのインデックス表現を指定できます。それぞれをコンマ(,)で区切ります。これは、鍵に複数の情報が含まれる場合に便利です。例4.9「disktop.stp」 からの以下の行では、プロセス ID、実行可能ファイル名、ユーザー ID、親プロセスの ID、および文字列「W」という 5 つの要素を使用しています。ここでは、devname の値を鍵に関連付けています。
device[pid(),execname(),uid(),ppid(),"W"] = devname
重要
連想アレイは、1 つのプローブで使用されるか複数のプローブで使用されるかに関係なく、global として宣言する必要があります。

3.5. SystemTap でのアレイ演算

本セクションでは、SystemTap で使用される最も一般的なアレイ演算を説明しています。

3.5.1. 関連する値の割り当て

インデックス化された一意のペアに関連する値を設定するには、以下のように = を使用します。
array_name[index_expression] = value
例3.11「基本的なアレイステートメント」 では、明示的な関連する値を一意の鍵に設定する非常に基本的な例を示しています。index_expressionvalue の両方にハンドラー関数を使用することもできます。たとえば以下のように、アレイを使用して、タイムスタンプをプロセス名 (これを一意の鍵として使用) への関連する値として設定することができます。

例3.12 タイムスタンプをプロセス名に関連付ける

arr[tid()] = gettimeofday_s()
例3.12「タイムスタンプをプロセス名に関連付ける」、SystemTap は適切な tid() 値(つまり、スレッドの ID、一意の鍵として使用されます)を返します。同時に SystemTap は関数 gettimeofday_s() を使用して、対応するタイムスタンプを関数 tid() で定義されている一意の鍵への関連する値として設定します。これで、スレッド ID とタイムスタンプを含む鍵のペアで構成されるアレイが作成されます。
この例では、tid() がアレイ arr ですでに定義されている値を返すと、この演算子はその値に関連付けられている元の値を破棄し、gettimeofday_s() の現在のタイムスタンプで置き換えます。

3.5.2. アレイからの値の読み取り

アレイからの値の読み取りは、変数値の読み取りと同じ方法でできます。これを行うには、array_name[index_expression] ステートメントを数式に要素として含めます。以下に例を示します。

例3.13 単純計算でのアレイ値の使用

delta = gettimeofday_s() - arr[tid()]
この例では、(からの)コンストラクトを使用してアレイ arr 例3.12「タイムスタンプをプロセス名に関連付ける」。これで 参照ポイント となるタイムスタンプが設定され、delta の計算に使用されます
例3.13「単純計算でのアレイ値の使用」、現在の gettimeofday_s() から keytid() の関連する値を差し引くことで、変数 delta の値を計算します。このコンストラクトは、アレイから oftid() の値を読み取ること でこれを行います。このコンストラクトは、読み取り操作の開始と完了など、2 つのイベント間の時間を判定する際に便利なものです。
注記
index_expression が一意の鍵が見つからない場合は、デフォルトで 0 の値 例3.13「単純計算でのアレイ値の使用」)または null (空の文字列の操作の場合)文字列値を返します。

3.5.3. 関連する値の増加

アレイ内の一意の鍵の関連する値を増やすには、++ を使用します。
array_name[index_expression] ++
ここでも、index_expression にハンドラー関数を使用できます。たとえば、仮想ファイルシステムへの読み込み( vfs.read イベントを使用)を特定のプロセスが実行した回数を計算したい場合は、以下のプローブを使用します。

例3.14 vfsreads.stp

probe vfs.read
{
  reads[execname()] ++
}
例3.14「vfsreads.stp」 プローブがプロセス名 gnome-terminal(つまり、gnome-terminal の初回実行時に)、そのプロセス名は一意の鍵 gnome-terminal (関連する値 1)として設定されます。プローブがプロセス名 gnome-terminal を返した場合は、SystemTap は gnome-terminal の関連する値を 1 に増やします。SystemTap は、プローブがプロセス名を返す際にこの演算をすべてのプロセス名に対して実行します

3.5.4. アレイ内での複数要素の処理

アレイで十分な情報を収集したら、それを有用なものにするためにアレイで全要素を取得して処理する必要があります。例3.14「vfsreads.stp」、各プロセスが実行した VFS reads の数に関する情報を収集しますが、その情報をどうするか指定しません。例3.14「vfsreads.stp」reads アレイで鍵のペアを出力することです。
アレイ内の鍵のペアすべてを処理する最善の方法(反復として)は、foreach ステートメントを使用することです。以下の例を見てみましょう。

例3.15 cumulative-vfsreads.stp

global reads
probe vfs.read
{ 
  reads[execname()] ++
}
probe timer.s(3)
{
  foreach (count in reads)
    printf("%s : %d \n", count, reads[count])
}
の 2 例3.15「cumulative-vfsreads.stp」foreach ステートメントは count 変数を使用して reads アレイ内の一意の鍵の反復を参照します。同じプローブ内の reads[count] アレイステートメントは、一意の鍵の関連する値を取得します。
例3.15「cumulative-vfsreads.stp」 の最初のプローブでは、スクリプトは VFS-read の統計情報を 3 秒ごとにプリントし、VFS-read を実行したプロセス名とその回数を表示します。
foreach ステートメントは、アレイ内のプロセス名のすべての反復 例3.15「cumulative-vfsreads.stp」 をプリントすることに注意してください。また、特定の順番はない点にご留意ください。+ (昇順)または - (降順)を使用すると、スクリプトに特定の順番で反復を処理するようにスクリプトに指示することができます。さらに、limit value オプションを使うと、スクリプトがプロセスする反復数を制限することもできます。
以下の代替プローブ例を見てみましょう。
probe timer.s(3)
{
  foreach (count in reads- limit 10)
    printf("%s : %d \n", count, reads[count])
}
この foreach ステートメントは、スクリプトにアレイ reads 内の要素を(関連する値の)降順で処理するように指示します。limit 10 オプションは、foreach に最初の 10 の反復のみを処理するよう指示します(つまり、高い値から最初の 10 の反復のみをプリントします)。

3.5.5. アレイおよびアレイ要素の消去/削除

場合によっては、アレイ要素で関連する値を消去したり、別のプローブで再利用するためにアレイ全体をリセットする必要がある場合があります。例3.15「cumulative-vfsreads.stp」 「アレイ内での複数要素の処理」 では、プロセスが 1 回に発生する VFS reads 数を経時的に追跡することができますが、各プロセスが 3 秒間行う VFS reads の数は表示されません。
これを実行するには、アレイが累積した値を消去する必要があります。delete 演算子を使用してアレイ内の要素またはアレイ全体を削除すると、これを実行できます。以下の例を見てみましょう。

例3.16 noncumulative-vfsreads.stp

global reads
probe vfs.read
{ 
  reads[execname()] ++
}
probe timer.s(3)
{
  foreach (count in reads)
    printf("%s : %d \n", count, reads[count])
  delete reads	
}
例3.16「noncumulative-vfsreads.stp」 では、2 つ目のプローブが 調査した 3 秒間のみで 各プロセスが実行した VFS reads 数をプリントします。delete reads ステートメントは、プローブ内の reads アレイを消去します。
注記
同一プローブ内には、複数のアレイ演算を設置することが可能です。「アレイ内での複数要素の処理」 および 「アレイおよびアレイ要素の消去/削除」 の例を使用すると、3 秒間でプロセスが実行した VFS reads の数を追跡し、かつ それらのプロセスでの累積 VFS reads 数を集計することができます。以下の例を見てみましょう。
global reads, totalreads
probe vfs.read
{
  reads[execname()] ++
  totalreads[execname()] ++
}
probe timer.s(3)
{
  printf("=======\n")
  foreach (count in reads-) 
    printf("%s : %d \n", count, reads[count])
  delete reads
}
probe end
{
  printf("TOTALS\n")
  foreach (total in totalreads-)
    printf("%s : %d \n", total, totalreads[total])
}
この例では、readstotalreads のアレイが同じ情報を追跡し、同様の方式で出力されます。唯一の違いは、reads は 3 秒ごとに消去されるのですが、totalreads は増え続けるという点です。

3.5.6. 条件付きステートメントにおけるアレイの使用

連想アレイは if ステートメントでも使用することができます。これは、アレイ内の値が特定の条件に一致した場合にサブルーチンを実行するという場合に便利です。以下の例を見てみましょう。

例3.17 vfsreads-print-if-1kb.stp

global reads
probe vfs.read
{
  reads[execname()] ++
}
probe timer.s(3)
{
  printf("=======\n")
  foreach (count in reads-)
    if (reads[count] >= 1024)
      printf("%s : %dkB \n", count, reads[count]/1024)
    else
      printf("%s : %dB \n", count, reads[count])
}
例3.17「vfsreads-print-if-1kb.stp」 では、全プロセス一覧と各プロセスが VFS read を実行した回数が 3 秒ごとにプリントされます。プロセス名の関連する値が 1024 以上の場合、スクリプト内の if ステートメントがこれを変換し、kB でプリントします。

メンバーシップのテスト

特定の一意の鍵がアレイのメンバーかどうかをテストすることもできます。以下の例のように、if ステートメント内でアレイ内のメンバーシップを使用することも可能です。

if([index_expression] in array_name) statement
以下の例を見てみましょう。

例3.18 vfsreads-stop-on-stapio2.stp

global reads
probe vfs.read
{
  reads[execname()] ++
}
probe timer.s(3)
{
  printf("=======\n")
  foreach (count in reads+) 
    printf("%s : %d \n", count, reads[count])
  if(["stapio"] in reads) {
    printf("stapio read detected, exiting\n")
    exit()
  }
}
if(["stapio"] in reads) ステートメントは、一意の鍵 stapio がアレイ reads に追加されたら、stapio read detected, exiting をプリントするようにスクリプトに指示します。

3.5.7. 統計集計の計算

統計集計は、新規データを素早くかつ大量に累積(集計ストリーム統計情報のみ)することが重要な場合に、数的値の統計情報を収集するために使用されます。統計集計はグローバル変数またはアレイ内の要素として使用できます。
統計集計に値を追加するには、演算子 <<< value を使用します。

例3.19 stat-aggregates.stp

global reads	
probe vfs.read
{
  reads[execname()] <<< count
}
Operator <<< count 例3.19「stat-aggregates.stp」、reads アレイ内の対応する execname() の関連する値に count が返した容量を count に保存します。これらの値は 保存される のであって、各一意の鍵の関連する値に追加されたり、現行の関連する値に置き換わるものではありません。各一意の鍵(execname())に複数の関連する値があり、プローブハンドラーが実行するプローブで累積していると考えればよいでしょう。
注記
例3.19「stat-aggregates.stp」 は、返された execname() が仮想ファイルシステムに書き込まれたデータ量を返します。
統計集計が収集したデータを抽出するには、構文フォーマット @extractor(variable/array index expression) を使用します。extractor 以下の整数抽出のいずれかになります。
count
変数やアレイのインデックス式に保存されたすべての値の数を返します。例3.19「stat-aggregates.stp」 の式は、アレイ writes の各一意の鍵に保管される値の数を返します
sum
変数やアレイのインデックス式に保存されたすべての値の合計を返します。例3.19「stat-aggregates.stp」 の式は、アレイ writes の各一意の鍵に保管されている値すべての合計を返します
min
変数やアレイのインデックス式に保存されたすべての値で最も小さいものを返します。
max
変数やアレイのインデックス式に保存されたすべての値で最も大きいものを返します。
avg
変数やアレイのインデックス式に保存されたすべての値の平均を返します。
統計集計を使用する際には、複数のインデックス式 (最大 5 つ) を使用するアレイコンストラクトを構築することもできます。これは、プローブ中に追加のコンテキスト情報を捕捉する際に便利です。以下に例を示します。

例3.20 複数のアレイインデックス

global reads
probe vfs.read
{
  reads[execname(),pid()] <<< 1
}
probe timer.s(3)
{
  foreach([var1,var2] in reads)
    printf("%s (%d) : %d \n", var1, var2, @count(reads[var1,var2]))
}
例3.20「複数のアレイインデックス」 では、最初のプローブで各プロセスが実行した VFS read の数を追跡します。この例が他と異なる点は、このアレイは実行された read をプロセス名 それに対応するプロセス ID の両方に関連付けしている点です。
の 2 つ目のプローブは、アレイ reads 例3.20「複数のアレイインデックス」foreach ステートメントは、最初のプローブにあるアレイ reads の最初のインスタンスに含まれる変数(var1 および var2)と同じ数を使用する点に注意してください。

3.6. tapsets

tapset は、SystemTap スクリプトで使用する事前作成されたプローブおよび関数のライブラリーを形成するスクリプトです。ユーザーが SystemTap スクリプトを実行すると、SystemTap はスクリプトのプローブイベントとハンドラーを tapset ライブラリーに対して確認します。次に SystemTap はスクリプトを C に変換する前に対応するプローブと関数を読み込みます(SystemTap セッションの transpires 「アーキテクチャー」 を参照)。
SystemTap スクリプトと同様に、tapsets はファイル名の extension.stp を使用します。tapsets の標準ライブラリーは、デフォルトで /usr/share/systemtap/tapset/ ディレクトリーにあります。ただし、SystemTap スクリプトとは異なり、tapsets は直接実行するものではなく、他のスクリプトがそこから定義をプルできるライブラリーを構成します。
tapset ライブラリーは抽象化レイヤーで、ユーザーによるイベントと関数の定義を容易にするように設計されています。tapset は、ユーザーがイベントとして指定したい関数に便利なエイリアスを提供します。使用する適切なエイリアスを知ることは、カーネルのバージョンごとに異なる特定のカーネル機能を記憶するよりも容易です。
「Event」、tapsets で定義されています。たとえば、thread_indent()indent.stp に定義されます。

第4章 便利な SystemTap スクリプト

本章では、さまざまなサブシステムの監視および調査に使用可能な SystemTap スクリプトをいくつか説明します。これらのスクリプトはすべて、systemtap-testsuite パッケージをインストールすると、/usr/share/systemtap/testsuite/systemtap.examples/ ディレクトリーで利用できます。

4.1. ネットワーク

以下のセクションでは、ネットワーク関連の関数を追跡し、ネットワークアクティビティーのプロファイルを構築するスクリプトを説明します。

4.1.1. ネットワークのプロファイリング

本セクションでは、ネットワークアクティビティーのプロファイル方法を説明します。例4.1「nettop.stp」 マシン上に各プロセスが生成されているネットワークトラフィックの量を下げます。

例4.1 nettop.stp

#! /usr/bin/env stap

global ifxmit, ifrecv
global ifmerged

probe netdev.transmit
{
  ifxmit[pid(), dev_name, execname(), uid()] <<< length
}

probe netdev.receive
{
  ifrecv[pid(), dev_name, execname(), uid()] <<< length
}

function print_activity()
{
  printf("%5s %5s %-7s %7s %7s %7s %7s %-15s\n",
         "PID", "UID", "DEV", "XMIT_PK", "RECV_PK",
         "XMIT_KB", "RECV_KB", "COMMAND")

  foreach ([pid, dev, exec, uid] in ifrecv) {
	  ifmerged[pid, dev, exec, uid] += @count(ifrecv[pid,dev,exec,uid]);
  }
  foreach ([pid, dev, exec, uid] in ifxmit) {
	  ifmerged[pid, dev, exec, uid] += @count(ifxmit[pid,dev,exec,uid]);
  }
  foreach ([pid, dev, exec, uid] in ifmerged-) {
    n_xmit = @count(ifxmit[pid, dev, exec, uid])
    n_recv = @count(ifrecv[pid, dev, exec, uid])
    printf("%5d %5d %-7s %7d %7d %7d %7d %-15s\n",
           pid, uid, dev, n_xmit, n_recv,
           n_xmit ? @sum(ifxmit[pid, dev, exec, uid])/1024 : 0,
           n_recv ? @sum(ifrecv[pid, dev, exec, uid])/1024 : 0,
           exec)
  }

  print("\n")

  delete ifxmit
  delete ifrecv
  delete ifmerged
}

probe timer.ms(5000), end, error
{
  print_activity()
}
print_activity() 関数は以下の式を使用することに注意してください。
n_xmit ? @sum(ifxmit[pid, dev, exec, uid])/1024 : 0
n_recv ? @sum(ifrecv[pid, dev, exec, uid])/1024 : 0
これらの式は if または else 条件です。2 つ目のステートメントは、以下の擬似コードをより簡潔にした方法です。
if n_recv != 0 then
  @sum(ifrecv[pid, dev, exec, uid])/1024
else
  0
例4.1「nettop.stp」 では、どのプロセスがシステム上でネットワークトラフィックを生成しているかを追跡し、各プロセスについて以下の情報を提供します。
  • PID - プロセスの ID。
  • UID - ユーザー ID。ユーザー ID が 0 の場合は、root ユーザーを参照します。
  • DEV - プロセスがデータの送受信に使用したイーサネットデバイス(例: eth0、eth1)。
  • XMIT_PK - プロセスが送信したパケット数
  • RECV_PK - プロセスが受信したパケット数
  • XMIT_KB - プロセスが送信したデータ量(キロバイト単位)。
  • RECV_KB - サービスが受信したデータ量(キロバイト単位)。
例4.1「nettop.stp」 は、5 秒ごとにネットワークプロファイルのサンプルを提供します。この設定は、それに応じて probe timer.ms(5000) を編集して変更できます。例4.2「例4.1「nettop.stp」 出力例」 には、20 例4.1「nettop.stp」

例4.2 例4.1「nettop.stp」 出力例

[...]
  PID   UID DEV     XMIT_PK RECV_PK XMIT_KB RECV_KB COMMAND        
    0     0 eth0          0       5       0       0 swapper        
11178     0 eth0          2       0       0       0 synergyc       
  PID   UID DEV     XMIT_PK RECV_PK XMIT_KB RECV_KB COMMAND        
 2886     4 eth0         79       0       5       0 cups-polld     
11362     0 eth0          0      61       0       5 firefox        
    0     0 eth0          3      32       0       3 swapper        
 2886     4 lo            4       4       0       0 cups-polld     
11178     0 eth0          3       0       0       0 synergyc       
  PID   UID DEV     XMIT_PK RECV_PK XMIT_KB RECV_KB COMMAND        
    0     0 eth0          0       6       0       0 swapper        
 2886     4 lo            2       2       0       0 cups-polld     
11178     0 eth0          3       0       0       0 synergyc       
 3611     0 eth0          0       1       0       0 Xorg           
  PID   UID DEV     XMIT_PK RECV_PK XMIT_KB RECV_KB COMMAND        
    0     0 eth0          3      42       0       2 swapper        
11178     0 eth0         43       1       3       0 synergyc       
11362     0 eth0          0       7       0       0 firefox        
 3897     0 eth0          0       1       0       0 multiload-apple
[...]

4.1.2. ネットワークソケットコードで呼び出された関数の追跡

本セクションでは、カーネルの net/socket.c ファイルから呼び出された関数を追跡する方法を説明します。このタスクでは、各プロセスがカーネルレベルでネットワークと対話する様子が詳細に分かります。

例4.3 socket-trace.stp

#!/usr/bin/stap

probe kernel.function("*@net/socket.c").call {
  printf ("%s -> %s\n", thread_indent(1), probefunc())
}
probe kernel.function("*@net/socket.c").return {
  printf ("%s <- %s\n", thread_indent(-1), probefunc())
}

例4.4 例4.3「socket-trace.stp」 のサンプル出力

[...]
0 Xorg(3611): -> sock_poll
3 Xorg(3611): <- sock_poll
0 Xorg(3611): -> sock_poll
3 Xorg(3611): <- sock_poll
0 gnome-terminal(11106): -> sock_poll
5 gnome-terminal(11106): <- sock_poll
0 scim-bridge(3883): -> sock_poll
3 scim-bridge(3883): <- sock_poll
0 scim-bridge(3883): -> sys_socketcall
4 scim-bridge(3883):  -> sys_recv
8 scim-bridge(3883):   -> sys_recvfrom
12 scim-bridge(3883):-> sock_from_file
16 scim-bridge(3883):<- sock_from_file
20 scim-bridge(3883):-> sock_recvmsg
24 scim-bridge(3883):<- sock_recvmsg
28 scim-bridge(3883):   <- sys_recvfrom
31 scim-bridge(3883):  <- sys_recv
35 scim-bridge(3883): <- sys_socketcall
[...]
例4.4「例4.3「socket-trace.stp」 のサンプル出力」 には、3 例4.3「socket-trace.stp」thread_indent() が提供するこのスクリプトの出力に関する詳細情報は、SystemTap 関数

4.1.3. 着信 TCP 接続の監視

このセクションでは、着信 TCP 接続の監視方法を説明します。このタスクは、承認されていない、疑わしい、さもなくば望ましくないネットワークアクセス要求をリアルタイムで特定する場合に便利です。

例4.5 tcp_connections.stp

#! /usr/bin/env stap

probe begin {
  printf("%6s %16s %6s %6s %16s\n",
         "UID", "CMD", "PID", "PORT", "IP_SOURCE")
}

probe kernel.function("tcp_accept").return?,
      kernel.function("inet_csk_accept").return? {
  sock = $return
  if (sock != 0)
    printf("%6d %16s %6d %6d %16s\n", uid(), execname(), pid(),
           inet_get_local_port(sock), inet_get_ip_source(sock))
}
例4.5「tcp_connections.stp」 の実行中は、システムが受け付けた着信 TCP 接続の以下の情報がリアルタイムでプリントアウトされます。
  • current UID
  • CMD - 接続を受け付けるコマンド
  • PID コマンドでは、
  • 接続が使用するポート
  • TCP 接続の発信元となる IP アドレス

例4.6 例4.5「tcp_connections.stp」 のサンプル出力

UID            CMD    PID   PORT        IP_SOURCE
0             sshd   3165     22      10.64.0.227
0             sshd   3165     22      10.64.0.227

4.1.4. カーネルでのネットワークパケットドロップの監視

Linux のネットワークスタックは、さまざまな理由でパケットを破棄する場合があります。Linux カーネルにはトレースポイント kernel.trace("kfree_skb") が含まれているものがあります。これは、パケットが破棄される場所を簡単に追跡します。例4.7「dropwatch.stp」 kernel.trace("kfree_skb") を使用して、パケットの破棄を追跡します。このスクリプトは、どの場所を 5 秒ごとに破棄するかをまとめています。

例4.7 dropwatch.stp

#!/usr/bin/stap

############################################################
# Dropwatch.stp
# Author: Neil Horman <nhorman@redhat.com>
# An example script to mimic the behavior of the dropwatch utility
# http://fedorahosted.org/dropwatch
############################################################

# Array to hold the list of drop points we find
global locations

# Note when we turn the monitor on and off
probe begin { printf("Monitoring for dropped packets\n") }
probe end { printf("Stopping dropped packet monitor\n") }

# increment a drop counter for every location we drop at
probe kernel.trace("kfree_skb") { locations[$location] <<< 1 }

# Every 5 seconds report our drop locations
probe timer.sec(5)
{
	printf("\n")
	foreach (l in locations-) {
		printf("%d packets dropped at location %p\n",
			   @count(locations[l]), l)
	}
	delete locations
}

kernel.trace("kfree_skb") は、カーネル内でネットワークパケットがドロップした場所を追跡します。kernel.trace("kfree_skb") には、解放されているバッファーへのポインター($skb)と、解放されているバッファーのカーネルコードの場所($location)の 2 つの引数があります。
dropwatch.stp スクリプトを 15 秒間実行すると、例4.8「例4.7「dropwatch.stp」 出力例」 のような結果が出力されます。ここでは、トレースポイントアドレスと実際のアドレスのミスの数が記載されています。

例4.8 例4.7「dropwatch.stp」 出力例

Monitoring for dropped packets
51 packets dropped at location 0xffffffff8024cd0f
2 packets dropped at location 0xffffffff8044b472
51 packets dropped at location 0xffffffff8024cd0f
1 packets dropped at location 0xffffffff8044b472
97 packets dropped at location 0xffffffff8024cd0f
1 packets dropped at location 0xffffffff8044b472
Stopping dropped packet monitor
パケットドロップの場所をより意味のあるものにするには、/boot/System.map-$(uname -r) ファイルを参照してください。このファイルには、各関数の開始アドレスが記載されており、例4.8「例4.7「dropwatch.stp」 出力例」。以下の /boot/System.map-$(uname -r) ファイルのスニペットを指定すると、アドレス 0xffffffff8024cd0f が関数 unix_stream_recvmsg にマッピングされ、アドレス 0xffffffff8044b472 を関数 arp_rcv にマッピングします。
[...]
ffffffff8024c5cd T unlock_new_inode
ffffffff8024c5da t unix_stream_sendmsg
ffffffff8024c920 t unix_stream_recvmsg
ffffffff8024cea1 t udp_v4_lookup_longway
[...]
ffffffff8044addc t arp_process
ffffffff8044b360 t arp_rcv
ffffffff8044b487 t parp_redo
ffffffff8044b48c t arp_solicit
[...]

4.2. disk

以下のセクションでは、ディスクおよび I/O アクティビティーを監視するスクリプトを説明します。

4.2.1. ディスク読み取り/書き込みトラフィックの要約

このセクションでは、どのプロセスが最も重いディスクの読み取り/書き込みをシステムに実行しているかを特定する方法を説明します。

例4.9 disktop.stp

#!/usr/bin/stap
#
# Copyright (C) 2007 Oracle Corp.
#
# Get the status of reading/writing disk every 5 seconds,
# output top ten entries 
#
# This is free software,GNU General Public License (GPL);
# either version 2, or (at your option) any later version.
#
# Usage:
#  ./disktop.stp
#

global io_stat,device
global read_bytes,write_bytes

probe vfs.read.return {
  if ($return>0) {
    if (devname!="N/A") {/*skip read from cache*/
      io_stat[pid(),execname(),uid(),ppid(),"R"] += $return
      device[pid(),execname(),uid(),ppid(),"R"] = devname
      read_bytes += $return
    }
  }
}

probe vfs.write.return {
  if ($return>0) {
    if (devname!="N/A") { /*skip update cache*/
      io_stat[pid(),execname(),uid(),ppid(),"W"] += $return
      device[pid(),execname(),uid(),ppid(),"W"] = devname
      write_bytes += $return
    }
  }
}

probe timer.ms(5000) {
  /* skip non-read/write disk */
  if (read_bytes+write_bytes) {

    printf("\n%-25s, %-8s%4dKb/sec, %-7s%6dKb, %-7s%6dKb\n\n",
           ctime(gettimeofday_s()),
           "Average:", ((read_bytes+write_bytes)/1024)/5,
           "Read:",read_bytes/1024,
           "Write:",write_bytes/1024)

    /* print header */
    printf("%8s %8s %8s %25s %8s %4s %12s\n",
           "UID","PID","PPID","CMD","DEVICE","T","BYTES")
  }
  /* print top ten I/O */
  foreach ([process,cmd,userid,parent,action] in io_stat- limit 10)
    printf("%8d %8d %8d %25s %8s %4s %12d\n",
           userid,process,parent,cmd,
           device[process,cmd,userid,parent,action],
           action,io_stat[process,cmd,userid,parent,action])

  /* clear data */
  delete io_stat
  delete device
  read_bytes = 0
  write_bytes = 0  
}

probe end{
  delete io_stat
  delete device
  delete read_bytes
  delete write_bytes
}
例4.9「disktop.stp」 は、ディスクの読み取りまたは書き込みを行う上位 10 のプロセスを出力します。例4.10「例4.9「disktop.stp」 出力例」 このスクリプトのサンプル出力を表示し、記載のプロセスごとに以下のデータが含まれます。
  • UID - ユーザー ID。ユーザー ID が 0 の場合は、root ユーザーを参照します。
  • PID - プロセスの ID。
  • PPID - プロセスの親プロセスのプロセス ID。
  • CMD - 一覧表示されたプロセスの名前。
  • DEVICE - プロセスが読み取りまたは書き込みを行なっているストレージデバイス。
  • T - プロセスが実行したアクションのタイプ。W は書き込みを参照し、R は読み取りを指します。
  • BYTES - ディスクから読み取った、またはディスクに書き込んだデータ量。
例4.9「disktop.stp」ctime() および gettimeofday_s() によって返されます。ctime() Unix 時刻(January 1, 1970)以降、カレンダーの時間を秒単位で派生します。gettimeofday_s() Unix 時間の開始からの実際の秒数をカウントします。これにより、出力用に人間が判読可能なタイムスタンプが非常に正確になります。
このスクリプトでは、$return は、各プロセスが仮想ファイルシステムからの読み取りまたは書き込みを行う実際のバイト数を保存するローカル変数です。$return 戻り値のプローブでのみ使用できます(例: vfs.read.return および vfs.read.return)。

例4.10 例4.9「disktop.stp」 出力例

[...]
Mon Sep 29 03:38:28 2008 , Average:  19Kb/sec, Read: 7Kb, Write: 89Kb
UID      PID     PPID                       CMD   DEVICE    T    BYTES
0    26319    26294                   firefox     sda5    W        90229
0     2758     2757           pam_timestamp_c     sda5    R         8064
0     2885        1                     cupsd     sda5    W         1678
Mon Sep 29 03:38:38 2008 , Average:   1Kb/sec, Read: 7Kb, Write: 1Kb
UID      PID     PPID                       CMD   DEVICE    T    BYTES
0     2758     2757           pam_timestamp_c     sda5    R         8064
0     2885        1                     cupsd     sda5    W         1678

4.2.2. ファイル読み取り/書き込みの I/O 時間の追跡

このセクションでは、各プロセスのファイルの読み取りおよび書き込み時間を監視する方法を説明します。これは、あるシステム上でどのファイルの読み込みが遅いかということを判断する際に便利です。

例4.11 iotime.stp

global start
global entry_io
global fd_io
global time_io

function timestamp:long() {
  return gettimeofday_us() - start
}

function proc:string() {
  return sprintf("%d (%s)", pid(), execname())
}

probe begin {
 start = gettimeofday_us()
}

global filenames
global filehandles
global fileread
global filewrite

probe syscall.open {
  filenames[pid()] = user_string($filename)
} 

probe syscall.open.return {
  if ($return != -1) {
    filehandles[pid(), $return] = filenames[pid()]
    fileread[pid(), $return] = 0
    filewrite[pid(), $return] = 0
  } else {
    printf("%d %s access %s fail\n", timestamp(), proc(), filenames[pid()])
  }
  delete filenames[pid()]
}

probe syscall.read {
  if ($count > 0) {
    fileread[pid(), $fd] += $count
  }
  t = gettimeofday_us(); p = pid()
  entry_io[p] = t
  fd_io[p] = $fd
}

probe syscall.read.return {
  t = gettimeofday_us(); p = pid()
  fd = fd_io[p]
  time_io[p,fd] <<< t - entry_io[p]
}

probe syscall.write {
  if ($count > 0) {
    filewrite[pid(), $fd] += $count
  }
  t = gettimeofday_us(); p = pid()
  entry_io[p] = t
  fd_io[p] = $fd
}

probe syscall.write.return {
  t = gettimeofday_us(); p = pid()
  fd = fd_io[p]
  time_io[p,fd] <<< t - entry_io[p]
}

probe syscall.close {
  if (filehandles[pid(), $fd] != "") {
    printf("%d %s access %s read: %d write: %d\n",  timestamp(), proc(),
           filehandles[pid(), $fd], fileread[pid(), $fd], filewrite[pid(), $fd])
    if (@count(time_io[pid(), $fd]))
      printf("%d %s iotime %s time: %d\n",  timestamp(), proc(),
             filehandles[pid(), $fd], @sum(time_io[pid(), $fd]))
   }
  delete fileread[pid(), $fd]
  delete filewrite[pid(), $fd]
  delete filehandles[pid(), $fd]
  delete fd_io[pid()]
  delete entry_io[pid()]
  delete time_io[pid(),$fd]
}
例4.11「iotime.stp」 では、システムコールが開かれる、閉じる、ファイルから読み取る、およびファイルに書き込む際に、毎回これを追跡します。例4.11「iotime.stp」 はシステムコールがアクセスする各ファイルについて、読み取りもしくは書き込みが終了するまでの時間をマイクロ秒単位でカウントし、読み取りもしくは書き込みされたデータ量をバイト単位で追跡します。
例4.11「iotime.stp」 また、ローカル変数 $count を使用してシステムコールが読み取りまたは書き込みを試行するデータ量 (バイト単位)も追跡します。$return 例4.9「disktop.stp」 from 「ディスク読み取り/書き込みトラフィックの要約」には、読み取り/書き込みの実際の量が格納されることに注意してください$count は、データの読み取りおよび書き込みを追跡するプローブでのみ使用できます(例: syscall.read および syscall.write)。

例4.12 例4.11「iotime.stp」 出力例

[...]
825946 3364 (NetworkManager) access /sys/class/net/eth0/carrier read: 8190 write: 0
825955 3364 (NetworkManager) iotime /sys/class/net/eth0/carrier time: 9
[...]
117061 2460 (pcscd) access /dev/bus/usb/003/001 read: 43 write: 0
117065 2460 (pcscd) iotime /dev/bus/usb/003/001 time: 7
[...]
3973737 2886 (sendmail) access /proc/loadavg read: 4096 write: 0
3973744 2886 (sendmail) iotime /proc/loadavg time: 11
[...]
例4.12「例4.11「iotime.stp」 出力例」 では、以下のデータがプリントアウトされます。
  • タイムスタンプ (マイクロ秒単位)
  • プロセス ID およびプロセス名
  • access または iotime のフラグ
  • アクセスされたファイル
プロセスがデータの読み取りまたは書き込みを実行すると、accessiotime の行のペアが一緒に表示されます。access 行のタイムスタンプは、そのプロセスがファイルにアクセスを開始した時間を指します。その行の最後には、読み取り/書き込みされたデータ量がバイト単位で表示されます。iotime の行には、読み取り/書き込みにプロセスが費やした時間(マイクロ秒単位)が表示されます。
access 行の後に iotime 行が続いていない場合は、プロセスがデータの読み取りまたは書き込みを行わなかったことを意味します。

4.2.3. 累積 I/O の追跡

このセクションでは、システムへの累積 I/O の量を追跡する方法を説明します。

例4.13 traceio.stp

#! /usr/bin/env stap
# traceio.stp
# Copyright (C) 2007 Red Hat, Inc., Eugene Teo <eteo@redhat.com>
# Copyright (C) 2009 Kai Meyer <kai@unixlords.com>
#   Fixed a bug that allows this to run longer
#   And added the humanreadable function
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#

global reads, writes, total_io

probe vfs.read.return {
  reads[pid(),execname()] += $return
  total_io[pid(),execname()] += $return
}

probe vfs.write.return {
  writes[pid(),execname()] += $return
  total_io[pid(),execname()] += $return
}

function humanreadable(bytes) {
  if (bytes > 1024*1024*1024) {
    return sprintf("%d GiB", bytes/1024/1024/1024)
  } else if (bytes > 1024*1024) {
    return sprintf("%d MiB", bytes/1024/1024)
  } else if (bytes > 1024) {
    return sprintf("%d KiB", bytes/1024)
  } else {
    return sprintf("%d   B", bytes)
  }
}

probe timer.s(1) {
  foreach([p,e] in total_io- limit 10)
    printf("%8d %15s r: %12s w: %12s\n",
           p, e, humanreadable(reads[p,e]),
           humanreadable(writes[p,e]))
  printf("\n")
  # Note we don't zero out reads, writes and total_io,
  # so the values are cumulative since the script started.
}
例4.13「traceio.stp」 は、I/O トラフィックに応じた上位 10 位の実行可能ファイルをプリントします。さらに、これらの上位 10 位の実行可能ファイルによる I/O 読み取りおよび書き込みの累積分量も追跡します。この情報は降順で 1 秒ごとに追跡、プリントアウトされます。
例4.13「traceio.stp」 また、ローカル変数 $return 例4.9「disktop.stp」

例4.14 例4.13「traceio.stp」 のサンプル出力

[...]
           Xorg r:   583401 KiB w:        0 KiB
       floaters r:       96 KiB w:     7130 KiB
multiload-apple r:      538 KiB w:      537 KiB
           sshd r:       71 KiB w:       72 KiB
pam_timestamp_c r:      138 KiB w:        0 KiB
        staprun r:       51 KiB w:       51 KiB
          snmpd r:       46 KiB w:        0 KiB
          pcscd r:       28 KiB w:        0 KiB
     irqbalance r:       27 KiB w:        4 KiB
          cupsd r:        4 KiB w:       18 KiB
           Xorg r:   588140 KiB w:        0 KiB
       floaters r:       97 KiB w:     7143 KiB
multiload-apple r:      543 KiB w:      542 KiB
           sshd r:       72 KiB w:       72 KiB
pam_timestamp_c r:      138 KiB w:        0 KiB
        staprun r:       51 KiB w:       51 KiB
          snmpd r:       46 KiB w:        0 KiB
          pcscd r:       28 KiB w:        0 KiB
     irqbalance r:       27 KiB w:        4 KiB
          cupsd r:        4 KiB w:       18 KiB

4.2.4. I/O 監視 (デバイスごと)

このセクションでは、特定のデバイス上の I/O アクティビティーを監視する方法を説明します。

例4.15 traceio2.stp

#! /usr/bin/env stap

global device_of_interest

probe begin {
  /* The following is not the most efficient way to do this.
      One could directly put the result of usrdev2kerndev()
      into device_of_interest.  However, want to test out
      the other device functions */
  dev = usrdev2kerndev($1)
  device_of_interest = MKDEV(MAJOR(dev), MINOR(dev))
}

probe vfs.write, vfs.read
{
  if (dev == device_of_interest)
    printf ("%s(%d) %s 0x%x\n",
            execname(), pid(), probefunc(), dev)
}
例4.15「traceio2.stp」 は、全体デバイス番号という引数 1 つを取ります。この番号を取得するには、stat -c "0x%D" ディレクトリー を使用します。このディレクトリーは、監視するデバイスに配置されます。
usrdev2kerndev() 関数は、全体デバイス番号をカーネルが理解する形式に変換します。usrdev2kerndev() が生成した出力は、特定デバイスのメジャー番号およびマイナー番号を決定するために MKDEV()MINOR()、および MAJOR() 関数とともに使用されます。
の出力には、読み取り/書き込みを実行しているプロセスの名前と ID、実行している関数(vfs_read または 例4.15「traceio2.stp」
以下の例は、stap traceio2.stp 0x805 の完全な出力の抜粋です。0x805 は、/home 全体のデバイス番号です。/home は、監視するデバイスである /dev/sda5 にあります。

例4.16 例4.15「traceio2.stp」 出力例

[...]
synergyc(3722) vfs_read 0x800005
synergyc(3722) vfs_read 0x800005
cupsd(2889) vfs_write 0x800005
cupsd(2889) vfs_write 0x800005
cupsd(2889) vfs_write 0x800005
[...]

4.2.5. ファイルの読み取りおよび書き込みの監視

このセクションでは、ファイルの読み取りおよび書き込みをリアルタイムで監視する方法を説明します。

例4.17 inodewatch.stp

#! /usr/bin/env stap

probe vfs.write, vfs.read
{
  # dev and ino are defined by vfs.write and vfs.read
  if (dev == MKDEV($1,$2) # major/minor device
      && ino == $3)
    printf ("%s(%d) %s 0x%x/%u\n",
      execname(), pid(), probefunc(), dev, ino)
}
例4.17「inodewatch.stp」 は、ファイルの以下の情報をコマンドラインの引数として取ります。
  • ファイルのメジャーデバイス番号
  • ファイルのマイナーデバイス番号
  • ファイルの inode 番号
この情報を取得するには、stat -c '%D %i' ファイル名を使用します 。filename は絶対パスになります。
たとえば、/etc/crontab ファイルを監視する場合は最初に stat -c '%D %i' /etc/crontab を実行します。これにより、以下の出力が出力されます。
805 1078319
805 ベース 16(16 進数)のデバイス番号です。小さい 2 桁がマイナーデバイス番号で、その上の数字はメジャー番号になります。1078319 inode 番号です。監視 /etc/crontab を開始するには、stap inodewatch.stp 0x8 0x05 1078319 を実行します( 0x 接頭辞はベース 16 の値を示します)。
このコマンドの出力には、読み取り/書き込みを実行しているプロセスの名前と ID、実行している関数(vfs_read または vfs_write)、デバイス番号(16 進数形式)、および inode 番号が含まれます。例4.18「例4.17「inodewatch.stp」 出力例」 stap inodewatch.stp 0x8 0x05 1078319 の出力が含まれます(スクリプトの実行中に cat /etc/crontab が実行されると)。

例4.18 例4.17「inodewatch.stp」 出力例

cat(16437) vfs_read 0x800005/1078319
cat(16437) vfs_read 0x800005/1078319

4.2.6. ファイル属性の変更の監視

このセクションでは、プロセスがターゲットファイルの属性を変更したかどうかをリアルタイムで監視する方法を説明します。

例4.19 inodewatch2-simple.stp

global ATTR_MODE = 1

probe kernel.function("inode_setattr") {
  dev_nr = $inode->i_sb->s_dev
  inode_nr = $inode->i_ino

  if (dev_nr == ($1 << 20 | $2) # major/minor device
      && inode_nr == $3
      && $attr->ia_valid & ATTR_MODE)
    printf ("%s(%d) %s 0x%x/%u %o %d\n",
      execname(), pid(), probefunc(), dev_nr, inode_nr, $attr->ia_mode, uid())
}
例4.17「inodewatch.stp」 from 「ファイルの読み取りおよび書き込みの監視」 (整数形式)と inode 番号を引数として取ります。この情報の取得方法は 「ファイルの読み取りおよび書き込みの監視」
例4.19「inodewatch2-simple.stp」、監視対象ファイルの属性変更と、ユーザーが作成したユーザーの ID 例4.19「inodewatch2-simple.stp」 が含まれている点で異なります。例4.20「例4.19「inodewatch2-simple.stp」 出力例」 は、ユーザー joechmod 777 /home/joe/bigfile および chmod 666 /home/joe/bigfile を実行するときに /home/joe/bigfile 例4.19「inodewatch2-simple.stp」

例4.20 例4.19「inodewatch2-simple.stp」 出力例

chmod(17448) inode_setattr 0x800005/6011835 100777 500
chmod(17449) inode_setattr 0x800005/6011835 100666 500

4.3. プロファイリング

以下のセクションでは、関数呼び出しを監視することでカーネルアクティビティーのプロファイルを実行するスクリプトを説明します。

4.3.1. 関数呼び出しのカウント

このセクションでは、30 秒間のサンプルで特定のカーネル関数をシステムが呼び出した回数を特定する方法を説明します。ワイルドカードの使用によっては、このスクリプトを使用して複数のカーネル関数を対象とすることもできます。

例4.21 functioncallcount.stp

#! /usr/bin/env stap
# The following line command will probe all the functions
# in kernel's memory management code:
#
# stap  functioncallcount.stp "*@mm/*.c"

probe kernel.function(@1).call {  # probe functions listed on commandline
  called[probefunc()] <<< 1  # add a count efficiently
}

global called

probe end {
  foreach (fn in called-)  # Sort by call count (in decreasing order)
  #       (fn+ in called)  # Sort by function name
    printf("%s %d\n", fn, @count(called[fn]))
  exit()
}
例4.21「functioncallcount.stp」 は、ターゲットカーネルの関数を引数として取ります。この引数はワイルドカードに対応しているので、ある程度までの複数のカーネル関数をターゲットにできます。
の出力には、サンプル時間中に呼び出された関数の名前とその回数 例4.21「functioncallcount.stp」 が含まれます。例4.22「例4.21「functioncallcount.stp」 出力例」 stap functioncallcount.stp "*@mm/*.c" の出力の抜粋が含まれます。

例4.22 例4.21「functioncallcount.stp」 出力例

[...]
__vma_link 97
__vma_link_file 66
__vma_link_list 97
__vma_link_rb 97
__xchg 103
add_page_to_active_list 102
add_page_to_inactive_list 19
add_to_page_cache 19
add_to_page_cache_lru 7
all_vm_events 6
alloc_pages_node 4630
alloc_slabmgmt 67
anon_vma_alloc 62
anon_vma_free 62
anon_vma_lock 66
anon_vma_prepare 98
anon_vma_unlink 97
anon_vma_unlock 66
arch_get_unmapped_area_topdown 94
arch_get_unmapped_exec_area 3
arch_unmap_area_topdown 97
atomic_add 2
atomic_add_negative 97
atomic_dec_and_test 5153
atomic_inc 470
atomic_inc_and_test 1
[...]

4.3.2. 呼び出し先の追跡

このセクションでは、着信および発信関数呼び出しを追跡する方法を説明します。

例4.23 para-callgraph.stp

#! /usr/bin/env stap

function trace(entry_p, extra) {
  %( $# > 1 %? if (tid() in trace) %)
  printf("%s%s%s %s\n",
         thread_indent (entry_p),
         (entry_p>0?"->":"<-"),
         probefunc (),
         extra)
}


%( $# > 1 %?
global trace
probe $2.call {
  trace[tid()] = 1
}
probe $2.return {
  delete trace[tid()]
}
%)

probe $1.call   { trace(1, $$parms) }
probe $1.return { trace(-1, $$return) }
例4.23「para-callgraph.stp」 は、以下の 2 つのコマンドライン引数を取っています。
  • トレースするエントリー/終了の関数($1)。
  • 2 つ目のオプションとなる trigger function ($2)。これは、スレッドごとの追跡を有効または無効にします。trigger function が終了していなければ、各スレッドにおける追跡は継続されます。
例4.23「para-callgraph.stp」 thread_indent() を使用します。この出力には、$1 のタイムスタンプ、プロセス名、およびスレッド ID(追跡しているプローブ関数)が含まれます。thread_indent() の詳細は、エントリー SystemTap 関数
以下の例には、stap para-callgraph.stp 'kernel.function("*@fs/*.c")' 'kernel.function("sys_read")' の出力の抜粋を示します。

例4.24 例4.23「para-callgraph.stp」 出力例

[...]
   267 gnome-terminal(2921): <-do_sync_read return=0xfffffffffffffff5
   269 gnome-terminal(2921):<-vfs_read return=0xfffffffffffffff5
     0 gnome-terminal(2921):->fput file=0xffff880111eebbc0
     2 gnome-terminal(2921):<-fput 
     0 gnome-terminal(2921):->fget_light fd=0x3 fput_needed=0xffff88010544df54
     3 gnome-terminal(2921):<-fget_light return=0xffff8801116ce980
     0 gnome-terminal(2921):->vfs_read file=0xffff8801116ce980 buf=0xc86504 count=0x1000 pos=0xffff88010544df48
     4 gnome-terminal(2921): ->rw_verify_area read_write=0x0 file=0xffff8801116ce980 ppos=0xffff88010544df48 count=0x1000
     7 gnome-terminal(2921): <-rw_verify_area return=0x1000
    12 gnome-terminal(2921): ->do_sync_read filp=0xffff8801116ce980 buf=0xc86504 len=0x1000 ppos=0xffff88010544df48
    15 gnome-terminal(2921): <-do_sync_read return=0xfffffffffffffff5
    18 gnome-terminal(2921):<-vfs_read return=0xfffffffffffffff5
     0 gnome-terminal(2921):->fput file=0xffff8801116ce980

4.3.3. カーネルおよびユーザースペースで費やした時間の判定

このセクションでは、スレッドがカーネルまたはユーザースペースで費やした時間を判定する方法を説明します。

例4.25 thread-times.stp

#! /usr/bin/env stap

probe perf.sw.cpu_clock!, timer.profile {
  // NB: To avoid contention on SMP machines, no global scalars/arrays used,
  // only contention-free statistics aggregates.
  tid=tid(); e=execname()
  if (!user_mode())
    kticks[e,tid] <<< 1
  else
    uticks[e,tid] <<< 1
  ticks <<< 1
  tids[e,tid] <<< 1
}

global uticks, kticks, ticks

global tids

probe timer.s(5), end {
  allticks = @count(ticks)
  printf ("%16s %5s %7s %7s (of %d ticks)\n",
          "comm", "tid", "%user", "%kernel", allticks)
  foreach ([e,tid] in tids- limit 20) {
    uscaled = @count(uticks[e,tid])*10000/allticks
    // SystemTap only performs integer arithmetic.
    // To avoid losing precision the decimal point is shifted
    // to the right four places (*100000). Think of this as
    // the original result value x.xxyy becoming xxxyy.0.
    // The integer percentage xxx is obtained
    // by dividing by 100 and the fractional percentage
    // is obtained with a modulo 100 operation.
    kscaled = @count(kticks[e,tid])*10000/allticks
    printf ("%16s %5d %3d.%02d%% %3d.%02d%%\n",
      e, tid, uscaled/100, uscaled%100, kscaled/100, kscaled%100)
  }
  printf("\n")

  delete uticks
  delete kticks
  delete ticks
  delete tids
}
例4.25「thread-times.stp」 は、5 秒間のサンプル内で CPU 時間を占めている上位 20 位のプロセスと、CPU ティックの総数を一覧表示します。このスクリプトの出力は、各プロセスが使用した CPU 時間のパーセント表示と、その時間がカーネルスペースかユーザースペースで費やされたかも示します。

例4.26 例4.25「thread-times.stp」 のサンプル出力

  tid   %user %kernel (of 20002 ticks)
    0   0.00%  87.88%
32169   5.24%   0.03%
 9815   3.33%   0.36%
 9859   0.95%   0.00%
 3611   0.56%   0.12%
 9861   0.62%   0.01%
11106   0.37%   0.02%
32167   0.08%   0.08%
 3897   0.01%   0.08%
 3800   0.03%   0.00%
 2886   0.02%   0.00%
 3243   0.00%   0.01%
 3862   0.01%   0.00%
 3782   0.00%   0.00%
21767   0.00%   0.00%
 2522   0.00%   0.00%
 3883   0.00%   0.00%
 3775   0.00%   0.00%
 3943   0.00%   0.00%
 3873   0.00%   0.00%

4.3.4. ポーリングアプリケーションの監視

このセクションでは、どのアプリケーションがポーリングを行なっているかを特定、監視する方法を説明します。これを行うことで、不必要または過剰なポーリングが追跡でき、CPU の使用量を改善し、省電力効果を向上させるエリアを特定できるようになります。

例4.27 timeout.stp

#! /usr/bin/env stap
# Copyright (C) 2009 Red Hat, Inc.
# Written by Ulrich Drepper <drepper@redhat.com>
# Modified by William Cohen <wcohen@redhat.com>

global process, timeout_count, to
global poll_timeout, epoll_timeout, select_timeout, itimer_timeout
global nanosleep_timeout, futex_timeout, signal_timeout

probe syscall.poll, syscall.epoll_wait {
  if (timeout) to[pid()]=timeout
}

probe syscall.poll.return {
  p = pid()
  if ($return == 0 && to[p] > 0 ) {
    poll_timeout[p]++
    timeout_count[p]++
    process[p] = execname()
    delete to[p]
  }
}

probe syscall.epoll_wait.return {
  p = pid()
  if ($return == 0 && to[p] > 0 ) {
    epoll_timeout[p]++
    timeout_count[p]++
    process[p] = execname()
    delete to[p]
  }
}

probe syscall.select.return {
  if ($return == 0) {
    p = pid()
    select_timeout[p]++
    timeout_count[p]++
    process[p] = execname()
  }
}

probe syscall.futex.return {
  if (errno_str($return) == "ETIMEDOUT") {
    p = pid()
    futex_timeout[p]++
    timeout_count[p]++
    process[p] = execname()
  }
}

probe syscall.nanosleep.return {
  if ($return == 0) {
    p = pid()
    nanosleep_timeout[p]++
    timeout_count[p]++
    process[p] = execname()
  }
}

probe kernel.function("it_real_fn") {
  p = pid()
  itimer_timeout[p]++
  timeout_count[p]++
  process[p] = execname()
}

probe syscall.rt_sigtimedwait.return {
  if (errno_str($return) == "EAGAIN") {
    p = pid()
    signal_timeout[p]++
    timeout_count[p]++
    process[p] = execname()
  }
}

probe syscall.exit {
  p = pid()
  if (p in process) {
    delete process[p]
    delete timeout_count[p]
    delete poll_timeout[p]
    delete epoll_timeout[p]
    delete select_timeout[p]
    delete itimer_timeout[p]
    delete futex_timeout[p]
    delete nanosleep_timeout[p]
    delete signal_timeout[p]
  }
}

probe timer.s(1) {
  ansi_clear_screen()
  printf ("  pid |   poll  select   epoll  itimer   futex nanosle  signal| process\n")
  foreach (p in timeout_count- limit 20) {
     printf ("%5d |%7d %7d %7d %7d %7d %7d %7d| %-.38s\n", p,
              poll_timeout[p], select_timeout[p],
              epoll_timeout[p], itimer_timeout[p],
              futex_timeout[p], nanosleep_timeout[p],
              signal_timeout[p], process[p])
  }
}
例4.27「timeout.stp」 は、各アプリケーションが以下のシステムコールを使用した回数を追跡します。
  • poll
  • select
  • epoll
  • itimer
  • futex
  • nanosleep
  • signal
いくつかのアプリケーションでは、これらのシステムコールは過剰に使用されています。そのため、これらは通常、ポーリングアプリケーションの「有力なクリプット」として特定されます。ただし、アプリケーションが異なるシステムコールを使用して過剰にポーリングしている場合もあります。場合によっては、システムが使用する上位のシステムコールを見つけることが便利なこともあります 「最もよく使われるシステムコールの追跡」 を参照してください)。例4.27「timeout.stp」

例4.28 例4.27「timeout.stp」 のサンプル出力

  uid |   poll  select   epoll  itimer   futex nanosle  signal| process
28937 | 148793       0       0    4727   37288       0       0| firefox
22945 |      0   56949       0       1       0       0       0| scim-bridge
    0 |      0       0       0   36414       0       0       0| swapper
 4275 |  23140       0       0       1       0       0       0| mixer_applet2
 4191 |      0   14405       0       0       0       0       0| scim-launcher
22941 |   7908       1       0      62       0       0       0| gnome-terminal
 4261 |      0       0       0       2       0    7622       0| escd
 3695 |      0       0       0       0       0    7622       0| gdm-binary
 3483 |      0    7206       0       0       0       0       0| dhcdbd
 4189 |   6916       0       0       2       0       0       0| scim-panel-gtk
 1863 |   5767       0       0       0       0       0       0| iscsid
 2562 |      0    2881       0       1       0    1438       0| pcscd
 4257 |   4255       0       0       1       0       0       0| gnome-power-man
 4278 |   3876       0       0      60       0       0       0| multiload-apple
 4083 |      0    1331       0    1728       0       0       0| Xorg
 3921 |   1603       0       0       0       0       0       0| gam_server
 4248 |   1591       0       0       0       0       0       0| nm-applet
 3165 |      0    1441       0       0       0       0       0| xterm
29548 |      0    1440       0       0       0       0       0| httpd
 1862 |      0       0       0       0       0    1438       0| iscsid
2 つ目のプローブのタイマー(timer.s())を編集して、サンプル時間を長くすることができます。の出力には、上位 20 位のポーリングアプリケーションの名前と 例4.21「functioncallcount.stp」 (時間内)。例4.28「例4.27「timeout.stp」 のサンプル出力」 スクリプトの抜粋が含まれます。

4.3.5. 最もよく使われるシステムコールの追跡

「ポーリングアプリケーションの監視」例4.27「timeout.stp」 では、以下のシステムコールを最もよく使用したものを挙げることで、どのアプリケーションがポーリングを行なっているかを特定します。
  • poll
  • select
  • epoll
  • itimer
  • futex
  • nanosleep
  • signal
ただしシステムによっては、別のシステムコールが過剰なポーリングを行なっている可能性もあります。ポーリングしているアプリケーションがポーリングに異なるシステムコールを使用していることが疑われる場合は、まずシステムが使用している上位のシステムコールを特定する必要があります。これには、例4.29「topsys.stp」 を使用します。

例4.29 topsys.stp

#! /usr/bin/env stap
#
# This script continuously lists the top 20 systemcalls in the interval 
# 5 seconds
#

global syscalls_count

probe syscall.* {
  syscalls_count[name]++
}

function print_systop () {
  printf ("%25s %10s\n", "SYSCALL", "COUNT")
  foreach (syscall in syscalls_count- limit 20) {
    printf("%25s %10d\n", syscall, syscalls_count[syscall])
  }
  delete syscalls_count
}

probe timer.s(5) {
  print_systop ()
  printf("--------------------------------------------------------------\n")
}
例4.29「topsys.stp」 は、5 秒ごとにシステムが使用している上位 20 位のシステムコールを一覧表示します。また、同期間に各システムコールが使用された回数も表示されます。例4.30「例4.29「topsys.stp」 のサンプル出力」 がサンプル出力になります。

例4.30 例4.29「topsys.stp」 のサンプル出力

--------------------------------------------------------------
                  SYSCALL      COUNT
             gettimeofday       1857
                     read       1821
                    ioctl       1568
                     poll       1033
                    close        638
                     open        503
                   select        455
                    write        391
                   writev        335
                    futex        303
                  recvmsg        251
                   socket        137
            clock_gettime        124
           rt_sigprocmask        121
                   sendto        120
                setitimer        106
                     stat         90
                     time         81
                sigreturn         72
                    fstat         66
--------------------------------------------------------------

4.3.6. プロセスごとのシステムコールボリュームの追跡

このセクションでは、最もボリュームの大きいシステムコールを実行しているプロセスを判定する方法を説明します。前のセクションでは、システムが使用している上位のシステムコールを監視する方法を説明しました「最もよく使われるシステムコールの追跡」)。また、どのアプリケーションが最も多く特定の「ポーリング疑者」のシステムコールを使用しているかを特定する方法も説明しました「ポーリングアプリケーションの監視」)。プロセスごとのシステムコールのボリュームを監視することで、ポーリングプロセスおよび他のリソースの大量消費についてシステムを調査する際により多くのデータが提供できます。

例4.31 syscalls_by_proc.stp

#! /usr/bin/env stap

# Copyright (C) 2006 IBM Corp.
#
# This file is part of systemtap, and is free software.  You can
# redistribute it and/or modify it under the terms of the GNU General
# Public License (GPL); either version 2, or (at your option) any
# later version.

#
# Print the system call count by process name in descending order.
#

global syscalls

probe begin {
  print ("Collecting data... Type Ctrl-C to exit and display results\n")
}

probe syscall.* {
  syscalls[execname()]++
}

probe end {
  printf ("%-10s %-s\n", "#SysCalls", "Process Name")
  foreach (proc in syscalls-)
    printf("%-10d %-s\n", syscalls[proc], proc)
}
例4.31「syscalls_by_proc.stp」 は、システムコールを多く実行している上位 20 位のプロセスを一覧表示します。また、一定期間内に各プロセスが実行したシステムコールの数も表示されます。例4.32「例4.29「topsys.stp」 出力例」、を参照してください。

例4.32 例4.29「topsys.stp」 出力例

Collecting data... Type Ctrl-C to exit and display results
#SysCalls  Process Name
1577       multiload-apple
692        synergyc
408        pcscd
376        mixer_applet2
299        gnome-terminal
293        Xorg
206        scim-panel-gtk
95         gnome-power-man
90         artsd
85         dhcdbd
84         scim-bridge
78         gnome-screensav
66         scim-launcher
[...]
プロセス名の代わりにプロセス ID を表示するには、以下のスクリプトを使用します。

例4.33 syscalls_by_pid.stp

#! /usr/bin/env stap

# Copyright (C) 2006 IBM Corp.
#
# This file is part of systemtap, and is free software.  You can
# redistribute it and/or modify it under the terms of the GNU General
# Public License (GPL); either version 2, or (at your option) any
# later version.

#
# Print the system call count by process ID in descending order.
#

global syscalls

probe begin {
  print ("Collecting data... Type Ctrl-C to exit and display results\n")
}

probe syscall.* {
  syscalls[pid()]++
}

probe end {
  printf ("%-10s %-s\n", "#SysCalls", "PID")
  foreach (pid in syscalls-)
    printf("%-10d %-d\n", syscalls[pid], pid)
}
出力で表示されているように、結果を表示するにはスクリプトを手動で終了する必要があります。どちらのスクリプトにも、タイマー.s() プローブを追加して、時間後に有効期限を追加できます。たとえば、5 秒後にスクリプトを期限切れになるように指示するには、以下のプローブをスクリプトに追加します。
probe timer.s(5)
{
	exit()
}

4.4. 競合ユーザースペースのロックの特定

このセクションでは、特定期間におけるシステムを通した競合ユーザースペースのロックを特定する方法を説明します。競合ユーザースペースのロックを特定する機能は、futex 競合が原因と疑われるハングの調査に役立ちます。
簡単に説明すると、複数のプロセスがメモリーの同じ領域にアクセスしようとすると、futex 競合が発生します。場合によっては、これは競合しているプロセス間のデッドロックになり、アプリケーションがハングしているように見えます。
例4.34「futexes.stp」 システムコールをプローブします。

例4.34 futexes.stp

#! /usr/bin/env stap

# This script tries to identify contended user-space locks by hooking
# into the futex system call.

global thread_thislock # short
global thread_blocktime # 
global FUTEX_WAIT = 0 /*, FUTEX_WAKE = 1 */

global lock_waits # long-lived stats on (tid,lock) blockage elapsed time
global process_names # long-lived pid-to-execname mapping

probe syscall.futex {  
  if (op != FUTEX_WAIT) next # don't care about WAKE event originator
  t = tid ()
  process_names[pid()] = execname()
  thread_thislock[t] = $uaddr
  thread_blocktime[t] = gettimeofday_us()
}

probe syscall.futex.return {  
  t = tid()
  ts = thread_blocktime[t]
  if (ts) {
    elapsed = gettimeofday_us() - ts
    lock_waits[pid(), thread_thislock[t]] <<< elapsed
    delete thread_blocktime[t]
    delete thread_thislock[t]
  }
}

probe end {
  foreach ([pid+, lock] in lock_waits) 
    printf ("%s[%d] lock %p contended %d times, %d avg us\n",
            process_names[pid], pid, lock, @count(lock_waits[pid,lock]),
            @avg(lock_waits[pid,lock]))
}
例4.34「futexes.stp」 は手動で停止する必要があります。終了時には以下の情報が表示されます。
  • 競合の原因となったプロセスの名前と ID
  • 競合対象となったメモリー領域
  • メモリー領域が競合された回数
  • プローブ中の競合の平均時間
例4.35「例4.34「futexes.stp」 のサンプル出力」例4.34「futexes.stp」 を終了した際 (約 20 秒後) の出力の抜粋です。

例4.35 例4.34「futexes.stp」 のサンプル出力

[...]	
automount[2825] lock 0x00bc7784 contended 18 times, 999931 avg us
synergyc[3686] lock 0x0861e96c contended 192 times, 101991 avg us
synergyc[3758] lock 0x08d98744 contended 192 times, 101990 avg us
synergyc[3938] lock 0x0982a8b4 contended 192 times, 101997 avg us
[...]

第5章 SystemTap のエラーを理解する

本章では、SystemTap の使用時に一般的に発生したエラーについて説明します。
多くの診断エラーには、以下のような man ページの読み取りを提案する文字列が含まれます。
[man warning::example1]
[man error::example2]
このような場合、警告の各 manページを参照してください。example1 および error::example2。これは、その診断に固有の情報を提供するものです。

5.1. 解析エラーとセマンティックエラー

このタイプのエラーは、スクリプトがカーネルモジュールに変換される前の、SystemTap により構文解析が行われ C に変換される際に発生します。たとえば、タイプのエラーは、無効な値を変数やアレイに割り当てる演算から発生します。

parse error: expected abc, saw xyz

スクリプトに文法的なエラーまたは誤字や脱字のエラーが含まれています。プローブのコンテキストから考えると、SystemTap は間違ったコンストラクトのタイプを検出しました。

以下の無効な SystemTap スクリプトにはプローブハンドラーがありません。
probe vfs.read
probe vfs.write
その結果、パーサーは 2 行目の probe キーワード以外のことを期待していることを示す以下のエラーメッセージが表示されます。
parse error: expected one of '. , ( ? ! { = +='
saw: keyword at perror.stp:2:1
1 parse error(s).

parse error: embedded code in unprivileged script

スクリプトには安全でない埋め込み C コードが含まれています( %{ %} で囲まれたコードブロック)。SystemTap では、スクリプトに C コードを埋め込むことができるため、目的にあった tapsets がない場合には便利です。ただし、埋め込みの C コンストラクトは安全ではありません。そのため、スクリプトにこのような構造を検出すると SystemTap はこのエラーで警告を発します。

スクリプト内の似たコンストラクトがすべて確実に安全であることが分かっていて、stapdev グループ(または root 権限) のメンバーである場合は 、-g オプションを使用してguru モードでスクリプトを実行します。
stap -g script

semantic error: type mismatch for identifier 'ident' ... string vs. long

スクリプトの ident 関数は、間違ったタイプ(%s または % d )を使用していました。例5.1「error-variable.stp」execname() 関数は文字列を返すため、書式指定子は %d ではなく %s である必要があります。

例5.1 error-variable.stp

probe syscall.open
{
  printf ("%d(%d) open\n", execname(), pid())
}

semantic error: unresolved type for identifier 'ident'

識別子(変数など)が使用されているが、タイプ(整数または文字列)を決定できません。たとえば、スクリプトでは変数に値を割り当てないように、printf ステートメントの変数を使用する場合は発生します。

semantic error: Expecting symbol or array index expression

SystemTap ではアレイ内の場所や変数に値を割り当てることはできません。割り当ての目的地が有効な目的地になっていません。以下のようなサンプルコードを使用すると、このエラーが発生することになります。

probe begin { printf("x") = 1 }

semantic error: unresolved function call (変数 N 関数の検索中に発生するエラー)

スクリプト内の関数呼び出しまたはアレイインデックス式が無効な数の引数/パラメーターを使用しました。SystemTap では、性質にアレイのインデックス数または関数へのパラメーター数を確認できます

semantic error: array locals not supported, missing global declaration?

アレイをグローバル変数と宣言せずに、スクリプトがアレイ演算を使用しました (グローバル変数は、SystemTap スクリプトでの使用後に宣言されることができます)。アレイが一貫性のないアリティーと使用されると、同様のメッセージが表示されます。

semantic error: variable 'vaar' modivdced during 'foreach' iteration

var アレイは、アクティブな foreach ループ内で修正(割り当てまたは削除)されています。このエラーは、スクリプト内の操作が foreach ループ内で関数呼び出しを実行しても表示されます。

semantic error: probe point mismatch at position N, while resolving probe point pnt

SystemTap は、イベントまたは SystemTap 関数 pnt が参照しているものを理解しませんでした。これは通常、SystemTap が tapset ライブラリー内で pnt に一致するものを見つけられなかったことを意味します。ここでの N は、エラーの行とコラムを指します。

semantic error: no match for probe point, while resolving probe point pnt

pnt イベントおよびハンドラー関数はさまざまな理由で解決できませんでした。このエラーは、スクリプトに kernel.function("name") イベントが含まれ、名前が存在しない場合に発生します。このエラーはスクリプトに無効なカーネルファイル名やソース行番号が含まれていることを意味する場合もあります。

semantic error: unresolved target-symbol expression

スクリプトのハンドラーはターゲット変数を参照しますが、変数の値が解決できませんでした。このエラーは、ハンドラーがターゲット変数を参照した際にその変数がコンテキスト内で無効であることも意味します。これは、生成されたコードのコンパイラー最適化の結果である可能性もあります。

semantic error: libdwfl failure

デバッグ情報の処理に問題がありました。ほとんどの場合、このエラーは、kernel-debuginfo パッケージのインストールで発生します。インストールされた kernel-debuginfo パッケージ自体が、一貫性や正確性の問題となる可能性があります。

semantic error: cannot find package debuginfo

SystemTap は適切な kernel-debuginfo を見つけることができませんでした。

5.2. ランタイムエラーおよび警告

ランタイムエラーと警告は、SystemTap インストルメンテーションがインストールされ、システム上でデータを収集すると発生します。

WARNING: Number of errors: N, skipped probes: M

この実行時にエラー、プローブをスキップするか、またはその両方を実行します。N および M は、ある期間にイベントハンドラーの実行に必要な時間など、条件により発生したエラーおよびプローブがスキップされる回数です。

division by 0

スクリプトコードが無効な除算を実行しました。

aggregate element not found

値が累積されていない集合で、@count 以外の統計抽出関数が呼び出されました。これは、division by zero と類似したものです。

aggregation overflow

現時点で、集計値を含むアレイに明確な鍵のペアが過剰にあります。

MAXNESTING exceeded

関数呼び出しの入れ子の試行が多すぎます。許可されるデフォルトの関数呼び出しの入れ子は 10 です。

MAXACTION exceeded

プローブハンドラーによるステートメントの実行の試みが多すぎました。プローブハンドラー内で許可されるデフォルトのアクション数は 1000 です。

kernel/user string copy fault at ADDR

プローブハンドラーが、無効なアドレス (ADDR) でカーネルまたはユーザースペースから文字列をコピーしようとしました。

pointer dereference fault

ターゲット変数の評価など、ポインターの逆参照演算中に障害が発生しました。

第6章 リファレンス

本章では、SystemTap についてさらに詳細な記載をしている他の参考文を紹介しています。高度なプローブや tapset を記述する際の参考にしてください。
SystemTap Wiki
SystemTap Wiki』 とは、SystemTap のデプロイメント、使用、および開発に関連するリンクや記事がまとめられているページです。 http://sourceware.org/systemtap/wiki/HomePage をご覧ください。
SystemTap チュートリアル
本ガイドのコンテンツの多くは 『SystemTap Tutorial』 を元にしています。『SystemTap Tutorial』 は、C++ やカーネル開発などに関して中から高程度の知識を有するユーザー向けの内容になります。http://sourceware.org/systemtap/tutorial/ をご覧ください。
man stapprobes
stapprobes の man ページでは、SystemTap がサポートするさまざまなプローブポイントと、SystemTap tapset ライブラリーで定義された追加のエイリアスを列挙します。man ページの下部には、stapprobes.scsi、stapprobes.kprocess、stapprobes.kprocess、stapprobes.signal など、特定のシステムコンポーネントの同様のプローブポイントを列挙する他の man ページのリストが含まれています。
man stapfuncs
man ページの stapfuncs は、SystemTap tapset ライブラリーで対応している多数の関数および各関数に規定の構文を説明しています。ただし、これはサポート対象の全関数の完全なリストではないことに注意してください。文書化されていない関数もいくつかあります。
SystemTap Language Reference (SystemTap 言語リファレンス)
本ガイドは、SystemTap の言語構成および構文がすべて記載されているリファレンスです。C++ および他の似たようなプログラミング言語の基本的な知識または中程度の知識をお持ちのユーザーを対象としています。『SystemTap Language Reference』 は、すべてのユーザーを対象に http://sourceware.org/systemtap/langref/ で公開されています。
Tapset Developers Guide
SystemTap スクリプトの記述に熟達したら、独自のタップセットの記述に挑戦することができます。『Tapset Developers Guide』 では、タップセットライブラリーに関数を追加する方法を説明しています。
Test Suite
systemtap-testsuite パッケージを使用すると、ソースから構築しなくても SystemTap ツールチェーン全体をテストできます。さらに、調査およびテストが可能な SystemTap 4章便利な SystemTap スクリプト
デフォルトでは、systemtap-testsuite に含まれるサンプルスクリプトは、/usr/share/systemtap/testsuite/systemtap.examples にあります。

付録A 改訂履歴

改訂履歴
改訂 7-7Mon Aug 5 2019Vladimír Slávik
Red Hat Enterprise Linux 7.7 GA リリース
改訂 7-6Tue Oct 30 2018Vladimír Slávik
Red Hat Enterprise Linux 7.6 GA リリース
改訂 7-5.1Mon Jun 18 2018Radek Bíba
stap テスト画面の ID を使用します。
改訂 7-5Tue Jan 09 2018Vladimír Slávik
Red Hat Enterprise Linux 7.5 Beta 公開用リリース。
改訂 7-4Wed Jul 26 2017Vladimír Slávik
Red Hat Enterprise Linux 7.4 のリリース
改訂 7-3.9Tue May 16 2017Robert Krátký
7.4 ベータ版のビルド
改訂 1-8Wed Oct 19 2016Robert Kratky
Red Hat Enterprise Linux 7.3 のリリース
改訂 1-6Wed Jan 20 2016Robert Kratky
多数の修正のある非同期リリース。
改訂 1-5Thu Nov 11 2015Robert Kratky
Release for Red Hat Enterprise Linux 7.2.
改訂 0-3Fri Dec 6 2013Jacquelynn East
Red Hat Enterprise Linux 7.0 リリース

索引

シンボル

$count
サンプル使用例
ローカル変数, ファイル読み取り/書き込みの I/O 時間の追跡
$return
サンプル使用例
ローカル変数, ディスク読み取り/書き込みトラフィックの要約, 累積 I/O の追跡
'foreach' 中に変数が修正される
解析エラー/セマンティックエラー
SystemTap のエラーを理解する, 解析エラーとセマンティックエラー
@avg (整数抽出)
統計集計の計算
アレイ演算, 統計集計の計算
@count (整数抽出)
統計集計の計算
アレイ演算, 統計集計の計算
@max (整数抽出)
統計集計の計算
アレイ演算, 統計集計の計算
@min (整数抽出)
統計集計の計算
アレイ演算, 統計集計の計算
@sum (整数抽出)
統計集計の計算
アレイ演算, 統計集計の計算
はじめに
SystemTap の機能, SystemTap の機能
パフォーマンスの監視, はじめに
本ガイドの目的, 本ガイドの目的
目的、ドキュメント, 本ガイドの目的
アグリゲーションのオーバーフロー
ランタイムエラー/警告
SystemTap のエラーを理解する, ランタイムエラーおよび警告
アレイ, 連想アレイ
(参照 連想アレイ)
アレイ/アレイ要素の消去
アレイ演算, アレイおよびアレイ要素の消去/削除
Delete 演算子, アレイおよびアレイ要素の消去/削除
仮想ファイルシステムの読み込み (累積的以外)、集計, アレイおよびアレイ要素の消去/削除
同一プローブ内の複数のアレイ演算, アレイおよびアレイ要素の消去/削除
アレイからの値の読み取り
アレイ演算, アレイからの値の読み取り
シンプルな計算でのアレイの使用, アレイからの値の読み取り
空の一意の鍵, アレイからの値の読み取り
タイムスタンプ差分の計算
アレイ演算, アレイからの値の読み取り
アレイを使った代数公式
アレイからの値の読み取り
アレイ演算, アレイからの値の読み取り
アレイメンバーシップのテスト
条件付きステートメント、アレイの使用
アレイ演算, 条件付きステートメントにおけるアレイの使用
アレイローカルがサポートされない
解析エラー/セマンティックエラー
SystemTap のエラーを理解する, 解析エラーとセマンティックエラー
アレイ内での複数要素の処理
foreach
アレイ演算, アレイ内での複数要素の処理
foreach 出力の制限
アレイ演算, アレイ内での複数要素の処理
foreach 出力の順序
アレイ演算, アレイ内での複数要素の処理
アレイ演算, アレイ内での複数要素の処理
累積的仮想ファイルシステムの読み込み、集計
アレイ演算, アレイ内での複数要素の処理
アレイ内の複数要素
アレイ演算, アレイ内での複数要素の処理
アレイ演算
アレイ/アレイ要素の消去, アレイおよびアレイ要素の消去/削除
Delete 演算子, アレイおよびアレイ要素の消去/削除
仮想ファイルシステムの読み込み (累積的以外)、集計, アレイおよびアレイ要素の消去/削除
同一プローブ内の複数のアレイ演算, アレイおよびアレイ要素の消去/削除
アレイおよびアレイ要素の削除, アレイおよびアレイ要素の消去/削除
アレイからの値の読み取り, アレイからの値の読み取り
シンプルな計算でのアレイの使用, アレイからの値の読み取り
タイムスタンプ差分の計算, アレイからの値の読み取り
空の一意の鍵, アレイからの値の読み取り
アレイ内での複数要素の処理, アレイ内での複数要素の処理
foreach, アレイ内での複数要素の処理
foreach 出力の制限, アレイ内での複数要素の処理
foreach 出力の順序, アレイ内での複数要素の処理
反復、アレイ内の要素の処理, アレイ内での複数要素の処理
累積的仮想ファイルシステムの読み込み、集計, アレイ内での複数要素の処理
アレイ内の複数要素, アレイ内での複数要素の処理
条件付きステートメント、アレイの使用, 条件付きステートメントにおけるアレイの使用
アレイメンバーシップのテスト, 条件付きステートメントにおけるアレイの使用
統計集計の計算, 統計集計の計算
@avg (整数抽出), 統計集計の計算
@count (整数抽出), 統計集計の計算
@max (整数抽出), 統計集計の計算
@min (整数抽出), 統計集計の計算
@sum (整数抽出), 統計集計の計算
count (演算子), 統計集計の計算
統計集計が収集したデータの抽出, 統計集計の計算
統計集計への値の追加, 統計集計の計算
連想アレイ, SystemTap でのアレイ演算
関連する値の割り当て, 関連する値の割り当て
タイムスタンプをプロセス名に関連付ける, 関連する値の割り当て
関連する値の増加, 関連する値の増加
仮想ファイルシステムの読み込みの集計 (VFS 読み込み), 関連する値の増加
アーキテクチャー表記法、決定, 必要なカーネル情報パッケージのインストール
アーキテクチャー表記法の決定, 必要なカーネル情報パッケージのインストール
イベント
begin, Event
end, Event
kernel.function("function"), Event
kernel.trace("tracepoint"), Event
module("module"), Event
syscall.system_call, Event
timer イベント, Event
vfs.file_operation, Event
ワイルドカード, Event
同期および非同期イベントの例, Event
同期イベント, Event
概要, Event
非同期イベント, Event
イベントおよびハンドラー, SystemTap の作動方法
イベントタイプ
SystemTap の作動方法, SystemTap の作動方法
イベントワイルドカード, Event
イベント内のワイルドカード, Event
インストルメンテーションモジュール
cross-instrumentation, 他のコンピューター用のインストルメンテーション生成
インストール
systemtap パッケージ, SystemTap のインストール
systemtap-runtime パッケージ, SystemTap のインストール
カーネルバージョン、判断, 必要なカーネル情報パッケージのインストール
カーネル情報パッケージ, 必要なカーネル情報パッケージのインストール
初期テスト, 初期テスト
必要なパッケージ, 必要なカーネル情報パッケージのインストール
設定とインストール, インストールと設定
インデックス式
概要
アレイ, 連想アレイ
エラー
ランタイムエラー/警告, ランタイムエラーおよび警告
aggregate element not found, ランタイムエラーおよび警告
aggregation overflow, ランタイムエラーおよび警告
division by 0, ランタイムエラーおよび警告
MAXACTION exceeded, ランタイムエラーおよび警告
MAXNESTING exceeded, ランタイムエラーおよび警告
number of errors: N, skipped probes: M, ランタイムエラーおよび警告
pointer dereference fault, ランタイムエラーおよび警告
コピー障害, ランタイムエラーおよび警告
解析エラー/セマンティックエラー, 解析エラーとセマンティックエラー
'foreach' 中に変数が修正される, 解析エラーとセマンティックエラー
guru モード, 解析エラーとセマンティックエラー
libdwfl 失敗, 解析エラーとセマンティックエラー
スクリプトの文法的なエラー/誤字のエラー, 解析エラーとセマンティックエラー
プローブの不一致, 解析エラーとセマンティックエラー
プローブポイントに一致するものがない, 解析エラーとセマンティックエラー
変数/アレイに無効な値, 解析エラーとセマンティックエラー
特権のないスクリプトにコードが埋め込まれている, 解析エラーとセマンティックエラー
解決できないターゲット記号式, 解析エラーとセマンティックエラー
解決できない識別子のタイプ, 解析エラーとセマンティックエラー
解決できない関数呼び出し, 解析エラーとセマンティックエラー
記号やアレイに期待されているインデックス式, 解析エラーとセマンティックエラー
識別子タイプの不一致, 解析エラーとセマンティックエラー
非グローバルアレイ, 解析エラーとセマンティックエラー
オプション、stap
用途, SystemTap スクリプトの実行
カーネル/ユーザースペースで費やした時間、判定
SystemTap スクリプトの例, カーネルおよびユーザースペースで費やした時間の判定
カーネルおよびユーザースペース、費やした時間の判定
SystemTap スクリプトの例, カーネルおよびユーザースペースで費やした時間の判定
カーネルおよびユーザースペースで費やした時間の判定
SystemTap スクリプトの例, カーネルおよびユーザースペースで費やした時間の判定
カーネルバージョン、判断, 必要なカーネル情報パッケージのインストール
カーネルバージョンの判断, 必要なカーネル情報パッケージのインストール
カーネル情報パッケージ, 必要なカーネル情報パッケージのインストール
キーのペア
概要
アレイ, 連想アレイ
クロスインストルメンテーション
SystemTap スクリプトからインストルメンテーションを生成する, 他のコンピューター用のインストルメンテーション生成
SystemTap スクリプトからカーネルモジュールを構築する, 他のコンピューター用のインストルメンテーション生成
利点:, 他のコンピューター用のインストルメンテーション生成
設定
ホストシステムおよびターゲットシステム, 他のコンピューター用のインストルメンテーション生成
クロスインストルメンテーションの利点, 他のコンピューター用のインストルメンテーション生成
コピー障害
ランタイムエラー/警告
SystemTap のエラーを理解する, ランタイムエラーおよび警告
コマンドラインの引数
SystemTap ハンドラーコンストラクト
ハンドラー, コマンドラインの引数
コンポーネント
SystemTap スクリプト
概要, SystemTap スクリプト
システムコール、監視
SystemTap スクリプトの例, 最もよく使われるシステムコールの追跡
システムコールの監視
SystemTap スクリプトの例, 最もよく使われるシステムコールの追跡
システムコールの監視 (プロセスごとのボリューム)
SystemTap スクリプトの例, プロセスごとのシステムコールボリュームの追跡
システムコールボリューム (プロセスごと)、監視
SystemTap スクリプトの例, プロセスごとのシステムコールボリュームの追跡
シンプルな計算でのアレイの使用
アレイからの値の読み取り
アレイ演算, アレイからの値の読み取り
スクリプト
概要, SystemTap スクリプト
イベントおよびハンドラー, SystemTap スクリプト
コンポーネント, SystemTap スクリプト
ステートメントブロック, SystemTap スクリプト
プローブ, SystemTap スクリプト
形式および構文, SystemTap スクリプト
関数, SystemTap スクリプト
スクリプトの例
CPU ティック, カーネルおよびユーザースペースで費やした時間の判定
ctime()、使用例, ディスク読み取り/書き込みトラフィックの要約
futex システムコール, 競合ユーザースペースのロックの特定
I/O 時間の監視, ファイル読み取り/書き込みの I/O 時間の追跡
if/else 条件、代替の構文, ネットワークのプロファイリング
inode 番号, ファイルの読み取りおよび書き込みの監視
net/socket.c、関数の追跡, ネットワークソケットコードで呼び出された関数の追跡
stat -c、ファイルデバイス番号の決定 (整数形式), ファイルの読み取りおよび書き込みの監視
stat -c、全体デバイス番号の決定, I/O 監視 (デバイスごと)
thread_indent()、サンプル使用例, 呼び出し先の追跡
timer.ms()、サンプル使用例, 関数呼び出しのカウント
timer.s()、サンプル使用例, ポーリングアプリケーションの監視, 最もよく使われるシステムコールの追跡
trigger function, 呼び出し先の追跡
usrdev2kerndev(), I/O 監視 (デバイスごと)
カーネルおよびユーザースペースで費やした時間の判定, カーネルおよびユーザースペースで費やした時間の判定
システムコールの監視, 最もよく使われるシステムコールの追跡
システムコールの監視 (プロセスごとのボリューム), プロセスごとのシステムコールボリュームの追跡
ディスク I/O トラフィックの要約, ディスク読み取り/書き込みトラフィックの要約
デバイス I/O の監視, I/O 監視 (デバイスごと)
ネットワークのプロファイリング, ネットワークのプロファイリング, カーネルでのネットワークパケットドロップの監視
ネットワークソケットコードで呼び出された関数の追跡, ネットワークソケットコードで呼び出された関数の追跡
ファイルの読み取りおよび書き込みの監視, ファイルの読み取りおよび書き込みの監視
ファイルデバイス番号 (整数形式), ファイルの読み取りおよび書き込みの監視
ファイル属性の変更の監視, ファイル属性の変更の監視
プロセスのデッドロック (futex 競合により発生), 競合ユーザースペースのロックの特定
ポーリングアプリケーションの監視, ポーリングアプリケーションの監視
全体デバイス番号 (コマンドライン引数として使用), I/O 監視 (デバイスごと)
呼び出し先の追跡, 呼び出し先の追跡
着信 TCP 接続の監視, 着信 TCP 接続の監視
競合ユーザースペースのロックの特定(futex 競合), 競合ユーザースペースのロックの特定
累積 I/O の追跡, 累積 I/O の追跡
複数のコマンドライン引数、例, 呼び出し先の追跡
関数呼び出しの集計, 関数呼び出しのカウント
スクリプトの文法的なエラー/誤字のエラー
解析エラー/セマンティックエラー
SystemTap のエラーを理解する, 解析エラーとセマンティックエラー
スクリプトの誤字のエラー
解析エラー/セマンティックエラー
SystemTap のエラーを理解する, 解析エラーとセマンティックエラー
ステートメントブロック
SystemTap スクリプト
概要, SystemTap スクリプト
セッション、SystemTap, アーキテクチャー
タイムスタンプ、プロセス名との関連付け
関連する値の割り当て
アレイ演算, 関連する値の割り当て
タイムスタンプをプロセス名に関連付ける
関連する値の割り当て
アレイ演算, 関連する値の割り当て
タイムスタンプ差分、計算
アレイからの値の読み取り
アレイ演算, アレイからの値の読み取り
タイムスタンプ差分の計算
アレイからの値の読み取り
アレイ演算, アレイからの値の読み取り
ターゲットカーネル
cross-instrumentation, 他のコンピューター用のインストルメンテーション生成
ターゲットシステム
cross-instrumentation, 他のコンピューター用のインストルメンテーション生成
ターゲットシステムおよびホストシステム
設定, 他のコンピューター用のインストルメンテーション生成
ターゲット記号式、解決できない
解析エラー/セマンティックエラー
SystemTap のエラーを理解する, 解析エラーとセマンティックエラー
テスト、初期, 初期テスト
ディスク I/O トラフィック、要約
スクリプトの例, ディスク読み取り/書き込みトラフィックの要約
ディスク I/O トラフィックの要約
スクリプトの例, ディスク読み取り/書き込みトラフィックの要約
デバイス I/O の監視
SystemTap スクリプトの例, I/O 監視 (デバイスごと)
デバイス I/O、監視
SystemTap スクリプトの例, I/O 監視 (デバイスごと)
ネットワークのプロファイリング
SystemTap スクリプトの例, ネットワークのプロファイリング, カーネルでのネットワークパケットドロップの監視
ネットワークソケットコード、呼び出された関数の追跡
SystemTap スクリプトの例, ネットワークソケットコードで呼び出された関数の追跡
ネットワークソケットコードで呼び出された関数、追跡
SystemTap スクリプトの例, ネットワークソケットコードで呼び出された関数の追跡
ネットワークソケットコードで呼び出された関数の追跡
SystemTap スクリプトの例, ネットワークソケットコードで呼び出された関数の追跡
ネットワークトラフィック、監視
SystemTap スクリプトの例, ネットワークのプロファイリング, カーネルでのネットワークパケットドロップの監視
ハンドラー
SystemTap ハンドラーコンストラクト, 基本的な SystemTap ハンドラーコンストラクト
global, 変数
コマンドラインの引数, コマンドラインの引数
変数, 変数
構文および形式, 基本的な SystemTap ハンドラーコンストラクト
条件付き (conditional) ステートメント, 条件付き (conditional) ステートメント
For ループ, 条件付き (conditional) ステートメント
if/else, 条件付き (conditional) ステートメント
While ループ, 条件付き (conditional) ステートメント
条件演算子, 条件付き (conditional) ステートメント
概要, SystemTap ハンドラー/ボディー
ハンドラーおよびイベント, SystemTap の作動方法
SystemTap スクリプト
概要, SystemTap スクリプト
ハンドラー関数, SystemTap ハンドラー/ボディー
パフォーマンスの監視
はじめに, はじめに
ファイルのデバイス番号 (整数形式)
SystemTap スクリプトの例, ファイルの読み取りおよび書き込みの監視
ファイルの読み取り/書き込み、監視
SystemTap スクリプトの例, ファイルの読み取りおよび書き込みの監視
ファイルの読み取りおよび書き込みの監視
SystemTap スクリプトの例, ファイルの読み取りおよび書き込みの監視
ファイルへの書き込み/読み取り、監視
SystemTap スクリプトの例, ファイルの読み取りおよび書き込みの監視
ファイルデバイス番号 (整数形式)
SystemTap スクリプトの例, ファイルの読み取りおよび書き込みの監視
ファイル属性、変更の監視
SystemTap スクリプトの例, ファイル属性の変更の監視
ファイル属性の変更、監視
SystemTap スクリプトの例, ファイル属性の変更の監視
ファイル属性の変更の監視
SystemTap スクリプトの例, ファイル属性の変更の監視
フライトレコーダーモード, SystemTap フライトレコーダーモード
ファイルモード, ファイルフライトレコーダー
メモリー内モード, メモリー内フライトレコーダー
プロセスのデッドロック (futex 競合により発生)
SystemTap スクリプトの例, 競合ユーザースペースのロックの特定
プローブ
SystemTap スクリプト
概要, SystemTap スクリプト
プローブの不一致
解析エラー/セマンティックエラー
SystemTap のエラーを理解する, 解析エラーとセマンティックエラー
プローブポイント (一致なし)
解析エラー/セマンティックエラー
SystemTap のエラーを理解する, 解析エラーとセマンティックエラー
プローブポイントに一致するものがない
解析エラー/セマンティックエラー
SystemTap のエラーを理解する, 解析エラーとセマンティックエラー
ホストシステム
cross-instrumentation, 他のコンピューター用のインストルメンテーション生成
ホストシステムおよびターゲットシステム
クロスインストルメンテーション
設定, 他のコンピューター用のインストルメンテーション生成
ポーリングアプリケーション、監視
SystemTap スクリプトの例, ポーリングアプリケーションの監視
ポーリングアプリケーションの監視
SystemTap スクリプトの例, ポーリングアプリケーションの監視
メンバーシップ (アレイ内)、テスト
条件付きステートメント、アレイの使用
アレイ演算, 条件付きステートメントにおけるアレイの使用
ユーザーおよびカーネルスペース、費やした時間の判定
SystemTap スクリプトの例, カーネルおよびユーザースペースで費やした時間の判定
ランタイムエラー/警告
SystemTap のエラーを理解する, ランタイムエラーおよび警告
aggregate element not found, ランタイムエラーおよび警告
aggregation overflow, ランタイムエラーおよび警告
division by 0, ランタイムエラーおよび警告
MAXACTION exceeded, ランタイムエラーおよび警告
MAXNESTING exceeded, ランタイムエラーおよび警告
number of errors: N, skipped probes: M, ランタイムエラーおよび警告
pointer dereference fault, ランタイムエラーおよび警告
コピー障害, ランタイムエラーおよび警告
ローカル変数
name, SystemTap ハンドラー/ボディー
サンプル使用例
$count, ファイル読み取り/書き込みの I/O 時間の追跡
$return, ディスク読み取り/書き込みトラフィックの要約, 累積 I/O の追跡
一意の鍵
概要
アレイ, 連想アレイ
仮想ファイルシステム の読み込み (累積的)、集計
アレイ内での複数要素の処理
アレイ演算, アレイ内での複数要素の処理
仮想ファイルシステムの読み込み (累積的以外)、集計
アレイ/アレイ要素の消去
アレイ演算, アレイおよびアレイ要素の消去/削除
仮想ファイルシステムの読み込みの集計 (VFS 読み込み)
関連する値の増加
アレイ演算, 関連する値の増加
使用方法
SystemTap スクリプトの実行, SystemTap スクリプトの実行
オプション、stap, SystemTap スクリプトの実行
便利な SystemTap スクリプトの例, 便利な SystemTap スクリプト
値、割り当て
アレイ演算, 関連する値の割り当て
全体デバイス番号 (コマンドライン引数として使用)
SystemTap スクリプトの例, I/O 監視 (デバイスごと)
初期テスト, 初期テスト
反復、アレイ内の要素の処理
アレイ内での複数要素の処理
アレイ演算, アレイ内での複数要素の処理
同一プローブ内の複数のアレイ演算
アレイ/アレイ要素の消去
アレイ演算, アレイおよびアレイ要素の消去/削除
同期および非同期イベントの例
イベント, Event
同期イベント
イベント, Event
呼び出し先の追跡
SystemTap スクリプトの例, 呼び出し先の追跡
変数
SystemTap ハンドラーコンストラクト
ハンドラー, 変数
変数 (ローカル)
name, SystemTap ハンドラー/ボディー
サンプル使用例
$count, ファイル読み取り/書き込みの I/O 時間の追跡
$return, ディスク読み取り/書き込みトラフィックの要約, 累積 I/O の追跡
変数/アレイに無効な値
解析エラー/セマンティックエラー
SystemTap のエラーを理解する, 解析エラーとセマンティックエラー
形式および構文
printf(), SystemTap ハンドラー/ボディー
SystemTap スクリプト
概要, SystemTap スクリプト
SystemTap ハンドラーコンストラクト
ハンドラー, 変数
必要なパッケージ, 必要なカーネル情報パッケージのインストール
整数抽出
統計集計の計算
アレイ演算, 統計集計の計算
書式指定子
printf(), SystemTap ハンドラー/ボディー
書式文字列
printf(), SystemTap ハンドラー/ボディー
最も大きいディスクの読み取り/書き込み、識別
スクリプトの例, ディスク読み取り/書き込みトラフィックの要約
最も大きいディスクの読み取り/書き込みの特定
スクリプトの例, ディスク読み取り/書き込みトラフィックの要約
本ガイドの目的
はじめに, 本ガイドの目的
条件付きステートメント、アレイの使用
アレイ演算, 条件付きステートメントにおけるアレイの使用
アレイメンバーシップのテスト, 条件付きステートメントにおけるアレイの使用
条件演算子
条件付き (conditional) ステートメント
ハンドラー, 条件付き (conditional) ステートメント
構文
概要
アレイ, 連想アレイ
構文および形式
printf(), SystemTap ハンドラー/ボディー
SystemTap スクリプト
概要, SystemTap スクリプト
SystemTap ハンドラーコンストラクト
ハンドラー, 基本的な SystemTap ハンドラーコンストラクト
標準入力から、スクリプトを実行
用途, SystemTap スクリプトの実行
標準入力からスクリプトを実行, SystemTap スクリプトの実行
無効な除算
ランタイムエラー/警告
SystemTap のエラーを理解する, ランタイムエラーおよび警告
特権のないスクリプト、コードが埋め込まれている
解析エラー/セマンティックエラー
SystemTap のエラーを理解する, 解析エラーとセマンティックエラー
特権のないスクリプトにコードが埋め込まれている
解析エラー/セマンティックエラー
SystemTap のエラーを理解する, 解析エラーとセマンティックエラー
特権のないスクリプトに安全でないコードが埋め込まれている
解析エラー/セマンティックエラー
SystemTap のエラーを理解する, 解析エラーとセマンティックエラー
用途
stap, SystemTap スクリプトの実行
stapdev, SystemTap スクリプトの実行
staprun, SystemTap スクリプトの実行
stapusr, SystemTap スクリプトの実行
標準入力から、スクリプトを実行, SystemTap スクリプトの実行
目的、ドキュメント
はじめに, 本ガイドの目的
着信 TCP 接続、監視
SystemTap スクリプトの例, 着信 TCP 接続の監視
着信 TCP 接続の監視
SystemTap スクリプトの例, 着信 TCP 接続の監視
着信/発信の関数呼び出し、追跡
SystemTap スクリプトの例, 呼び出し先の追跡
着信/発信の関数呼び出しの追跡
SystemTap スクリプトの例, 呼び出し先の追跡
空の一意の鍵
アレイからの値の読み取り
アレイ演算, アレイからの値の読み取り
競合ユーザースペースのロック (futex 競合)、特定
SystemTap スクリプトの例, 競合ユーザースペースのロックの特定
競合ユーザースペースのロックの特定(futex 競合)
SystemTap スクリプトの例, 競合ユーザースペースのロックの特定
累積 I/O の監視
SystemTap スクリプトの例, 累積 I/O の追跡
累積 I/O の追跡
SystemTap スクリプトの例, 累積 I/O の追跡
累積 I/O、追跡
SystemTap スクリプトの例, 累積 I/O の追跡
累積的仮想ファイルシステムの読み込み、集計
アレイ内での複数要素の処理
アレイ演算, アレイ内での複数要素の処理
統計集計
アレイ演算, 統計集計の計算
統計集計が収集したデータの抽出
統計集計の計算
アレイ演算, 統計集計の計算
統計集計の計算
アレイ演算, 統計集計の計算
@avg (整数抽出), 統計集計の計算
@count (整数抽出), 統計集計の計算
@max (整数抽出), 統計集計の計算
@min (整数抽出), 統計集計の計算
@sum (整数抽出), 統計集計の計算
count (演算子), 統計集計の計算
統計集計が収集したデータの抽出, 統計集計の計算
統計集計への値の追加, 統計集計の計算
統計集計への値の追加
統計集計の計算
アレイ演算, 統計集計の計算
複数のコマンドライン引数、例
SystemTap スクリプトの例, 呼び出し先の追跡
複数のコマンドライン引数の例
SystemTap スクリプトの例, 呼び出し先の追跡
解析エラー/セマンティックエラー
SystemTap のエラーを理解する, 解析エラーとセマンティックエラー
'foreach' 中に変数が修正される, 解析エラーとセマンティックエラー
guru モード, 解析エラーとセマンティックエラー
libdwfl 失敗, 解析エラーとセマンティックエラー
スクリプトの文法的なエラー/誤字のエラー, 解析エラーとセマンティックエラー
プローブの不一致, 解析エラーとセマンティックエラー
プローブポイントに一致するものがない, 解析エラーとセマンティックエラー
変数/アレイに無効な値, 解析エラーとセマンティックエラー
特権のないスクリプトにコードが埋め込まれている, 解析エラーとセマンティックエラー
解決できないターゲット記号式, 解析エラーとセマンティックエラー
解決できない識別子のタイプ, 解析エラーとセマンティックエラー
解決できない関数呼び出し, 解析エラーとセマンティックエラー
記号やアレイに期待されているインデックス式, 解析エラーとセマンティックエラー
識別子タイプの不一致, 解析エラーとセマンティックエラー
非グローバルアレイ, 解析エラーとセマンティックエラー
解決できないターゲット記号式
解析エラー/セマンティックエラー
SystemTap のエラーを理解する, 解析エラーとセマンティックエラー
解決できない識別子のタイプ
解析エラー/セマンティックエラー
SystemTap のエラーを理解する, 解析エラーとセマンティックエラー
解決できない関数呼び出し
解析エラー/セマンティックエラー
SystemTap のエラーを理解する, 解析エラーとセマンティックエラー
記号やアレイに期待されているインデックス式
解析エラー/セマンティックエラー
SystemTap のエラーを理解する, 解析エラーとセマンティックエラー
設定とインストール, インストールと設定
識別子タイプの不一致
解析エラー/セマンティックエラー
SystemTap のエラーを理解する, 解析エラーとセマンティックエラー
連想アレイ
概要, 連想アレイ
example, 連想アレイ
インデックス式, 連想アレイ
キーのペア, 連想アレイ
一意の鍵, 連想アレイ
構文, 連想アレイ
関連する値, 連想アレイ
関数, SystemTap ハンドラー/ボディー
cpu(), SystemTap ハンドラー/ボディー
ctime(), SystemTap ハンドラー/ボディー
gettimeofday_s(), SystemTap ハンドラー/ボディー
pp(), SystemTap ハンドラー/ボディー
SystemTap スクリプト
概要, SystemTap スクリプト
target(), SystemTap ハンドラー/ボディー
thread_indent(), SystemTap ハンドラー/ボディー
tid(), SystemTap ハンドラー/ボディー
uid(), SystemTap ハンドラー/ボディー
関数呼び出し (着信/発信)、追跡
SystemTap スクリプトの例, 呼び出し先の追跡
関数呼び出し (解決できない)
解析エラー/セマンティックエラー
SystemTap のエラーを理解する, 解析エラーとセマンティックエラー
関数呼び出し、集計
SystemTap スクリプトの例, 関数呼び出しのカウント
関数呼び出しのカウント
SystemTap スクリプトの例, 関数呼び出しのカウント
関数呼び出しの集計
SystemTap スクリプトの例, 関数呼び出しのカウント
関数(ハンドラーで使用)
exit(), SystemTap ハンドラー/ボディー
関連する値
概要
アレイ, 連想アレイ
関連する値の割り当て
アレイ演算, 関連する値の割り当て
タイムスタンプをプロセス名に関連付ける, 関連する値の割り当て
タイムスタンプをプロセス名に関連付ける
アレイ演算, 関連する値の割り当て
関連する値の増加
アレイ演算, 関連する値の増加
仮想ファイルシステムの読み込みの集計 (VFS 読み込み), 関連する値の増加
集計 (統計)
アレイ演算, 統計集計の計算
非グローバルアレイ
解析エラー/セマンティックエラー
SystemTap のエラーを理解する, 解析エラーとセマンティックエラー
非同期イベント
イベント, Event

A

aggregate element not found
ランタイムエラー/警告
SystemTap のエラーを理解する, ランタイムエラーおよび警告
aggregation overflow
ランタイムエラー/警告
SystemTap のエラーを理解する, ランタイムエラーおよび警告

B

begin
イベント, Event

D

Delete 演算子
アレイ/アレイ要素の消去
アレイ演算, アレイおよびアレイ要素の消去/削除
division by 0
ランタイムエラー/警告
SystemTap のエラーを理解する, ランタイムエラーおよび警告

E

end
イベント, Event
example
概要
アレイ, 連想アレイ
exceeded MAXACTION
ランタイムエラー/警告
SystemTap のエラーを理解する, ランタイムエラーおよび警告
exceeded MAXNESTING
ランタイムエラー/警告
SystemTap のエラーを理解する, ランタイムエラーおよび警告
exit()
関数, SystemTap ハンドラー/ボディー

F

For ループ
条件付き (conditional) ステートメント
ハンドラー, 条件付き (conditional) ステートメント
foreach
アレイ内での複数要素の処理
アレイ演算, アレイ内での複数要素の処理
foreach 出力の制限
アレイ内での複数要素の処理
アレイ演算, アレイ内での複数要素の処理
foreach 出力の順序
アレイ内での複数要素の処理
アレイ演算, アレイ内での複数要素の処理
format
概要
アレイ, 連想アレイ
futex システムコール
SystemTap スクリプトの例, 競合ユーザースペースのロックの特定
futex 競合、定義
SystemTap スクリプトの例, 競合ユーザースペースのロックの特定
futex 競合、特定
SystemTap スクリプトの例, 競合ユーザースペースのロックの特定

G

gettimeofday_s()
関数, SystemTap ハンドラー/ボディー
global
SystemTap ハンドラーコンストラクト
ハンドラー, 変数
guru モード
解析エラー/セマンティックエラー
SystemTap のエラーを理解する, 解析エラーとセマンティックエラー

I

I/O の時間
SystemTap スクリプトの例, ファイル読み取り/書き込みの I/O 時間の追跡
I/O アクティビティーのプリント (累積)
SystemTap スクリプトの例, 累積 I/O の追跡
I/O トラフィック、要約
スクリプトの例, ディスク読み取り/書き込みトラフィックの要約
I/O 時間、監視
SystemTap スクリプトの例, ファイル読み取り/書き込みの I/O 時間の追跡
I/O 時間の監視
SystemTap スクリプトの例, ファイル読み取り/書き込みの I/O 時間の追跡
I/O 監視 (デバイスごと)
SystemTap スクリプトの例, I/O 監視 (デバイスごと)
if/else
条件付き (conditional) ステートメント
ハンドラー, 条件付き (conditional) ステートメント
if/else ステートメント、アレイの使用
アレイ演算, 条件付きステートメントにおけるアレイの使用
if/else 条件、代替の構文
SystemTap スクリプトの例, ネットワークのプロファイリング
inode 番号
SystemTap スクリプトの例, ファイルの読み取りおよび書き込みの監視

K

kernel.function("function")
イベント, Event
kernel.trace("tracepoint")
イベント, Event

L

libdwfl 失敗
解析エラー/セマンティックエラー
SystemTap のエラーを理解する, 解析エラーとセマンティックエラー

M

MAXACTION exceeded
ランタイムエラー/警告
SystemTap のエラーを理解する, ランタイムエラーおよび警告
MAXNESTING exceeded
ランタイムエラー/警告
SystemTap のエラーを理解する, ランタイムエラーおよび警告
module("module")
イベント, Event

N

name
ローカル変数, SystemTap ハンドラー/ボディー
net/socket.c、関数の追跡
SystemTap スクリプトの例, ネットワークソケットコードで呼び出された関数の追跡
number of errors: N, skipped probes: M
ランタイムエラー/警告
SystemTap のエラーを理解する, ランタイムエラーおよび警告

O

operations
アレイ/アレイ要素の消去, アレイおよびアレイ要素の消去/削除
Delete 演算子, アレイおよびアレイ要素の消去/削除
仮想ファイルシステムの読み込み (累積的以外)、集計, アレイおよびアレイ要素の消去/削除
同一プローブ内の複数のアレイ演算, アレイおよびアレイ要素の消去/削除
アレイおよびアレイ要素の削除, アレイおよびアレイ要素の消去/削除
アレイからの値の読み取り, アレイからの値の読み取り
シンプルな計算でのアレイの使用, アレイからの値の読み取り
タイムスタンプ差分の計算, アレイからの値の読み取り
空の一意の鍵, アレイからの値の読み取り
アレイ内での複数要素の処理, アレイ内での複数要素の処理
foreach, アレイ内での複数要素の処理
foreach 出力の制限, アレイ内での複数要素の処理
foreach 出力の順序, アレイ内での複数要素の処理
反復、アレイ内の要素の処理, アレイ内での複数要素の処理
累積的仮想ファイルシステムの読み込み、集計, アレイ内での複数要素の処理
アレイ内の複数要素, アレイ内での複数要素の処理
条件付きステートメント、アレイの使用, 条件付きステートメントにおけるアレイの使用
アレイメンバーシップのテスト, 条件付きステートメントにおけるアレイの使用
統計集計の計算, 統計集計の計算
@avg (整数抽出), 統計集計の計算
@count (整数抽出), 統計集計の計算
@max (整数抽出), 統計集計の計算
@min (整数抽出), 統計集計の計算
@sum (整数抽出), 統計集計の計算
count (演算子), 統計集計の計算
統計集計が収集したデータの抽出, 統計集計の計算
統計集計への値の追加, 統計集計の計算
連想アレイ, SystemTap でのアレイ演算
関連する値の割り当て
タイムスタンプをプロセス名に関連付ける, 関連する値の割り当て
関連する値の増加, 関連する値の増加
仮想ファイルシステムの読み込みの集計 (VFS 読み込み), 関連する値の増加

P

pointer dereference fault
ランタイムエラー/警告
SystemTap のエラーを理解する, ランタイムエラーおよび警告
pp()
関数, SystemTap ハンドラー/ボディー
printf()
書式指定子, SystemTap ハンドラー/ボディー
書式文字列, SystemTap ハンドラー/ボディー
構文および形式, SystemTap ハンドラー/ボディー

S

stap
用途, SystemTap スクリプトの実行
stap オプション, SystemTap スクリプトの実行
stapdev
使用方法, SystemTap スクリプトの実行
staprun
使用方法, SystemTap スクリプトの実行
stapusr
使用方法, SystemTap スクリプトの実行
stat -c、ファイルデバイス番号の決定 (整数形式)
SystemTap スクリプトの例, ファイルの読み取りおよび書き込みの監視
stat -c、全体デバイス番号の決定
SystemTap スクリプトの例, I/O 監視 (デバイスごと)
syscall.system_call
イベント, Event
SystemTap のアーキテクチャー, アーキテクチャー
SystemTap のエラーを理解する
ランタイムエラー/警告, ランタイムエラーおよび警告
aggregate element not found, ランタイムエラーおよび警告
aggregation overflow, ランタイムエラーおよび警告
division by 0, ランタイムエラーおよび警告
MAXACTION exceeded, ランタイムエラーおよび警告
MAXNESTING exceeded, ランタイムエラーおよび警告
number of errors: N, skipped probes: M, ランタイムエラーおよび警告
pointer dereference fault, ランタイムエラーおよび警告
コピー障害, ランタイムエラーおよび警告
解析エラー/セマンティックエラー, 解析エラーとセマンティックエラー
'foreach' 中に変数が修正される, 解析エラーとセマンティックエラー
guru モード, 解析エラーとセマンティックエラー
libdwfl 失敗, 解析エラーとセマンティックエラー
スクリプトの文法的なエラー/誤字のエラー, 解析エラーとセマンティックエラー
プローブの不一致, 解析エラーとセマンティックエラー
プローブポイントに一致するものがない, 解析エラーとセマンティックエラー
変数/アレイに無効な値, 解析エラーとセマンティックエラー
特権のないスクリプトにコードが埋め込まれている, 解析エラーとセマンティックエラー
解決できないターゲット記号式, 解析エラーとセマンティックエラー
解決できない識別子のタイプ, 解析エラーとセマンティックエラー
解決できない関数呼び出し, 解析エラーとセマンティックエラー
記号やアレイに期待されているインデックス式, 解析エラーとセマンティックエラー
識別子タイプの不一致, 解析エラーとセマンティックエラー
非グローバルアレイ, 解析エラーとセマンティックエラー
SystemTap の作動方法, SystemTap の作動方法
SystemTap セッション, アーキテクチャー
アーキテクチャー, アーキテクチャー
イベントおよびハンドラー, SystemTap の作動方法
イベントタイプ, SystemTap の作動方法
SystemTap の使用, SystemTap の使用
SystemTap の実行に必要な RPM, 必要なカーネル情報パッケージのインストール
SystemTap の実行に必要なパッケージ, 必要なカーネル情報パッケージのインストール
SystemTap の機能
はじめに, SystemTap の機能
SystemTap アーキテクチャー, アーキテクチャー
SystemTap スクリプト
便利な例, 便利な SystemTap スクリプト
概要, SystemTap スクリプト
イベントおよびハンドラー, SystemTap スクリプト
コンポーネント, SystemTap スクリプト
ステートメントブロック, SystemTap スクリプト
プローブ, SystemTap スクリプト
形式および構文, SystemTap スクリプト
関数, SystemTap スクリプト
SystemTap スクリプト、実行方法, SystemTap スクリプトの実行
SystemTap スクリプトからインストルメンテーション/カーネルモジュールをコンパイルする, 他のコンピューター用のインストルメンテーション生成
SystemTap スクリプトからインストルメンテーションモジュール、構築する, 他のコンピューター用のインストルメンテーション生成
SystemTap スクリプトからインストルメンテーションモジュールを構築する, 他のコンピューター用のインストルメンテーション生成
SystemTap スクリプトからカーネルモジュール、構築する, 他のコンピューター用のインストルメンテーション生成
SystemTap スクリプトからカーネルモジュールを構築する, 他のコンピューター用のインストルメンテーション生成
SystemTap スクリプトの例, 便利な SystemTap スクリプト
CPU ティック, カーネルおよびユーザースペースで費やした時間の判定
ctime()、使用例, ディスク読み取り/書き込みトラフィックの要約
futex システムコール, 競合ユーザースペースのロックの特定
I/O 時間の監視, ファイル読み取り/書き込みの I/O 時間の追跡
if/else 条件、代替の構文, ネットワークのプロファイリング
inode 番号, ファイルの読み取りおよび書き込みの監視
net/socket.c、関数の追跡, ネットワークソケットコードで呼び出された関数の追跡
stat -c、ファイルデバイス番号の決定 (整数形式), ファイルの読み取りおよび書き込みの監視
stat -c、全体デバイス番号の決定, I/O 監視 (デバイスごと)
thread_indent()、サンプル使用例, 呼び出し先の追跡
timer.ms()、サンプル使用例, 関数呼び出しのカウント
timer.s()、サンプル使用例, ポーリングアプリケーションの監視, 最もよく使われるシステムコールの追跡
trigger function, 呼び出し先の追跡
usrdev2kerndev(), I/O 監視 (デバイスごと)
カーネルおよびユーザースペースで費やした時間の判定, カーネルおよびユーザースペースで費やした時間の判定
システムコールの監視, 最もよく使われるシステムコールの追跡
システムコールの監視 (プロセスごとのボリューム), プロセスごとのシステムコールボリュームの追跡
ディスク I/O トラフィックの要約, ディスク読み取り/書き込みトラフィックの要約
デバイス I/O の監視, I/O 監視 (デバイスごと)
ネットワークのプロファイリング, ネットワークのプロファイリング, カーネルでのネットワークパケットドロップの監視
ネットワークソケットコードで呼び出された関数の追跡, ネットワークソケットコードで呼び出された関数の追跡
ファイルの読み取りおよび書き込みの監視, ファイルの読み取りおよび書き込みの監視
ファイルデバイス番号 (整数形式), ファイルの読み取りおよび書き込みの監視
ファイル属性の変更の監視, ファイル属性の変更の監視
プロセスのデッドロック (futex 競合により発生), 競合ユーザースペースのロックの特定
ポーリングアプリケーションの監視, ポーリングアプリケーションの監視
全体デバイス番号 (コマンドライン引数として使用), I/O 監視 (デバイスごと)
呼び出し先の追跡, 呼び出し先の追跡
着信 TCP 接続の監視, 着信 TCP 接続の監視
競合ユーザースペースのロックの特定(futex 競合), 競合ユーザースペースのロックの特定
累積 I/O の追跡, 累積 I/O の追跡
複数のコマンドライン引数、例, 呼び出し先の追跡
関数呼び出しの集計, 関数呼び出しのカウント
SystemTap スクリプトの実行
用途, SystemTap スクリプトの実行
SystemTap スクリプト関数, SystemTap ハンドラー/ボディー
SystemTap ステートメント
SystemTap ハンドラーコンストラクト
global, 変数
コマンドラインの引数, コマンドラインの引数
変数, 変数
条件付き (conditional) ステートメント, 条件付き (conditional) ステートメント
For ループ, 条件付き (conditional) ステートメント
if/else, 条件付き (conditional) ステートメント
While ループ, 条件付き (conditional) ステートメント
条件演算子, 条件付き (conditional) ステートメント
SystemTap セッション, アーキテクチャー
SystemTap ハンドラー
SystemTap ハンドラーコンストラクト, 基本的な SystemTap ハンドラーコンストラクト
構文および形式, 基本的な SystemTap ハンドラーコンストラクト
systemtap パッケージ, SystemTap のインストール
systemtap-runtime パッケージ, SystemTap のインストール
systemtap-testsuite パッケージ
サンプルスクリプト, 便利な SystemTap スクリプト

T

Tapsets
定義, tapsets
target()
関数, SystemTap ハンドラー/ボディー
TCP 接続 (着信)、監視
SystemTap スクリプトの例, 着信 TCP 接続の監視
thread_indent()
関数, SystemTap ハンドラー/ボディー
thread_indent()、サンプル使用例
SystemTap スクリプトの例, 呼び出し先の追跡
tid()
関数, SystemTap ハンドラー/ボディー
timer イベント
イベント, Event
timer.ms()、サンプル使用例
SystemTap スクリプトの例, 関数呼び出しのカウント
timer.s()、サンプル使用例
SystemTap スクリプトの例, ポーリングアプリケーションの監視, 最もよく使われるシステムコールの追跡
tracepoint, Event, カーネルでのネットワークパケットドロップの監視
trigger function
SystemTap スクリプトの例, 呼び出し先の追跡

V

VF 読み取り、集計
関連する値の増加
アレイ演算, 関連する値の増加
vfs.file_operation
イベント, Event

W

While ループ
条件付き (conditional) ステートメント
ハンドラー, 条件付き (conditional) ステートメント

法律上の通知

Copyright © 2019 Red Hat, Inc.
このドキュメントは、Red Hat が Creative Commons Attribution-ShareAlike 3.0 Unported License に基づいてライセンスを提供しています。If you distribute this document, or a modified version of it, you must provide attribution to Red Hat, Inc. and provide a link to the original.If the document is modified, all Red Hat trademarks must be removed.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, JBoss, OpenShift, Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent.Red Hat Software Collections is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission.We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.