问题
I have a few questions related to limitations on the stack size for Linux. I'm most interested in x86_64 systems, but if there are platform differences I'd like to understand them as well. My questions are:
1) How does Linux dynamically increase the size of the stack?
I've written a test program with a recursive function (to use stack space) where I can specify the number of iterations as a command line parameter. The program pauses waiting for user input after finishing the recursion, which allows me to get information about the running process. If I run with a small number of iterations and then use pmap
to view the stack size it is 132K.
00007fff0aa3c000 132K rw--- [ stack ]
Whereas if I run with a larger number of iterations the size can grow much larger, I believe up to 8192 KB by default. For example here's output from running with more iterations.
00007fff3ed75000 8040K rw--- [ stack ]
But if I use strace
to trace the system calls when running the application I don't see any associated with growing the stack. So I'm wondering what the kernel is doing to manage the stack space for a process.
2) Does Linux protect the stack region in any way when setting ulimit -s unlimited
?
If I use the command ulimit -s unlimited
then I'm able to run many more iterations of my recursive function and the stack grows much larger. For example here's output from pmap
00007ffda43a3000 8031260K rw--- [ stack ]
Since I don't want to cause my machine to crash/hang/lockup I haven't tested with infinite recursion yet. But I'm wondering if I did is there anything that would cause the kernel to detect stack overflow. Or is ulimit the only protection and turning that off allows the stack to grow unbounded?
3) How are stack guard pages handled?
This isn't directly related to anything I've experimented with, but I'm also wondering how Linux manages stack guard pages in conjunction with allowing the stack to grow dynamically.
回答1:
- For each running process, Linux keeps a list of regions of the virtual memory addresses. If an address reference generates a page fault, Linux checks that list to see if the virtual address is legal (within the range of one of the regions). If not claimed by a region, the application gets a SIGSEGV error, otherwise the kernel allocates another page of system memory and adds to the translation caches. if the faulting address just misses a region, and that region is for a stack (which grow up or down, according to the machine architecture) then Linux allocates another VM page, maps it into the region, thus growing the stack.
- The kernel does not protect the stack. If a stack access causes a page fault because a physical VM page is not attached to a memory region for the process, the process's rlimit is tested to see if adding another page is permitted.
- Stack guard pages are using by some malloc(3) debugger libraries. What these to is to expand each memory request by 2 VM pages: one page before the new page, one page after it. The extra pages are marked as no-access-at-all so if the application walks off the end of a region, or moves before the beginning, the application gets an access violation.
The above has been shamelessly over-simplified but still should give the gist.
来源:https://stackoverflow.com/questions/31328349/stack-memory-management-in-linux