Process Monitor の基本的な使い方について


Process Monitor の基本的な使い方について

Process Monitor とは、Microsoft 社の Sysinternals で公開されている、OS 上のアプリケーションやサービスが行うレジストリアクセス、ファイルアクセスなどをモニターするツールです。

このツールで出来ること

Process Monitor はフィルタドライバとして動作する (*) ので、プロセスの I/O を確認することが出来ます。例えば、以下のようなことが出来ます。

  • レジストリアクセスの監視
  • ファイルアクセスの監視
  • アプリケーションのスタックの確認

fltmc filters でこの様子が確認できます。

このツールで出来ないこと (難しいこと)

  • ネットワークパケットの確認 -> WireShark や netsh、Fiddler 等を使いましょう。
  • OS 負荷調査等より高度な解析が必要 -> WPR 等を使いましょう。  

使い方について

導入まで

  1. 以下のサイトをクリックし、Download Process Monitor にてダウンロードします。
    https://docs.microsoft.com/en-us/sysinternals/downloads/procmon

  2. 解凍し、Procmon.exe をクリックします。EULA が表示されたら表示にしたがってください。

  3. フィルター画面が表示されます。設定すると表示行をフィルターすることができます。サービスの動作も見えてほしいので、"Process Name is System" のチェックを外して "OK" を押します。

  4. すぐにキャプチャが始まってしまうので、虫メガネアイコンをクリックしキャプチャを止めます。そして、消しゴムアイコンで一旦全部クリアしましょう。もう一度虫メガネアイコンをクリックするとキャプチャを開始することができます。

設定関連

  • スタック情報を解決するためにシンボルパスを設定します。
    [Options] - [Configure Symbols] より以下を設定します。
    srv*<任意のシンボルフォルダ>*https://msdl.microsoft.com/download/symbols

  • 列の先頭行を右クリックし "Select Columns" をクリックすると、列をカスタマイズすることが出来ます。私はこんな感じにチェックを増やしてます。

Duration : 経過時間
User Name : プロセスを実行したユーザー名
Integrity : 整合性レベル
Thread ID : スレッド ID

使ってみる

キャプチャを開始すると大量に行が表示されます。

基本的に Operation を見ながら流れを追っていく形になるかと思います。

Reg~ はレジストリ関連
Thread~ はスレッド関連
Query~ や Read~ は参照
Create~ は作成や参照
Write~ や Set~ は書き込み
Close~ は終了
結果は Result で確認できます。

実際に追ってみる

テストシナリオが難しいのですが。。とりあえず、何かのアプリケーションがファイルに大量アクセスして色々起きてるということにします。
とりあえず、VC++ で以下のコードを書きました。

ConsoleApplication1.cpp
#include "stdafx.h"
#include <iostream>
#include <string>
#include <fstream>

using namespace std;

int main() {
    const int LOOP = 10000;
    for (int i = 0; i < LOOP; i++) {
        ifstream ifs("C:\\work\\test\\data.txt", ios_base::in);
        string str;

        if (ifs.fail()) {
            cerr << "File do not exist.\n";
            int  waituser;
            cin >> waituser;
            return 0;
        }
    }

    int  waituser;
    cout << "Finished";
    cin >> waituser;
    return 0;
}
  1. Process Monitor でキャプチャ開始

  2. ConsoleApplication1 を開始~終了

  3. Process Monitor でキャプチャ終了とします。

[Tools] - [File Summary] をクリックします。

いい感じに data.txt が先頭に出てきましたね。

data.txt の行をダブルクリックしますと、data.txt のパスでフィルターされます。

先頭行をダブルクリックしてみますと、Event Properties としてオペレーションの情報と引数が表示されます。

CreateFile API の引数とほぼほぼマッチしてますね。

HANDLE CreateFileA(
LPCSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
);
https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-createfilea

なお、この Operation は Process Monitor が勝手に区分けしただけで、System Call の名称と合致するわけではありません。
また、引数も API 内の呼び出しに応じて何段階かに別れて表示される場合もあります。

[Process]タブではアプリケーションのパスやコマンドライン、プロセス情報や読み込まれたモジュールまで表示されます。

[Stack] タブですが、スタック情報が表示され、"Source" をクリックするとソースの該当行も表示されます。(*)

なぜかそのまま解決されてしまったのですが、本当は Process Monitor - [Options] - [Configure Symbols] よりシンボルとソースコードのパスを設定します。あと、シンボルが上手く解決できないことが結構あるあるなのですが、この場合、もう一つ Process Monitor を立ち上げたりしてシンボルの解析状況を確認し、exe や pdb を配置してあげます。(これが正しい方法なのかは疑問ですが・・)

Process Monitor - [Tools] - "Stack Summary" ではスタックごとの使用率を見ることもできます。ここから "Source" を見ることもできますし、これでボトルネックを探していくパターンもあると思います。

なお、絶対に意識しておかないといけないのは、Process Monitor では Result に多くのエラーが表示されますが、実際には関係のない場合も多く、これが本当に調査したい内容なのかどうかを見極める必要があります。

例えば、適当に Excel を起動してみてキャプチャした以下の画像では "NAME COLLISION" というエラーが大量に表示されています。

そして、NAME COLLISION と次の SUCCESS の行をそれぞれダブルクリックして 、"Event Properties" - "Stack" を確認すると、呼び出し側のアドレスが変わらないため、Excel が SHGetFolderPath API を Call し、その内部の呼び出しでこのエラーがハンドリングされている (であろう*) 様子が確認できます。

*Process Monitor はデバッグではなく過程がわからないので "あろう" となります。

なお、当然適当に起動した Excel はちゃんと起動されていますので、Result で何かエラーが出てるというだけでは判断できないのですね。

お役立ち機能について

手にとっていただいた皆様は、おそらく Filter や Highlight などを触られたのではないかなと思います。
ここでは、ちょっと目に止まりそうにないと思われる項目をピックアップします。

  • Drop Filter Event
    Process Monitor - [Filter] - "Drop Filter Event" を設定すると、フィルター条件に引っかかったものだけをキャプチャします。

  • History Depth
    Process Monitor - [Options] - "History Depth" を設定すると、最大容量を設定できます。なお、あんまり厳密ではないので、大体そのくらいの容量で制限されるとお考えください。

  • Enable Boot Logging
    Process Monitor - [Options] – "Enable Boot Logging" を設定すると、ブート時に Process Monitor がログ採取を行います。なお、Generate thread profiling events のチェックはいらないと思います。ブート後、Process Monitor を起動するとログ採取を終了できます。

  • Backing Files
    Process Monitor - [File] – "Backing Files" を設定すると、既定の仮想メモリ上へのアウトプットからファイルへのアウトプットに切り替えることができます。Process Monitor は長時間採取することはおすすめしませんが、必要に応じて使用してみてください。なお、History Depth と併用することもできます。

  • コマンドライン
    Process Monitor はコマンドラインで実行できます。Process Monitor - [Help] – "Command Line Options" では使用できるコマンドが記載されています。

以上、Process Monitor の基本的な使い方でした。
お読みいただきましてありがとうございました。