Linux のメモリ管理において、`slab_unreclaimable` は、スラブアロケータによって割り当てられ、回収不能としてマークされたメモリです。総メモリに対する回収不能なメモリの比率が高いと、利用可能なメモリが減少し、システムパフォーマンスが低下する可能性があります。このトピックでは、Alibaba Cloud Linux システムで `slab_unreclaimable` のメモリ使用量が過剰になった場合のトラブルシューティング方法について説明します。
症状
Linux インスタンスで cat /proc/meminfo | grep "SUnreclaim" コマンドを実行して `SUnreclaim` の値を確認すると、その値が高い (例:SUnreclaim: 6069340 kB) ことがあります。この値がシステムの総メモリの 10% を超える場合、`slab_unreclaimable` のメモリ使用量が過剰であり、システムにスラブメモリリークが発生している可能性があることを示しています。
原因
Linux のメモリ管理において、スラブはカーネルがメモリの小さなブロックを効率的に割り当てるために使用するキャッシュ機構です。カーネルコンポーネントやドライバーは、`kmalloc` などのメモリ割り当てインターフェイスを呼び出して、スラブアロケータにメモリをリクエストします。これらのコンポーネントやドライバーがメモリを適切に解放しない場合、回収不能なメモリの量が増加し、利用可能なメモリが減少します。
トラブルシューティング手順
トラブルシューティング対象の Linux インスタンスに接続します。
詳細については、「ECS リモート接続方法の選択」をご参照ください。
次のコマンドを実行して、多数の
objectsまたは大量のメモリを使用し、回収不能としてマークされているスラブの名前を特定します。最も多くの
objectsまたはメモリを使用しているスラブに関する情報を表示します。slabtop -s -aコマンドの出力で、
OBJ/SLAB列の値が高いスラブの名前 (NAME列) を確認し、記録します。スラブメモリが回収不能かどうかを確認します。
コマンドで、
<slab NAME>を前の手順で確認したOBJ/SLAB列の値が高いスラブの名前に置き換えます。cat /sys/kernel/slab/<slab NAME>/reclaim_accountたとえば、
kmalloc-192という名前のスラブが回収不能かどうかを確認します。cat /sys/kernel/slab/kmalloc-192/reclaim_account結果が 0 の場合はスラブメモリが回収不能であることを示し、1 の場合は回収可能であることを示します。
`slab_unreclaimable` のメモリ使用量が過剰な原因を特定します。
crash ツールを使用した静的解析、または perf ツールを使用した動的解析によって、スラブメモリリークの原因を特定できます。このシナリオ例では、メモリリークが発生しているスラブの名前は
kmalloc-192です。crash ツールを使用した静的解析
次のコマンドを実行して crash ツールをインストールします。
sudo yum install crash -y次のコマンドを実行して kernel-debuginfo ツールをインストールします。
Alibaba Cloud Linux 3
sudo yum install -y kernel-debuginfo-<kernel_version> --enablerepo=alinux3-plus-debug説明kernel_versionを、ご利用のシステムの実際のカーネルバージョンに置き換えます。uname -rコマンドを実行すると、カーネルバージョンをクエリできます。Alibaba Cloud Linux 2
sudo yum install kernel-debuginfo -y
次のコマンドを実行して crash ツールを起動します。
sudo crashcrash ツールで、次のコマンドを実行して
kmalloc-192のメモリ統計情報を表示します。kmem -S kmalloc-192大量の統計情報が返された場合は、最後の数行 (たとえば 10 行) のみを表示できます。
kmem -S kmalloc-192 | tail -n 10次のようなサンプル出力が返されます:
SLAB MEMORY NODE TOTAL ALLOCATED FREE ffffea004c94e780 ffff88132539e000 0 42 29 13 ffffea004cbef900 ffff88132fbe4000 0 42 40 2 ffffea000a0e6280 ffff88028398a000 0 42 40 2 ffffea004bfa8000 ffff8812fea00000 0 42 41 1 ffffea006842b380 ffff881a10ace000 0 42 41 1 ffffea0009e7dc80 ffff880279f72000 0 42 34 8 ffffea004e67ae80 ffff881399eba000 0 42 40 2 ffffea00b18d6f80 ffff882c635be000 0 42 42 0ffff88028398a000の統計情報では、空きメモリ (FREE列) が少なく、割り当て済みメモリ (ALLOCATED列) が多くなっています。crash ツールで、次のコマンドを実行して
ffff88028398a000のメモリ情報を表示します。rd ffff88028398a000 512 -Sこのコマンドは大量の情報を返します。プロンプトに従って複数ページを分析用に表示できます。例:
返された情報に
put_cred_rcu関数が複数回出現する場合は、Linux カーネルのソースコードでput_cred_rcu関数を検索します。void __put_cred(struct cred *cred) { call_rcu(&cred->rcu, put_cred_rcu); }put_cred_rcu関数は、`cred` 構造体を非同期に解放するために使用されます。`cred` 構造体の末尾にput_cred_rcuが存在することは、カーネルの `cred` 構造体でスラブメモリリークが発生していることを示します。
perf ツールを使用した動的解析
次のコマンドを実行して perf ツールをインストールします。
sudo yum install perf -y次のコマンドを実行して perf ツールを使用し、
kmalloc-192内の解放されていないメモリを動的に記録します。データは 200 秒間隔で記録されます。sudo perf record -a -e kmem:kmalloc --filter 'bytes_alloc == 192' -e kmem:kfree --filter ' ptr != 0' sleep 200sudo perf record -a -e kmem:kmalloc --filter 'bytes_alloc == 192' -e kmem:kfree --filter ' ptr != 0' sleep 200現在のディレクトリで、動的に記録されたデータを一時ファイルに出力します。
この例では、一時ファイルの名前は testperf.txt です。
sudo perf script > testperf.txt次のコマンドを実行して testperf.txt ファイルの内容を表示します。
cat testperf.txtメモリ情報を手動で検査し、解放されたメモリがない (
free) エントリを探します。次に、Linux カーネルのソースコードで、スラブメモリリークの原因となっている関数を検索します。
crash や perf などのツールを使用して関数呼び出しパスや影響を受けるカーネルデータ構造を特定した後、カーネル開発者または専門の運用保守 (O&M) エンジニアの指導のもとでメモリリークの具体的な原因を特定します。その後、メモリリークを解決します。
考えられる解決策は次のとおりです:
カーネルをアップグレードするか、パッチを適用する。
カーネルパラメーターを調整する。
影響を受けるサービスまたはモジュールを再起動する。
アプリケーションまたはドライバーを最適化する。
システムを再起動する。
関連ドキュメント
スラブメモリリークは、インスタンス上のアプリケーションで利用可能なメモリを減らし、メモリの断片化を引き起こします。これにより、システムの Out-Of-Memory (OOM) Killer がトリガーされ、システムパフォーマンスの変動を引き起こす可能性があります。
メモリの断片化: Linux のメモリ断片化の緩和
Polkit のメモリリーク: Alibaba Cloud Linux 2 の polkit におけるメモリリークの解決方法
システムの OOM Killer: OOM Killer のトラブルシューティング