Please try to answer a question about unix/linux automatic expansion stack

Source: Internet
Author: User

Have the ability to come out, do not have the ability to be a turtle!

If let me answer about the process stack, line stacks problem, as long as the problem is not general, as long as the problem is clear, I will lay it on to answer, the correct rate on 90%, however, sadly, the problem is often not so clear, so the game to this end!! 艹. But if you give me a chance to ask a question, I'll question the questioner, and remember to answer it with your poop:

The unix/linux stack is scaled down on most platforms (note that I've told him the truth and I didn't ask ...). How it is extended, which can be recited and read aloud), calls a function A in an execution stream, and the function a allocates a large array on the stack resulting in a stack extension (note that this is another statement, I have not given a problem), and a returns, unix/ Linux is supposed to recycle a large array allocation stack space on a--because it's no longer used, but it doesn't do it (this could be a trap, it's really what unix/linux should have done but not done, or I'm just teasing you ...). Not sure, but the statement is the case). (Note that my question comes up), excuse me, unix/linux Why do you do this??!!!
All answers such as those prescribed by the operating system are 0 points! Besides, can you prove that I'm right? What if I was teasing you? Can the operating system prescribe a wrong thing? Or I can continue to ask why so stipulated, until like my junior high school history teacher was I asked to the corner of my eye to punch like, if I can get back a bit of the so-called pleasure, then hit! The problem is this, whether it is a pseudo-proposition or you have your own ideas, can say 5 minutes, I think enough can be. The answer to this question is as follows:
Time limit: 5 minutes.
Answer: Full dictation, can't draw, can't gesture ... The language is ambiguous, the ability to express is not good, the calculation is wrong.
Advice: If you do not have a deep understanding of OS virtual memory management and Linux VMA implementation details, please do not guess the answer. Please answer "do not know" directly, then read this article.
.................................
5 minutes to go. I'd like to announce a little bit of my idea.
First of all, this problem seems to be problematic in itself. Because while Linux is supposed to do this, it:
first, it is not necessarily able to do;
Secondly, it is not necessary to do it at all.
So what is the argument? Why would you say that?
Positive arguments do not need to be done. The execution stream also calls other functions or calls a again, and frequently recycles the stack loss performance;
Negative arguments can be difficult or impossible. Stack operations are processor-controlled, and the OS kernel address space management mechanism has no synchronization mechanism, after a function call, the CPU automatically handles stack register contraction, pop-up stack frame, however it can not notify the OS memory management system to update the process address space mapping relationship.
How to handle the dispute of the address space area of the stack the stack will extend to the address where the exception is encountered B,b may be a readonly address or a protection hole, in the case of a downward expansion of the stack, if the address B on the upper side, will cause the stack space smaller, if lower, Once the function local variable is almost full of space of stack bottom to B, mmap can unmap the area and then remap, but this can confuse the data and cause serious problems.
The conclusion of the mmap or BRK period, compare the top of the stack with the ESP register, if less than the recovery (equals is normal, greater than is not possible).
Linux true Practice Linux does not determine what ESP register, the principle of Linux is very simple, as long as an address in a VMA range or in the scope of the stack extensible, and have access to, it is accessible, The kernel is whether the VMA is a stack or heap or something, specifically controlled by the application itself, that is, you can write a piece of code, all the areas of the address space can be written to zero, it is entirely possible that buffer overflow may be a deliberate destruction, However, the occasional mistakes of programmers can also cause damage, although most of them do not know how the error occurred. I don't want to use words to long-winded how Linux manages VMA, you know this should be a prerequisite, you have to know this. I use a piece of code and two illustrations to show how the Linux kernel manages the address space mappings near the stack, and in the second picture, it gives you a problem if you have to sabotage it. In other words, once a strange and strange mistake occurs, you must be able to understand the details of how the error occurred.
Demo Code
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include < sys/mman.h> #define LARGE 70000000#define PAGESIZE 4096//The function does nothing, just to extend the stack down//notice that the stack size limit is removed with Ulimit, which is more    Easy to explain the problem void call () {int i;    Char A[large]; Please believe that the segfault must be triggered in the middle of the assignment, because the elements on either side are in the Stack/fixmap VMA,//are either in the free and lonely, and are fixmap to the truncated VMA.    Therefore, the following assignment does not cause a segment error://a[0] = 1;    A[LARGE-1] = 1;    for (i = 0; i < LARGE; i++) {a[i] = 1;    }}int Main (int argc, char **argv) {int i;    Char *p_map, *p_base, *p_base2;    printf ("%d\ninit state\n", Getpid ());    Gets the approximate address of the stack and pagesize the alignment.    P_base = (char *) &i;    P_BASE2 = (char *) ((unsigned long) p_base) & ~4095);    Gets the address of the pagesize alignment used to Fixmap, which starts at the bottom of the current stack.    P_BASE2 = (char *) ((unsigned long) p_base2-(unsigned long) 36*pagesize);    GetChar ();    Call Fixmap, obviously, if you carefully analyze the/proc/xx/maps file during GetChar and//Get those magic number above, the following mmap will succeed anyway! P_map = (char *) mmap ((VOid*) P_base2, pagesize*3, Prot_read | Prot_write, map_fixed | Map_private |    Map_anonymous,-1, 0);    if (P_map = = map_failed) {printf ("FAILED 1\n");        } else {printf ("before Unmap fixmap around stack\n");        GetChar ();    If it succeeds, it is released, and the address space at this time reverts to the condition before Mmap munmap (P_map, pagesize*3);    } printf ("After unmap fixmap around stack\n");    GetChar ();    Call ();    printf ("After extend stack[first]\n");    GetChar (); Still called before the same mmap for Fixmap, because the call Call,stack//space has been extended to this fixmap fixaddress, unfortunately, succeeded, but it will stack VMA//A knife cut into two paragraphs.    However, access can still be done. P_map = (char *) mmap ((void*) P_base2, pagesize*3, Prot_read | Prot_write, map_fixed | Map_private |    Map_anonymous,-1, 0);    if (P_map = = map_failed) {printf ("FAILED 2\n");    } printf ("After second Fixmap around stacks at the same address\n");    GetChar (); It's more ruthless here!    Part unmap the above Fixmap VMA, leaving an empty hole.    Munmap (P_map, PAGESIZE); printf ("After unmap fixMap around Stack incompletely\n ");    GetChar (); When the hole is touch, it does not trigger the stack extend! But direct segfault!.    Explosion!    Call ();    Will never get here!    printf ("After extend stack[second]\n");    GetChar (); return 0;}

A diagram of the above code shows how the address space mapping area near the stack of the process evolves until the accident:




The following picture shows the process of the accident and the cause of the incident:




Test mode If you think the picture is my own drawing, then there must be a question, I am based on what to draw out, in fact, I do not look at the code to draw, I was constantly looking at the PROCFS maps file in real-time to understand the details of the process address space, to convert it into the above diagram, In order to give me a chance to go to the other terminal to check the maps file, I added the GetChar call in the code, each time I see the maps file, I will take a hit the keyboard enter. My test is as follows:
Code-compiled process output [email protected]:~#./a.out
7846
Init state

Before Unmap fixmap around stack

After Unmap fixmap around stack

After extend Stack[first]

After second Fixmap around stack at the same address

After Unmap fixmap around stack incompletely

Segment error (Core dumped)
The following is a look at the output of each step of the process maps file: [Email protected]:~# cat/proc/' ps-e|grep A.out|awk ' {print $} '/maps |tail-n 6|head-n 4
2b2c01483000-2b2c01487000 r--p 00157000 fe:00 387296/lib/libc-2.11.2.so
2b2c01487000-2b2c01488000 rw-p 0015b000 fe:00 387296/lib/libc-2.11.2.so
2b2c01488000-2b2c0148f000 Rw-p 00000000 00:00 0
7fff6236a000-7fff6237f000 Rw-p 00000000 00:00 0 [Stack]
[Email protected]:~# cat/proc/' ps-e|grep A.out|awk ' {print $} '/maps |tail-n 6|head-n 4
2b2c01487000-2b2c01488000 rw-p 0015b000 fe:00 387296/lib/libc-2.11.2.so
2b2c01488000-2b2c0148f000 Rw-p 00000000 00:00 0
7fff62359000-7fff6235c000 Rw-p 00000000 00:00 0
7fff6236a000-7fff6237f000 Rw-p 00000000 00:00 0 [Stack]
[Email protected]:~# cat/proc/' ps-e|grep A.out|awk ' {print $} '/maps |tail-n 6|head-n 4
2b2c01483000-2b2c01487000 r--p 00157000 fe:00 387296/lib/libc-2.11.2.so
2b2c01487000-2b2c01488000 rw-p 0015b000 fe:00 387296/lib/libc-2.11.2.so
2b2c01488000-2b2c0148f000 Rw-p 00000000 00:00 0
7fff6236a000-7fff6237f000 Rw-p 00000000 00:00 0 [Stack]
[Email protected]:~# cat/proc/' ps-e|grep A.out|awk ' {print $} '/maps |tail-n 6|head-n 4
2b2c01483000-2b2c01487000 r--p 00157000 fe:00 387296/lib/libc-2.11.2.so
2b2c01487000-2b2c01488000 rw-p 0015b000 fe:00 387296/lib/libc-2.11.2.so
2b2c01488000-2b2c0148f000 Rw-p 00000000 00:00 0
7fff5e0bb000-7fff6237f000 Rw-p 00000000 00:00 0 [Stack]
[Email protected]:~# cat/proc/' ps-e|grep A.out|awk ' {print $} '/maps |tail-n 6|head-n 4
2b2c01488000-2b2c0148f000 Rw-p 00000000 00:00 0
7fff5e0bb000-7fff62359000 Rw-p 00000000 00:00 0
7fff62359000-7fff6235c000 Rw-p 00000000 00:00 0
7fff6235d000-7fff6237f000 Rw-p 00000000 00:00 0 [Stack]
[Email protected]:~# cat/proc/' ps-e|grep A.out|awk ' {print $} '/maps |tail-n 6|head-n 4
2b2c01488000-2b2c0148f000 Rw-p 00000000 00:00 0
7fff5e0bb000-7fff62359000 Rw-p 00000000 00:00 0
7fff6235a000-7fff6235c000 Rw-p 00000000 00:00 0
7fff6235d000-7fff6237f000 Rw-p 00000000 00:00 0 [Stack]
I am afraid that the above text message is too messy, format in different browsers will have problems, I also deliberately cut a picture:




What's the use? You can completely limit the size of a process stack in this way, not error, but segfault. Then you can signal capture this segfault, in which the Fixmap VMA that is not fully unmap and the poor and lonely broken stack VMA is completely unmap. But it's really nothing fun. What's the use of it? Its role is to give you a deeper understanding of how Linux manages virtual address space.

Small tips This article does not involve line stacks, but it is not difficult, the thread stack is generally in the heap or in the middle of the large mmap area dynamic allocation, mmap time to give it a map_growsdown flag on it. There is no difference in the way it is managed. The core problem is how the fault handler for the pages is identified a page fault is a VMA inside the pages (the result is paging), or VMA external pages. In the latter case, the page fault processing logic further identifies the fault of the stack (the result is the extend stack then paging), or the non-stack pages (the result is segfault ...).
The Linux stack is always extended unless it encounters a run contraction in this way as described in this article. If you want to read Linux kernel code, you also need to understand the following facts:
1.find_vma function can find VMA only one limit, that is, the input address is less than the end of the lookup VMA, not many people think that the input address must be located in the search VMA between start and end;
The 2.FIND_VMA function is implemented so incompletely because it simplifies the processing of fault pages and also provides a more uniform way to handle VMA of upgrows and downgrows at the same time.

Something although the question is a bit messy, but if you can find the above answer 5 minutes in a row, it should be good! But I do not know how language expression ability can be used without illustrations and code to explain the above details of each ... In a word, I think this topic of mine is a good topic. Can suggest to see this article of person, put it to do face test bar. All can not find the problem of problems and can't say why, do not! This is really a good test, ah, it is so good, so that I would like to make a few more than it better.

Please try to answer a question about unix/linux automatic expansion stack

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.