正確なメカニズムは、Linuxでここに示されています。匿名マッピングでのページフォールトの処理では、スタックのように拡張する必要があるのが「成長した割り当て」であるかどうかを確認します。VM領域レコードに必要があると表示されている場合は、開始アドレスを調整してスタックを拡張します。
ページフォールトが発生すると、アドレスに応じて、スタック拡張を介してサービスが提供されます(およびフォールトが打ち消されます)。仮想メモリのこの「フォールトで下向きに成長する」動作はMAP_GROWSDOWN
、mmap
syscall に渡されるフラグを使用して、任意のユーザープログラムで要求できます。
ユーザープログラムでもこのメカニズムをいじることができます:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
int main() {
long page_size = sysconf(_SC_PAGE_SIZE);
void *mem = mmap(NULL, page_size, PROT_READ|PROT_WRITE, MAP_GROWSDOWN|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
if (MAP_FAILED == mem) {
perror("failed to create growsdown mapping");
return EXIT_FAILURE;
}
volatile char *tos = (char *) mem + page_size;
int i;
for (i = 1; i < 10 * page_size; ++i)
tos[-i] = 42;
fprintf(stderr, "inspect mappping for originally page-sized %p in /proc... press any key to continue...\n", mem);
(void) getchar();
if (munmap(mem, page_size))
perror("failed munmap");
return EXIT_SUCCESS;
}
プロンプトが表示されたら、プログラムのPIDを見つけ(を介してps
)/proc/$THAT_PID/maps
、元の領域がどのように成長したかを確認します。
ulimit -s
)に制限されています。