aboutsummaryrefslogtreecommitdiff
path: root/ja/handbook/vm.sgml
blob: 76f9207a8f14f29662f13dd67e8e4b6d9cc061cf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
<!-- $Id: vm.sgml,v 1.1 1999-03-01 16:12:18 motoyuki Exp $ -->
<!-- The FreeBSD Documentation Project -->
<!-- The FreeBSD Japanese Documentation Project -->
<!-- Original revision: 1.2 -->

<sect><heading>FreeBSD VM システム<label id="vm"></heading>

<p><em>原作: &a.dillon;.<newline>
  6 Feb 1999.</em>

<em>FreeBSD における VM の内部構造詳説</em>

<sect1><heading>物理メモリ管理 - vm_page_t</heading>

	<p>
	物理メモリはページ単位に, 
	<em>vm_page_t</em>構造体を用いて管理されます. 
	物理メモリのページは, ページキューの一つに存在する, 
	それぞれの vm_page_t 構造体の配置によって分類されます. 
	<p>
	ページは, wired(ワイヤード), active(活性状態), 
	inactive(非活性状態), cache(キャッシュ状態), free(使われていない状態)の
	各状態をとります. wired 状態を除いて, ページは通常
	その状態を示す二重連結リストのキューに置かれます. 
	wired 状態のページがキューに置かれることはありません. 
	<p>
	FreeBSD は, ページカラーリング(page coloring)を実装するため, 
	cache 状態, free 状態にあるページ用に, 
	さらに複雑なページキューを実装しています. その各々の状態は, 
	プロセッサの L1, L2 キャッシュサイズに応じて最適化された
	多重キューを利用します. 
	FreeBSD	は, 新たなページを確保(allocate)することが
	必要になった場合に確保される VM オブジェクトのために, 
	L1, L2 キャッシュに対して合理的にアライン(align)されたページを
	得ようと試みます. 
	<p>
	加えて, ページは参照カウントとともに保持され, 
	ビジーカウントとともにロックされます. 
	VM システムは, ページフラグとして
	PG_BUSY を使う「完全ロック状態」も実装しています. 
	<p>
	一般的には, 各々のページキューは最長不使用 (LRU) 方式で動作します. 
	ページは普通, 最初に wired, もしくは active 状態に置かれます. 
	wired 状態の場合, そのページはどこかにあるページテーブルに
	関連づけられています. 
	VM システムはアクティブなキュー内のページをスキャンし, 
	wired 状態のページにエイジング(訳注: ページ参照頻度を量る手法の一つ;
	aging)を施します。そして, そのページはあまりアクティブでないキューへ
	移動することになります. 
	cache キューに移動させられたページは, 再利用の候補になっている
	VM オブジェクトに割り付けられています. 
	free キューにあるページは, 完全に自由の状態にあります. 
	FreeBSD は, free キューにあるページ数を最小限にとどめようと
	試みますが, 割り込み発生時のページ確保を融通するため, 
	完全に自由なページをいくつか持っていなければなりません. 
	<p>
	プロセスがページテーブルに存在しない, 
	ページキューの一つ(例えば, inactive, cache キュー等)に
	存在するページをアクセスしようとしたとき, 
	比較的負荷の小さなページ再活性化フォールトが起こります. 
	システムメモリに全く存在していないページの場合は, 
	ディスクからページを読み出す間, そのプロセスはブロック(block)されます. 
	<p>
	FreeBSD は, ページキューを動的に調節し, 
	同期済(clean)のページ, 同期していない(dirty)ページの分類を
	合理的に保つのと同様に, それぞれのキューにあるページが合理的な
	比率に保つように試みます. 
	再バランス化処理が起こる量は, システムのメモリ負荷に依存します. 
	この再バランス化処理はページアウトデーモンによって実装されていて, 
	(補助記憶とページを同期して)同期していないページの
	クリーニングすることや, (LRU キュー内でのページ位置を再配置したり, 
	ページをキューの間を移動することで)ページが頻繁に
	参照状態にあることに注目すること, キューを均等にするための
	キュー間ページ移動等を伴います. 
	ページが実際にどれだけ使われているかを決定するために, 
	FreeBSD の VM システムは, ページの再活性化フォールトを
	自発的に, 合理的な数だけ発生します. 
	これは, ページをスワップアウトしたり, クリーニングする時期を
	より良く決めることに繋がります. 

<sect1><heading>統合バッファキャッシュ - vm_object_t</heading>

	<p>
	FreeBSD は, 一般化した「VM オブジェクト」という考え方を実装しています.
	VM オブジェクトは, 様々な種類の補助記憶(backing store) - 補助記憶なし, 
	スワップ, 物理デバイス, ファイル, に割り付けられます. 
	ファイルシステムはファイルと関連するインコアデータを管理するのに, 
	同じ VM オブジェクトを利用するため, 統合バッファキャッシュと呼ばれます. 
	<p>
	VM オブジェクトは, <em>シャドウ化</em>することができます. 
	シャドウ化とは, オブジェクトがそれぞれ互いの上に
	スタック(stack)されるということです. 例えば, MAP_PRIVATE mmap() の
	動作を実装するために, 
	ファイルに割り付けられた VM オブジェクトの上にスタックされた, 
	スワップに割り付けられた VM オブジェクトが存在しているでしょう. 
	このスタッキングは, fork されたアドレス空間のための
	様々な共有属性, コピーオンライト(訳注: ページ共有のための
	手法の一つ; cow,copy-on-write)を実装するのにも利用されています. 
	<p>
	vm_page_t は, 同時に一つの VM オブジェクトしか割り付けられることが
	できないことに注意しなければなりません. 
	VM オブジェクトのシャドウ化は, 複数のインスタンスが同じページに
	共有できるように実装されています. 

<sect1><heading>ファイルシステム I/O - struct buf</heading>

	<p>
	補助記憶にファイルを使う VM オブジェクトのように, 
	v ノードを使う VM オブジェクトは通常, 
	処理されているかどうかという情報を, 
	VMシステムが管理する処理情報から独立して管理される必要があります. 
	例えば, VM システムが物理ページと補助記憶を同期させようとしたとき, 
	VM システムは, 実際に書き戻す前に, 
	ページがクリーニング済であるというマークを付ける必要があるわけです. 
	さらに, ファイルシステムは, KVM 内で操作できるように, 
	ファイルや, ファイルメタデータの一部分を KVM にマッピングすることが
	できなくてはなりません. 
	<p>
	これを管理するために使われる実体は, ファイルシステムバッファ, 
	<em>struct buf</em>, <em>bp</em> として知られています. 
	ファイルシステムに VM オブジェクトの一部を操作することが
	必要となるときは通常, オブジェクトの部分が struct buf に
	マッピングされ, KVM に struct buf 内のページがマッピングされます. 
	同じ方法で, ディスク I/O はオブジェクトの部分を
	バッファ構造体内にマッピングし, その時バッファ構造体上の I/O を
	発行することで発行されます. 基礎となっている vm_page_t は,
	I/O 処理の間 ビジー(busy)状態になります. ファイルシステムにも
	独立したビジー状態があり, それはハードウェア上の VM ページの代わりに
	ファイルシステムバッファで動作するファイルシステムドライバのコードに
	とって有用です. 
	<p>
	FreeBSD は, マッピングを保持するためにある量に制限された KVM を
	予約していますが, KVM がマッピングを保持するためだけに使われ, 
	キャッシュデータの能力を制限しないということは
	明確にされるべきでしょう. 
	物理データキャッシュを行うことは厳密に vm_page_t の機能になっており, 
	ファイルシステムバッファの機能ではありません. 
	しかし, ファイルシステムバッファは placehold I/O に使われるため, 
	それは実質的に同時処理可能な I/O 処理量を制限します. 
	通常は二, 三千のファイルバッファが利用可能ですから, 
	このことは問題にならないでしょう. 

<sect1><heading>マッピングページテーブル - vm_map_t, vm_entry_t</heading>

	<p>
	FreeBSD は, 物理ページテーブルの形態を VM システムと分離しています. 
	ハードウェア上にある全てのプロセス毎のページテーブルは, 
	その場その場で再構成され, 通常, 使い捨てだとみなされています. 
	KVM を管理するような特殊なページテーブルは, 最初に永続的な確保が
	行われ, これらのページテーブルが破棄されることはありません. 
	<p>
	FreeBSD は, vm_objects の部分を, 仮想メモリのアドレス範囲に
	vm_map_t と vm_entry_t 構造体を通して割り付けます. 
	ページテーブルは, vm_map_t/vm_entry_t/vm_object_t という階層から
	直接つくられます. 「物理ページは, 直接一つの vm_object に
	割り付けられる」と私が述べたことを思い出して下さい.
	ええと, そうですね, しかしそれはいつでも完全に当てはまる,
	というわけでもないのです. vm_page_t のは, 実際に割り付けられた
	ページテーブルにもリンクされています. 一つの vm_page_t は
	ページテーブルが呼ばれた時, いくつかの <em>pmaps</em> と
	リンクされることがあります. しかし, そのような階層的な割り付けは, 
	同じ vm_page_t を参照するオブジェクト内の, 
	同じページへの参照全てを保持しているため, 
	その結果, 常にバッファキャッシュの統合を得ることができるわけです. 

<sect1><heading>KVM メモリマッピング</heading>

	<p>
	FreeBSD は, 様々なカーネル構造体を保持するため, KVM を利用します. 
	ファイルシステムバッファキャッシュは, KVM 内で最も大きなものです. 
	それはつまり, struct buf の実体に対するマッピングに他なりません.  
	<p>
	Linux と異なり, FreeBSD は全ての物理メモリを KVM にマッピングしません. 
	これは, FreeBSD が 32 ビットプラットフォームで 4G バイトまでの
	メモリを扱える, ということを意味します. 
	実際, MMU がそれを可能にしているならば, 
	理論上, FreeBSD は 32 ビットプラットフォームで
	8TB までのメモリを扱うことができることになります. 
	しかし, 大部分の 32 ビットプラットフォームは 4G バイトの RAM しか
	マッピングできないようになっている, ということには議論の余地があるでしょう. 
	<p>
	KVM は, いくつかのメカニズムによって管理されています. 
	中心となっているのは, <em>ゾーンアロケータ(zone allocator)<\em>です. 
	ゾーンアロケータは, 特定の構造体型を確保するために
	KVM の部分(chunk)を得て, 一定の大きさのメモリブロックに分割します. 
	<tt>vmstat -m</tt> コマンドで, ゾーンによって
	分割された, 現在の KVM 利用状況一覧を得ることができます. 

<sect1><heading>FreeBSD VM システムのチューニング</heading>
	<p>
	FreeBSD カーネルでは, 動的に自分自身をチューニングするために, 
	協調的な努力が行なわれています. 
	普通は, 'maxusers' と 'NMBCLUSTERS' という
	カーネルオプション, つまり, /usr/src/sys/i386/conf/XXX で
	指定されるもの以外, いじくる必要はありません. 
	可能なカーネルオプションの一覧は, /usr/src/sys/i386/conf/LINT に
	記載されています. 
	<p>
	大きなシステムに対しては, 'maxusers' を増やしたいと思うかも知れませんね. 
	この値は普通, 10 から 256 の間の値にします. 
	<p>
	もし, システムが負荷の高いネットワーク用途に使われるなら, 
	NMBCLUSTERS を増やしたいと望むことでしょう. 
	この値は普通, 1024 から 4096 の間です. 
	各クラスタは, 16KB 程度ですので, 度を過ぎることのないようにして下さい. 
	<p>
	NBUF パラメータも, 伝統的にシステムの規模を決めるのに使われます. 
	これは, システムがファイルシステムバッファを I/O のために
	マッピングするのに使われる, KVA の大きさを決めるのに使われます. 	
	このパラメータは, 統合バッファキャッシュには何の影響も与えません. 
	これは -3.x 以降のカーネルでは動的にチューニングされるため, 
	普通は手作業で調整されるべきものではありません. 
	NBUF パラメータは, 指定しようとしないことを推奨します. 
	システムに選択させれば良いのです. 
	小さすぎる値は極端に非効率的なファイルシステム動作を招き, 
	一方で, 大きすぎる値は wired 状態のページを数多くつくりだし, 
	ページキューを枯渇させてしまうでしょう. 
	<p>
	デフォルトでは, FreeBSD カーネルは最適化されていません. 
	カーネルコンフィグにある 'makeoption' ディレクティブを使って
	最適化とデバッグフラグをセットすることができます. 
	ただし, それによって得られる大きな(7MB 超の)カーネルを相手にするのが嫌なら, 
	-g オプションは使ってはいけません. 
	<p><tt>makeoptions    DEBUG="-g"</tt>
	<p><tt>makeoptions     COPTFLAGS="-O2 -pipe"</tt>
	<p>
	sysctl は, 実行時にカーネルパラメータをチューニングする手段を提供しています. 
	しかし, 普通は sysctl 変数, 特に VM に関連したものをいじくる必要が
	生じるようなことはありません. 
	<p>
	実行時の VM とシステムのチューニングは, 比較的単純です. 
	まず, 可能ならば UFS/FFS ファイルシステムで softupdates を使いましょう. 
	/usr/src/contrib/sys/softupdates/README のファイルに, 
	設定方法に関する手順(と制限)について書かれています. 
	<p>
	次に, 十分なスワップを設定します. '作業'ディスクを含む
	各物理ディスク装置毎に一つずつ(最大四つまで)のスワップパーティションを
	設定すべきです. 少なくとも, メインメモリの 2 倍の
	スワップ空間が望ましく, メモリがあまりない場合には,
	おそらくそれより多く必要になります. 
	また, スワップパーティションのサイズは, 
	後でパーティションをつくり直しする必要がないように
	マシンに設定したいメモリ設定の最大値を基準に決めるべきでしょう. 	
	もし, クラッシュダンプをとりたい場合, 
	スワップパーティションは最低限メインメモリと同じの大きさで,
	/var/crash にはダンプを保持するのに十分な
	空きがなければなければなりません. 
	<p>
	NFS 経由のスワップは, -4.x 以降のシステムで完全に動作しますが, 
	NFS サーバ側では, ページングがその負荷の主な原因になることに
	注意しなければなりません. 

<em>Contributed by &a.dillon;.<newline>
  6 Feb 1999.</em>