このページの目次
プロセスのメモリレイアウト
カバー範囲: /proc/pid/maps の読み方 → stack/heap/mmap/vDSO/vvar/vsyscall → セグメント (text/data/bss) → メモリレイアウトと ASLR → mmap のマッピングタイプ 対象: Linux x86-64/ARM64 ユーザーランド
概要
Linux の各プロセスは、48ビット(または57ビット)の仮想アドレス空間を認識しています。この空間のレイアウトを理解することは、メモリ境界違反のデバッグ、core dump の解析、メモリ使用量の最適化にとって極めて重要です。/proc/pid/maps は、このレイアウトの「地図」となります。
典型的な 64-bit レイアウト
/proc/pid/maps の詳細解説
# 形式: アドレス 権限 オフセット デバイス inode パス名
# === バイナリ (PIE) ===
# === ヒープ ===
# === 共有ライブラリ ===
# === スレッドスタック (匿名 mmap) ===
# === スタック ===
権限ビットの解釈
r--p: 読み取り専用, プライベート ← .rodata, 読み取り専用セグメント
r-xp: 読み取り+実行, プライベート ← .text
rw-p: 読み取り+書き込み, プライベート ← .data, .bss, ヒープ, スタック
r--s: 読み取り専用, 共有 ← ほとんど使用されない
rw-s: 読み取り+書き込み, 共有 ← MAP_SHARED マッピング
---p: アクセス不可, プライベート ← ガードページ (スタック/ヒープ用)
匿名マップ vs ファイルマップ
[heap], [stack], [vdso]: 匿名マップ (ファイル名なし, カーネルが作成)
/lib64/libc.so.6: ファイルマップ (ファイル名あり, ファイルからの mmap)
7f1233e00000 (名前なし): 匿名マップ (malloc, スレッドスタック)
→ [heap] ではない! malloc は mmap を使用
各領域の詳細
Stack: スタックの自動成長
// スタックは mmap または brk で割り当てられる (カーネル設定による)
// VM_GROWSDOWN: push 操作で現在のスタック底を超えると → ページフォルト → カーネルが自動的にスタックを拡張
// → 拡張は RLIMIT_STACK (デフォルト 8MB) に制限される
// → スタックトップの下方にはガードページ (---p) があり、境界違反を防ぐ
// メインスレッドスタック: [stack] に位置する
// サブスレッドスタック: pthread_create → mmap (通常 8MB, mmap 領域内に位置)
Heap: brk vs mmap
// 従来の brk/sbrk: データセグメントを拡張 (.bss の直後)
// → ユーザーランド: brk(addr) → プログラムブレークを変更
// → 問題: 断片化, 個別に解放できない
// malloc の現在の戦略:
// 1. 小規模割り当て (< 128KB デフォルト): brk を使用 → [heap] 領域に配置
// 2. 大規模割り当て (>= 128KB): mmap を使用 → 独立した匿名マップ
// 3. mmap しきい値: mallopt(M_MMAP_THRESHOLD) で調整可能
vDSO / vvar / vsyscall: カーネルによる注入
[vdso]: 各プロセスのアドレス空間に注入される .so
提供: __vdso_clock_gettime, __vdso_getcpu, __vdso_time, __vdso_getrandom
→ ユーザーランドで実行, システムコール不要 → 極めて高速
[vvar]: vDSO のデータページ (カーネル timekeeper 構造体, CPU 固有データ)
→ ユーザーランド向けに読み取り専用 (R/O)
[vsyscall]: 廃止された高速システムコールページ (x86 のみ)
→ 固定アドレス: 0xffffffffff600000 (セキュリティリスク)
→ 現在はデフォルトでエミュレート (ページフォルト → カーネルがシミュレート → 返却)
ツール
# プロセスのメモリレイアウト
|
# メモリマップの要約
# メモリ使用量の概要
|
# VmPeak: 歴史的な最大仮想メモリ
# VmSize: 現在の仮想メモリ
# VmRSS: 物理メモリ (Resident)
# VmData/VmStk/VmExe/VmLib: データ/スタック/コード/ライブラリ
# ASLR の設定
参考
- カーネルドキュメント:
Documentation/filesystems/proc.rst(maps/smaps) - ソースコード:
fs/proc/task_mmu.c(/proc/pid/maps の実装),arch/x86/entry/vdso/ - LWN: "The vDSO and vvar", "ASLR for 64-bit Linux"
キーワード: /proc/pid/maps, stack, heap, vDSO, vvar, ASLR, PIE, smaps, brk, mmap