Точний механізм наведено тут, в Linux: обробляючи помилку сторінки на анонімних відображеннях, ви перевіряєте, чи це "виділення зросло", яке слід розширювати як стек. Якщо запис VM області каже, що слід, то ви налаштовуєте стартову адресу, щоб розширити стек.
Якщо виникає помилка сторінки, залежно від адреси, вона може обслуговуватися (а помилка скасовується) за допомогою розширення стека. Таку поведінку віртуальної пам’яті «зростаючий вниз» у вікні може запитувати довільні користувацькі програми, при цьому MAP_GROWSDOWN
прапор передається до mmap
системного виклику.
З цим механізмом можна повозитися і в користувацькій програмі:
#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;
}
Коли буде запропоновано, ви знайдете під програми (via ps
) і подивіться, /proc/$THAT_PID/maps
як зросла початкова область.
ulimit -s
).