Der genaue Mechanismus ist hier unter Linux angegeben: Wenn Sie einen Seitenfehler bei anonymen Zuordnungen behandeln , überprüfen Sie , ob es sich um eine "gewachsene Do-Zuweisung" handelt , die Sie wie einen Stapel erweitern sollten. Wenn der VM-Bereichsdatensatz angibt, dass Sie sollten, passen Sie die Startadresse an, um den Stapel zu erweitern.
Wenn ein Seitenfehler auftritt, kann er abhängig von der Adresse über die Stapelerweiterung behoben (und der Fehler gelöscht) werden. Dieses Verhalten für den virtuellen Speicher, das bei einem Fehler nach unten wächst, kann von beliebigen Benutzerprogrammen angefordert werden, wobei das MAP_GROWSDOWN
Flag an den mmap
Systemaufruf übergeben wird.
Mit diesem Mechanismus können Sie auch in einem Anwenderprogramm herumspielen:
#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;
}
Wenn Sie dazu aufgefordert werden, finden Sie die PID des Programms (über ps
) und sehen /proc/$THAT_PID/maps
, wie der ursprüngliche Bereich gewachsen ist.
ulimit -s
) begrenzt.