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

Source: Internet
Author: User
Tags extend

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

There is no need to do so. The execution stream also calls other functions or calls a again, and frequently recycles the stack loss performance;

Negative arguments

Difficult or impossible to do. 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 deal with disputes in the address space area of the stack

The stack will continue to expand to the address of the exception b,b may be a readonly address or a protection hole, in the case of the downward expansion of the stack, if the address B on the upper side, will cause the stack space is 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 a pat on the head

Mmap or BRK, compare the top of the stack with the ESP register, if less than the recovery (equals is normal, greater than is not possible).

Linux Real-world practices

Linux does not determine what the 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 can be expanded, and has permissions, it is accessible, the kernel is whether the VMA belongs to the stack or heap or something, Specifically controlled by the application itself, that is, you can write a piece of code, the address space in all the writable areas of the full zero, it is entirely possible that buffer overflow may be a deliberate destruction, but the programmer accidental errors 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//  Please note that the stack size limit is removed with ulimit, which makes it easier 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 Stack/fixmap vma,     //  is either in the free, and lonely, 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&NBSP;ARGC,&NBSP;CHAR&NBSP;**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 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, apparently, If you carefully analyze the/proc/xx/maps file during GetChar and     //  get those magic number, the mmap below 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 ();         //  releases it when it succeeds, and the address space 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 call the same as beforeMmap for Fixmap, since the call to call,stack    //  space has been extended to this fixmap fixaddress, unfortunately, succeeded, however it will stack  vma    //  cut a knife into two segments. 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 stack at the  same address\n ");     getchar ();    //  here more ruthless! Part unmap the top of the FIXMAP&NBSP;VMA, leaving an empty hole.     munmap (p_map, pagesize);     priNTF ("after unmap fixmap around stack incompletely\n");     getchar ();    //  does not cause stack extend! when the hole is being touch But direct segfault!. Explosion!     call ();    //  will never get here!     printf ("after extend stack[second]\n");     getchar ();     return 0;}


Plots for the above code

The following illustration shows how the address space mapping area near the stack of the process evolves until the accident:


650) this.width=650; "src=" http://s3.51cto.com/wyfs02/M02/6E/56/wKioL1V5kJbh9XAPAAPZJ0eyaDM117.jpg "title=" 1.jpg " alt= "Wkiol1v5kjbh9xapaapzj0eyadm117.jpg"/>


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


650) this.width=650; "src=" http://s3.51cto.com/wyfs02/M02/6E/56/wKioL1V5kH7zuAAJAAJ0F6nd3H8313.jpg "title=" 2.jpg " alt= "Wkiol1v5kh7zuaajaaj0f6nd3h8313.jpg"/>


Test method

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 am not by looking 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, convert it to 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:


650) this.width=650; "src=" http://s3.51cto.com/wyfs02/M00/6E/5A/wKiom1V5jr3ACZqbAAUKk3j55lQ041.jpg "title=" 3.jpg " alt= "Wkiom1v5jr3aczqbaaukk3j55lq041.jpg"/>


What's the use?

You can completely limit the stack size of a process 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 dynamically allocated, 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 that the page fault handling program is how to identify a missing pages is a VMA internal 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 this 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.