In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >
Share
Shulou(Shulou.com)06/02 Report--
Come out if you can, or be a turtle if you can't!
If you ask me to answer questions about process stack and thread stack, as long as the questions are not general, as long as the questions are clear, I will answer them one by one, with a correct rate of 90%. However, sadly, the questions are often not very fucking clear, so the game is over! Damn it. But if you give me a chance to ask, I will ask the following question, remember, use your strength to shit to answer (the question is rough enough! Don't take it too seriously, the important things are below -):
UNIX/Linux 's stack is extended downwards on most platforms (note that I've told him the truth, I didn't ask. How it is extended, which can be recited and read aloud), calls a function An in an execution flow, and that function An allocates a large array on stack resulting in the stack extension (note, this is another statement, I haven't given a question yet), and then A returns, and UNIX/Linux is supposed to recycle the large array in call A to allocate stack space-- because it's no longer used. But it didn't do it (it could be a trap, is it really UNIX / Linux that should have done this but didn't do it, or am I just teasing you? Not sure, but that's what the statement is. (attention, here comes my question), excuse me, why is UNIX/Linux doing this?
All answers such as those stipulated by the operating system will be zero! Besides, can you prove that I must be right? What if I'm messing with you? Can the operating system specify the wrong thing? Or I can continue to ask why, until my junior high school history teacher was asked to punch me in the corner of the eye, if I can get back some of the bitch's so-called pleasure, then do it! That's the problem. Whether it's a fake question or you have your own ideas, I think it's good enough to be able to talk for five minutes. The requirements for answering this question are as follows:
Time limit: 5 minutes.
Answer: full dictation, no drawing, no gestures. If the language is ambiguous and the expression ability is not good, it is a mistake.
Answer suggestion: if you don't have a good understanding of OS virtual memory management and the details of Linux's VMA implementation, please don't guess the answer. Please answer "I don't know" directly, and then finish reading this article.
..
Five minutes go by. I'm going to publish some of my thoughts.
First of all, from the point of view of itself, there is a problem. Because while Linux is supposed to do this, it:
First, it may not be able to do it.
Second, it is not necessary to do it at all.
So what's the argument? Why do you say that?
Positive argument
There's no need to do this. The execution flow will also call other functions or call An again, frequently reclaiming stack loss performance.
Negative argument
Difficult or impossible to do. The stack operation is controlled by the processor, and there is no synchronization mechanism between the OS kernel address space management mechanism. After the end of a function call, CPU automatically handles the contraction of the stack register and pops up the stack frame. However, it cannot inform the OS memory management system to update the mapping of the process address space.
How to deal with the dispute in the address space area where stack is located
Stack will expand until it encounters an abnormal address Bstack B may be an address of readonly or a protection hole, in the case of downward expansion of stack, if the address B is on the upper side, it will lead to a smaller stack space, if lower, once the function local variables almost fill the space from the bottom of stack to B, mmap can also unmap this area and then remap, but this will confuse the data and cause serious problems.
The conclusion of a pat on the head
During mmap or brk, compare the top of stack with the esp register, and if it is less than that, it will be recycled (equal to normal, greater than is impossible).
What Linux really does.
Linux does not judge what esp registers. The principle of Linux is very simple. As long as an address is within a vma range or stack expandable range and has permission, it can access the kernel, no matter whether the VMA belongs to stack or heap or whatever, it is controlled by the application itself. That is to say, you can write a piece of code. It is entirely possible to zero all writable areas in the address space. Buffer overflows can be a form of deliberate sabotage, but occasional errors by programmers can also cause destruction. although most of them don't know how the error happened. I don't want to talk at length about how Linux manages VMA, you know this should be a premise, you have to know this. I use a piece of code and two diagrams to show how the Linux kernel manages address space mapping near stack, and shows in the second figure what can happen if you have to sabotage it. In other words, once an inexplicable and wonderful error occurs, you must be able to understand in detail how it happened.
Demo code # include # define LARGE 70000000#define PAGESIZE 4096max / this function does nothing but extends stack downwards / / Please note that you use ulimit to remove the stack size limit, which will make it easier to explain the problem void call () {int i; char a [LARGE] / / believe that segfault must be triggered in the middle assignment, because the elements on both sides are either in stack/fixmap vma, / / or in a free, lonely, truncated vma by fixmap. So 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()); // 获取stack的大致地址,并且PAGESIZE对齐。 p_base = (char *)&i; p_base2 = (char *)(((unsigned long)p_base) & ~4095); // 获取pagesize对齐的用来fixmap的地址,该地址起点在当前stack的下面。 p_base2 = (char *)((unsigned long)p_base2 - (unsigned long)36*PAGESIZE); getchar(); // 调用fixmap,显然,如果你仔细在getchar期间分析了/proc/xx/maps文件并且 // 得到了上述的那些magic number,下面的mmap无论如何是会成功的! 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(); // 成功了就释放掉它,此时的地址空间恢复成mmap之前的状况 munmap(p_map, PAGESIZE*3); } printf("after unmap fixmap around stack\n"); getchar(); call(); printf("after extend stack[first]\n"); getchar(); // 依然调用之前的那个一模一样的mmap进行fixmap,由于调用了call,stack // 空间已经扩展到了这个fixmap的fixaddress,很遗憾,成功了,然而它将stack vma // 一刀切成了两段。不管怎样,访问还是可以进行的。 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(); // 这里更狠!部分unmap了上面那个fixmap vma,留下一个空洞。 munmap(p_map, PAGESIZE); printf("after unmap fixmap around stack incompletely\n"); getchar(); // 当空洞被touch的时候,不会引发stack extend!而是直接segfault!爆炸! call(); // 永远不会到达这里! printf("after extend stack[second]\n"); getchar(); return 0;} 针对上述代码的图解 下面一幅图展示一直到出事之前,该进程的stack附近的地址空间映射区域是怎么演化的:The following picture shows the process of the accident and the cause of the accident:
Test mode
If you think I drew the picture myself, then there must be a question: what did I draw it on? in fact, I didn't draw it by looking at the code. I learned the details of the process address space in real time by constantly looking at the maps file of procfs, and translated it into the diagram above. In order to give me a chance to check the maps file at another terminal, I added getchar call to the code. Every time I check the maps file, I clap the enter key of the keyboard. My tests are as follows:
Process output after code compilation
Root@abcd:~#. / 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)
Here is the output of the maps file for each process:
Root@abcd:~# cat / proc/ `ps-e | grep a.out | awk'{print $1}'`/ maps | tail-n 6 | head-n 4
2b2c01483000-2b2c01487000 Rmurmurp 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]
Root@abcd:~# cat / proc/ `ps-e | grep a.out | awk'{print $1}'`/ 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]
Root@abcd:~# cat / proc/ `ps-e | grep a.out | awk'{print $1}'`/ maps | tail-n 6 | head-n 4
2b2c01483000-2b2c01487000 Rmurmurp 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]
Root@abcd:~# cat / proc/ `ps-e | grep a.out | awk'{print $1}'`/ maps | tail-n 6 | head-n 4
2b2c01483000-2b2c01487000 Rmurmurp 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]
Root@abcd:~# cat / proc/ `ps-e | grep a.out | awk'{print $1}'`/ 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]
Root@abcd:~# cat / proc/ `ps-e | grep a.out | awk'{print $1}'`/ 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, and there will be problems with the format in different browsers. I also specially took a picture:
What's the use?
You can completely limit the size of a process's stack in this way, not by reporting an error, but by segfault. Then you can signal to capture the segfault and completely unmap the incomplete unmap fixmap vma and the poor and lonely mutilated stack vma inside. But it's really not funny. What's the use? Its purpose is to give you a deeper understanding of the way Linux manages virtual address space.
Little Tips
This article does not cover the thread stack, but it is not difficult. The thread stack is usually allocated dynamically in the heap area or a large mmap area in the middle. Just give it a MAP_GROWSDOWN flag when mmap. There is no difference in the way it is managed. The core question is how the page fault exception handler can tell whether a page fault is a page fault inside of vma (the result is paging) or outside of vma. In the latter case, the missing page processing logic further identifies whether it is a stack missing page (the result is extend stack and then paging) or a non-stack missing page (the result is segfault...).
Linux's stack expands forever unless it encounters a run contraction in this way described in this article. If you want to read the kernel code of Linux, you also need to understand the following facts:
There is only one restriction that the 1.find_vma function can find vma, that is, as long as the input address is less than the end for finding vma, it is not as many people think that the input address must be between start and end for finding vma.
The reason why the 2.find_vma function is so incompletely is to simplify the handling of page fault interrupts, and to provide a more unified way to handle both upgrows and downgrows vma.
Later words
Although this question is a bit confused, but if you can find the above answer for 5 minutes in a row, it should be true! But I don't know what kind of language expression ability can explain every detail of the above clearly without illustration and code. In a word, I think my topic is a good one. You can suggest to those who read this article to make it an interview question. Those who can not find the problem and can not say why, do not! This is really a good test question, it is so good that I want to come up with a few better ones.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.