Linux で C/C++ の足固め: Linux の メモリー/ファイル/mmap と C++ アロケーター


序文
1. Linux カーネルを学ぶ意義
2. C++ カスタムアロケーターを作る意義
1. 対象となる読者
2. 前提知識
3. 開発環境
3.1. Linux カーネルのバージョンを揃える
3.2. 本書の貢献者リスト
I. Linux と POSIX C
4. パイプとリダイレクトのまとめ
5. echo コマンド
6. シェルの確認
7. /dev ディレクトリー
7.1. echo のリダイレクト
8. アペンド
9. リダイレクトのファイル記述子
10. ファイル記述子間のリダイレクト
11. ファイル記述子リダイレクトのまとめ
12. exec (bash)
13. ファイル記述子を閉じる
14. 読み書きファイル記述子
15. /proc ディレクトリー
16. /dev/shm ディレクトリー
II. Linux (POSIX) のファイル入出力
17. system 関数
18. fprintf 関数
19. open / dprintf 関数
20. read() / write() 関数
20.1. 文字列をヒープにコピー
21. lseek()
22. fopen / fread / fwrite / fclose 関数
III. Linux でメモリー割り当て
23. 32 ビットプロセスのレイアウト
24. malloc (cstdlib)
25. malloc を strace で検証してみる
25.1. ASLR と共有オブジェクト
26. MALLOC(3) Linux プログラマーマニュアル
27. brk / sbrk (unistd.h)
27.1. gdb で sbrk() の解析
27.2. strace によって brk() / malloc() のコールをチェック
IV. glibc から malloc() の基本構造を理解してみる
28. malloc() の内部実装
29. アリーナによるマルチスレッド対応
30. アリーナオブジェクト( main_arena / malloc_state )
31. ヒープのヘッダーオブジェクト( heap_info )
32. チャンク( malloc_chunk )
33. 最少チャンクサイズと最少割り当てサイズ
34. malloc_par
35. top チャンク
35.1. ビン
36. 未整理ビン / スモールビン / ラージビン
37. ビンのインデックスの計算
37.1. 32 ビットアーキテクチャのビン
37.2. 64 ビットアーキテクチャのビン
38. ビン・インデックスのまとめ
39. ビンのチャンク連結
40. ビンの初期化
41. 未整理チャンク( Unsorted Chunk )のマクロ
42. トップチャンク( Top Chunk )のマクロ
43. Binmap のマクロ
44. tcache
45. malloc() フリーチャンクの挙動
46. malloc.c の内部マクロ
46.1. チャンクを取り扱えるマクロ
47. ファーストビンの解放
48. malloc.c の内部関数
49. malloc() の実装
49.1. _int_malloc() 関数
50. free() の実装
51. calloc()
52. realloc()
53. alloca() 関数
53.1. alloca() の使用法
54. posix_memalign() / aligned_alloc()
54.1. glibc-2.7 の内部実装
54.2. アラインメントの仕組み
54.3. アラインメントの最少サイズ
54.4. 大きめのアラインメント
54.5. 複数のアラインメントでの検証
55. std::launder ( C++17 )
56. std::aligned_storage ( C++11 )
57. std::align ( C++11 )
58. std::aligned_alloc ( C++17 )
V. Linux カーネルのメモリーとファイルシステム
59. Linux の仮想メモリーエリア・メモリー記述子
60. メモリー記述子( mm_struct )
61. 仮想メモリー領域( vm_area_struct )
62. ページ記述子( struct page )
63. ページとブロック
64. バッファー ( buffer_head )
65. ブロック I/O ( bio )
66. ページのキャッシュ
67. スラブレイヤー・スラブアロケーター
68. ファイルとメモリーのマッピング (mmap)
69. ページとハードウェア
70. ページキャッシュ ( struct address_space )
71. Linux のファイルシステム
71.1. カーネルヘッダー ( /usr/src/ )
71.2. カーネルソースのアーカイブ
71.3. super_block (カーネル)
71.4. inode (カーネル)
71.5. dentry (カーネル)
71.6. file (カーネル)
72. stat 構造体
VI. mmap
73. mmap の使い方
74. マルチタスクで使えると共有メモリーオブジェクト
75. fork()
75.1. fork() を 2 回コールする
75.2. fork() を 3 回コールする
75.3. fork() を 4 回コールする
76. fstat 関数を使ってファイルサイズを指定する場合
77. MAP_PRIVATE の Copy-On-Write
77.1. fork() で MAP_PRIVATE の Copy-On-Write を検証
78. MAP_ANONYMOUS
79. アノニマスマッピング
80. fork() でプライベートファイルマッピングのチェック
81. fork() でプライベートアノニマスマッピングをチェック
82. fork() で共有ファイルマッピングをチェック
83. fork() で共有アノニマスマッピングをチェック
84. /dev/zero
VII. (汎用ではない)カスタムアロケーターの設計
85. アロケーターに必要な最低限の関数・オーバーロード・テンプレート
86. std::allocator を使うだけのリファレンスアロケーター
86.1. std::allocator を模したカスタムアロケーター
VIII. スマートポインターで使えるデリーター
87. スマートポインターで使えるようにするためのデリーター実装
IX. スタック領域に割り当てるアロケーター
88. 配列内のアドレスの走査
88.1. スタックアロケーター(可変長のリクエストサイズに対応、難易度高いのでスキップ推奨)
89. ヒープへのフォールバック付きスタックアロケーター
90. コードをシンプルにする(内部バッファーのアドレスかのチェック)
X. ヒープ領域のアドレスに割り当て
91. ヒープ領域のアドレス
92. malloc を使ってヒープに割り当て
93. カスタムヒープアロケーター
94. static オブジェクトはヒープっぽい領域に割り当てられるはず?
95. アロケーターをスタティックメンバーにするとどうなるのか?
XI. アロケーターをセレクターで切り替え
96. アロケータークラス内での複数の割り当て方針を切り替え
96.1. 複数のアロケーターインスタンスを切り替え
XII. C++ カスタムアロケーターの STL サポート(実験)
97. C++ カスタムスタックアロケーターの用語の復習
98. STL コンテナのサポート ( new / delete )
99. STL サポートの適用対象
100. STL コンテナ側のメモリー割り当て要件
101. sizeof を使った割り当てサイズの算出によるスタックアロケーター実装
XIII. mmap() を使ったカスタムアロケーター
102. ユーザーによるオブジェクト管理を前提にするカスタムページアロケーター
103. カスタムアロケーターによるブロック管理
XIV. (おまけ)アロケーターのポリモーフィズム
104. メモリーリソースクラス
105. std::experimental::pmr::memory_resource ( C++17 )
105.1. memory_resource でアラインメントの実装(非実用的な実験です)
106. ポリモーフィックアロケーター
107. std::pmr::polymorphic_allocator ( C++17 )
108. std::experimental::pmr::vector コンテナ ( C++17 )
109. std::pmr::polymorphic_allocator の動作チェック
109.1. ポリモーフィックアロケーターの実装

図の一覧

30.1. メインアリーナ(main_arena)
30.2. スレッドアリーナ
32.1. 割り当て済みチャンク(allocated chunk)
32.2. 割り当て済みチャンクの内部(allocated chunk)
32.3. フリーチャンク(free chunk)
32.4. フリーチャンクの内部(small free chunk、大きめでない場合)
39.1. Unsorted/Small/Large Bins
39.2. Large Bins
68.1. 一段ページテーブル構成
68.2. 二段ページテーブル構成
68.3. Linux 三段ページテーブル(Linux 2.6.11以前)

Copyright 2018-2019, by Masaki Komatsu