カーネルのメモリリークを調べてメモリが圧迫される原因を突き止める [Win10]
カーネルモードで動いていたセキュリティソフトのドライバーに潜むバグがメモリリークを引き起こし、他のアプリケーションのメモリを圧迫していた話。これはイレギュラーなケースだと思うが、パソコンの動作が異常に重いときはこういう可能性も疑った方がいいと思う。
ある日、会社で使っているパソコンが異常に重くなるという相談を受けた。聞くところでは、PC再起動直後は快調に動くのだが、電源を入れっぱなしにしておくと、数時間後にはブラウザやExcelのみならずWindows上のあらゆる動作が異常に重くなってくるとか。
話を聞いた時点では、ブラウザのタブを多数開いたままになっているんじゃないか、サイズが肥大化したExcelファイルを開いているんじゃないか、もしくはハードディスクなどのハードウェアの不調かと疑っていたのだが、タスクマネージャーを開いた時点で「尋常ではない状態」であることに気付いた。
プロセスタブを開くと、アプリのメモリ使用量がどれも非常に「低い」にもかかわらず、メモリ使用率は異常に高い。プロセスの一覧にない何かがメモリを圧迫しているようである。
パフォーマンスタブのメモリを見ると、明らかにおかしい数字を見つけた。物理メモリ8GBに対して「非ページプール」が5GB超と半分以上を占めている。(以下全てのスクリーンショットは正常動作のもの)
プールメモリとは、主にカーネルモードで動作するデバイスドライバーやWindowsのシステムが割り当てたメモリで、特に「非ページプール」は仮想メモリにページされない(=必ず物理メモリを使用する)よう指定されたメモリである。
タスクマネージャーにはその内訳を調べる機能はない。これを調べるには Windows Driver Kit (WDK) にドライバー開発者向けのツールとして収録されている「PoolMon」を使用する。
→ Windows Driver Kit (WDK) のダウンロード - Windows drivers | Microsoft Docs
WDKのダウンロード・インストールには相当なドライブ空き容量を必要とするが、PoolMon.exe自体はたった60数キロバイトの実行ファイルであり、ファイル単体で他のPCに持ち込んでもそのまま使える。このツール単体で配布して欲しいものだ。
poolmonをスイッチ無しで起動すると、システムプールの使用量がタグの名前順でリストされる。TypeのPagedはページプール、Nonpは非ページプールを示す。Allocはメモリ割り当て操作の回数、Freeはメモリ開放操作の回数、DiffはAllocとFreesの差分、Bytesは割り当てサイズを示す。また、括弧内は前回更新分からの差分を示す。
bキーを一回押すとBytesの高い順、つまり割り当てサイズの高い順に並ぶ。また、pキーを一回押すとNonp(非ページプール)だけに絞り込むことができる。
継続的にメモリリークを起こしているドライバーがあれば、メモリーを解放することなく割り当て続けていることになるので、そのDiffとBytesの値が増え続けるはず。
ただ、異常値を示している項目を見つけたとしても、このリストに表示される4文字のTagから原因となっているドライバーを予想するのは困難だ。そこで、コマンドを使ってシステムファイル (*.sys)に含まれる4文字を探索することで、原因のファイルを特定する。コマンドプロンプトでFINDSTRコマンドを使う方法と、PowerShellのSelect-Stringコマンドレットを使う方法があるが、今回は後者の方法を試してみる。
次の例ではWindows PowerShellを立ち上げて、”Vi57”という文字列を含む.sysファイルをC:\Windows\System32\driversフォルダーから検索している、
PS C:\Users\adminal> Set-Location "C:\Windows\System32\drivers"
PS C:\Windows\System32\drivers> Select-String -Path *.sys -Pattern "Vi57" -CaseSensitive | Select-Object FileName -Unique
Filename
--------
dxgmms2.sys
dxgmms2.sysというファイルがヒットした。ファイルのプロパティを調べると、WindowsのDirectX関連のファイルのようだ。こんな感じで原因を探っていったら、セキュリティソフトが原因であることが判明した。
セキュリティソフトの不具合によるパフォーマンスの低下は今まで数回遭遇したことあるが、原因を調べるのは簡単ではない。まず、セキュリティソフトはシステムに深く根付いているので、その挙動を調べるには今回のように難易度が高い手順を踏む必要がある。そして、不具合発生中はパフォーマンスが低下している状態にあり、操作を中々受け付けないという状態で解析ツールを使うのは苦労と困難を伴う。このようなツールは原因の詳細分析に使うものであって、まだ原因が確定していないうちは、周辺機器を全部外す、最近インストールしたソフトをアンインストールする、セキュリティソフトの機能を切ってみる、という初歩的なところから攻めていった方がいい。セキュリティソフトのサポートに問い合わせても、おそらく同じような回答をするだろう。
参考サイト
- Finding Memory Leaks with PoolMon | by Clint Colding | Medium
- PoolMon - Windows drivers | Microsoft Docs
EOF