Linuxでは、プロセスがシステムに(仮想)メモリを要求すると、vma(プロセスの仮想メモリの記述子)に登録されますが、すべての仮想の物理ページは呼び出し時に予約されません。後で、プロセスがこのページにアクセスすると、エラーが発生し(アクセスによりページフォールト割り込みが生成されます)、PF#ハンドラーが物理ページを割り当て、プロセスページテーブルを更新します。
2つのケースがあります。読み取りが書き込み保護されているゼロページ(特別なグローバル事前ゼロ化ページ)へのリンクに変わる可能性がある場合の障害。書き込みの失敗(ゼロページと、必要なだけでまだ物理的にマップされていないページの両方)は、実際のプライベート物理ページの割り当てになります。
mmap(および内部的にmmapでもあるbrk / sbrk)の場合、このメソッドはページごとです。すべてのmmapされた領域は、全体としてvmaに登録されます(開始アドレスと終了アドレスがあります)。ただし、スタックには開始アドレスしかないため、他の方法で処理されます(通常のプラットフォームでは高いアドレス、低いアドレスに成長します)。
質問は:
スタックの近くにある新しい未割り当てメモリにアクセスすると、PF#を取得して大きくなります。スタックの隣のページではなく、スタックから10ページまたは100ページ離れているページにアクセスした場合、この成長はどのように処理されますか?
例えば
int main() {
int *a = alloca(100); /* some useful data */
int *b = alloca(50*4096); /* skip 49 pages */
int *c = alloca(100);
a[0]=1;
/* no accesses to b - this is untouched hole of 49 pages */
c[0]=1;
}
このプログラムは、スタックに割り当てられた2つまたは50のプライベート物理ページを取得しますか?
カーネルに単一のページフォールトに数十の物理ページを割り当ててから、ページごとに数十のページフォールトを割り当てるように依頼することは有益だと思います(1つの割り込み+1つのコンテキストスイッチ+Nのページ割り当て要求に対する単純でキャッシュフレンドリーなループとNの割り込み+ N個のコンテキストスイッチ+N個のページ割り当て(mmコードがIcacheから削除される可能性がある場合)。