13

getrlimit(2) has the following definition in the man pages:

RLIMIT_AS The maximum size of the process's virtual memory (address space) in bytes. This limit affects calls to brk(2), mmap(2) and mremap(2), which fail with the error ENOMEM upon exceeding this limit. Also automatic stack expansion will fail (and generate a SIGSEGV that kills the process if no alternate stack has been made available via sigaltstack(2)). Since the value is a long, on machines with a 32-bit long either this limit is at most 2 GiB, or this resource is unlimited.

What is meant by "automatic stack expansion" here? Does the stack in a Linux/UNIX environment grow as needed? If yes, what's the exact mechanism?

2 Answers 2

8

The exact mechanism is given here, on Linux: in handling a page fault on anonymous mappings you check to see whether it's a "grown does allocation" that you should expand like a stack. If the VM area record says you should, then you adjust the start address to expand the stack.

When a page fault occurs, depending on the address, it may be serviced (and the fault quashed) via stack expansion. This "growing downwards on a fault" behavior for virtual memory can be requested by arbitrary user programs with the MAP_GROWSDOWN flag being passed to the mmap syscall.

You can mess around with this mechanism in a user program as well:

#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;
}

When it prompts you find the pid of the program (via ps) and look at /proc/$THAT_PID/maps to see how the original area has grown.

2
  • Is it ok to call munmap for the original mem and page_size even if the memory region has grown via MAP_GROWSDOWN? I presume yes, because otherwise it would be a very complex API to use, but the documentation does not say anything explicitly on this matter
    – i.petruk
    Apr 20, 2016 at 11:39
  • 3
    MAP_GROWSDOWN shouldn't be used, and has been removed from glibc (see lwn.net/Articles/294001 for why).
    – Talia
    Jan 25, 2017 at 2:26
1

Yes stacks grow dynamically. The stack is in the top of the memory growing downwards towards the heap.

--------------
| Stack      |
--------------
| Free memory|
--------------
| Heap       |
--------------
     .
     .

The heap grows upwards (whenever you do malloc) and the stack grows downwards as and when new functions are called. The heap is present just above the BSS section of the program. Which means the size of your program and the way it allcates memory in heap also affect the maximum stack size for that process. Usually the stack size is unlimited (till heap and stack areas meet and/or overwrite which will give a stack overflow and SIGSEGV :-)

This is only for the user processes, The kernel stack is fixed always (usually 8KB)

8
  • "Usually the stack size is unlimited", no, usually it limited by 8Mb (ulimit -s).
    – Eddy_Em
    Feb 5, 2013 at 6:57
  • yes you are right in most systems. You are checking the shell's ulimit command, if so there is a hard limit on the stack size, which is unlimited (ulimit -Hs). Anyway, that point was to stress that stack and heap grows in the opposite directions.
    – Santosh
    Feb 5, 2013 at 9:53
  • Then how is "automatic expansion" is any different from "pushing elements to the stack"? From your explanation, I get the feeling that they are the same. Also, I felt like starting points of stack and heap are way more than 8MB, so the stack can grow as much as it need (or it hits the heap). Is that true? If yes, how does the operating system decided on where to place the heap and the stack? Feb 5, 2013 at 15:21
  • They are the same, but stacks dont have a fixed size unless you hard limit the size using rlimit. Stack is placed at the end of the virtual memory area, and heap is immediatly af*er tke data segment of the executable.
    – Santosh
    Feb 5, 2013 at 21:57
  • I understand, thanks. However, I don't think I get the "stacks don't have fixed size" part. If that's the case, what's the 8Mb soft limit for? Feb 6, 2013 at 16:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .