Linux の仮想メモリは各プロセスに保護された仮想アドレス空間を与えながら、カーネルがファイルを共有し、
アドレス空間をオーバーコミットし、物理ページを回収し、NUMA ノードへメモリを配置できるようにします。
以下ではメモリ管理ユニット(MMU)を仮定します。Linux には MMU のないシステム向けに独立した nommu 実装があります。
変換と TLB #
すべてのロード、ストア、命令フェッチは仮想アドレスを使います。ハードウェアページテーブルはアドレスを物理ページフレームとオフセットへ変換します。 Linux は階層を 5 レベルでモデル化します。
PGD— ページグローバルディレクトリP4D— ページ第 4 レベルディレクトリPUD— ページ上位ディレクトリPMD— ページ中間ディレクトリPTE— ページテーブルエントリ
ハードウェアレベルが少ないアーキテクチャでは、未使用の Linux レベルを隣接レベルへ折りたたみます。 アクセスごとに複数のページテーブルをたどるコストが高いため、CPU は変換を translation lookaside buffer(TLB)にキャッシュします。 マッピングを変更するには、影響を受けるアドレス空間を実行できるすべての CPU で古い変換を無効化する必要があります。
基本ページサイズはアーキテクチャとカーネル設定に依存します。より高いページテーブルレベルのマッピングは大きなページをカバーでき、 ページテーブルメモリと TLB 圧力を減らします。Linux には 2 つの独立した huge page 機構があります。
- HugeTLB は明示的な huge page を予約・管理し、一般に
hugetlbfsorMAP_HUGETLB; capacity and allocation failure are part of its operational contract. - Transparent Huge Pages(THP) はカーネルポリシーに従って適格なマッピングを kernel policy, without a distinct application mapping ABI. Promotion and compaction can introduce latency, so workloads should measure rather than assume a benefit.
アドレス空間とマッピング #
各ユーザー空間アドレス空間は mm_struct で記述されます。カーネルスレッドは通常、独立したユーザー空間 mm を持たず、
必要な場合にアーキテクチャ固有の実行がアクティブなアドレス空間コンテキストを使います。
カーネルは連続した仮想メモリ領域を vm_area_struct(VMA)として表します。
VMA は半開アドレス範囲、権限、フラグ、バッキングオブジェクト、フォールト操作を記録します。現代のカーネルは maple tree で VMA をインデックス化します。
An execve(2) creates mappings for executable and shared-library segments.
Other common VMAs include the stack, heap, anonymous mmap(2) mappings,
file-backed mappings, shared memory, and the vDSO. mmap(2) reserves a virtual
range and its access policy; it need not allocate or read all physical pages at
mapping time.
mprotect(2) changes VMA permissions, and munmap(2) removes mappings.
Permission checks require both a suitable VMA and a suitable page-table entry.
Guard pages, non-executable mappings, and address-space layout randomization are
therefore enforcement mechanisms, not merely bookkeeping.
フォールト、デマンドページング、コピーオンライト #
ページフォールトは、変換が存在しないか、試みたアクセスが現在のエントリの権限に違反するため、制御をカーネルへ移します。 フォールトハンドラーは VMA を見つけ、アクセスが合法か判断します。
- minor fault はストレージ I/O なしで解決されます。たとえば常駐する resident page-cache page or installing a newly allocated zero-filled page.
- major fault は実行継続前にストレージ I/O を必要とします。
- 不正なアドレスまたは許可されないアクセスは通常
SIGSEGVを生成しますが、 object-specific failures, such as an inaccessible file-backed page, generateSIGBUS.
匿名メモリは最初、共有された読み取り専用ゼロページへマップできます。書き込みでフォールトが発生し、非公開の物理ページを取得します。
fork(2) 後、親と子は通常、読み取り専用マッピングを通じてページを共有します。
最初の書き込み側はコピーオンライトフォールトを起こして非公開ページを受け取り、もう一方のマッピングは変更しません。
コピーオンライトにより exec() する子の fork() は安価になりますが、大規模な fork 後の書き込みは高価になることがあります。
File-backed mappings and read(2) use the page cache. Clean cache pages are
reclaimable because the kernel can reread the file. Dirty shared mappings must
be written back before their frames can be reused. A private file mapping uses
copy-on-write for writes, so its modified pages are anonymous rather than
changes to the backing file.
物理割り当てと NUMA #
Linux はページディスクリプターで物理フレームを記述し、NUMA ノードとゾーンでメモリを分割します。 ゾーンはハードウェア制約を表します。たとえば DMA 可能メモリや、対象となる 32 ビットシステムでカーネルが常時マップしないメモリです。 アクセスレイテンシーは要求元 CPU とメモリバンクに依存するため、NUMA ノードはゾーン、空きリスト、統計、回収状態を所有します。
The buddy allocator supplies physically contiguous page blocks. Order zero is
one base page; order n is 2^n contiguous pages. SLAB-family allocators,
commonly SLUB, obtain pages from the buddy allocator and divide them into caches
of fixed-size kernel objects.
kmalloc() returns physically contiguous kernel memory for sizes supported by
the allocator. vmalloc() constructs a virtually contiguous kernel range from
noncontiguous physical pages, so it has different allocation cost and device-DMA
properties. Driver and DMA APIs should be selected by the device’s addressing
requirements rather than substituting one for the other.
回収、ライトバック、スワップ、OOM #
物理メモリの圧力によって回収が発生します。カーネルは次を実行できます。
- クリーンなページキャッシュページを破棄する。
- ダーティなファイルページを書き戻してから破棄する。
- スワップが利用できる場合、対象の匿名ページをスワップする。
- ファイルシステムメタデータなど回収可能なキャッシュに対して shrinker を呼び出す。
Each zone has watermarks. Crossing the low watermark wakes kswapd for
background reclaim. An allocation under more severe pressure can enter direct
reclaim and block until enough pages are available. Reclaim policy and
multi-generational LRU availability are kernel-configuration and release
dependent; inspect the target kernel rather than assuming an LRU implementation.
Pinned pages, many kernel allocations, unreclaimable device buffers, and pages
protected by policy reduce reclaimable capacity. Fragmentation can also prevent
a higher-order allocation despite ample free memory. Compaction migrates movable
pages to form a contiguous free block; kcompactd can run it in the background,
and an allocating task can compact synchronously. THP and DMA are common
consumers of such blocks.
When reclaim and compaction cannot satisfy an allocation, the kernel applies an
out-of-memory policy. OOM handling may be global, scoped to a memory cgroup, or
constrained by the failing allocation context. An OOM kill is a recovery path,
not evidence that the selected process is the original source of memory growth.
Investigate cgroup limits, memory pressure, allocation patterns, and pinned
memory before changing oom_score_adj.
メモリ動作の観測 #
各インターフェースは異なる層を報告するため、複数を組み合わせて使います。
cat /proc/meminfo
cat /proc/vmstat
cat /proc/pressure/memory
cat /proc/$$/maps
cat /proc/$$/smaps_rollup
cat /proc/$$/numa_maps
vmstat 1/proc/PID/maps は VMA を一覧表示します。smaps は VMA ごとの RSS、proportional set size、
匿名、ファイル、スワップ、ページサイズの計上を追加し、smaps_rollup はそれを集約します。
numa_maps は局所性とポリシーを示します。
/proc/PID/pagemap is restricted because physical-mapping information can
weaken security boundaries.
For fault rates, process accounting exposes ru_minflt and ru_majflt through
getrusage(2), while /proc/PID/stat includes per-process minor and major
fault counters. /proc/vmstat provides system-wide pgfault and pgmajfault
counters. Interpret deltas over an interval with latency and I/O metrics:
major-fault counts identify fault paths that needed I/O, but do not independently
prove the storage device caused an application’s latency.
/proc/pressure/memory の pressure stall information(PSI)は、メモリ圧力によってタスクが停止していた時間を報告します。
PSI を vmstat、cgroup の memory.events、アプリケーションレイテンシーと組み合わせ、
無害なキャッシュ入れ替えと継続的な回収または cgroup 制限圧力を区別します。
カーネルの動作と調整可能項目は変化します。主な参照先は Linux の
memory-management index, its
concepts overview, and
the target release’s source under
mm/.
コメント
GitHub で閲覧・コメントする(投稿にはログインが必要です)