In Linux, when process asks for some (virtual) memory from system, it just registered in vma (descriptor of process's virtual memory) but physical page for every virtual is not reserved at time of call. Later, when process will access this page, it will be faulted (access will generate Page Fault interrupt), and PF# handler will allocate physical page and update process page table.
There are two cases: fault when reading may turn into link to zero page (special global pre-zeroed page) which is write-protected; and fault on writing (both on zero-page and on just-required-yet-not-physically mapped page) will result in actual private physical page allocation.
For mmaps (and brk/sbrk, which is internally mmap too) this method is per-page; all mmaped regions are registered as whole in vma (they have begin and end addresses). But stack is handled in other way, because it has only start address (higher one on typical platform; grow to lower addresses).
The question is:
When I access new unallocated memory near stack, it will get PF# and grow. How this growing handled, if I access not the page next to stack, but the page which is 10 or 100 pages away from stack?
E.g.
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;
}
Will this program get 2 or 50 private physical pages allocated for stack?
I think it can be profitable to ask kernel to allocate tens physical pages in single pagefault then do tens pagefaults allocating page by page (1 interrupt + 1 context-switch + simple, cache-friendly loop over N page-allocation requests versus N interrupts + N context-switches + N page allocations, when mm code may be evicted from Icache).
mlock(2)
will prefault too. – Danieldaniela