[Linux] x86_64, how to thread stack allocation

I. Background

We know that a process address space can be roughly divided into code area (text), read-only data area (rodata), initialization data area (data), the initialization data area (bss),

Heap (heap), shared memory area (.so, mmap place), the stack (stack), the core area (kernel).

Heap: Bottom-up growth

Stack: top-down growth

Here's where the stack can be said to be a process stack (or main thread stack), but when outside the main process (the main thread) creates a new child threads, threads and processes we know little difference in linux, which is housed at in the task_struct different only in the process by the fork, a start copying only the virtual address space of the parent process, and the copy (Cow) these techniques use a virtual address space to write, in which the segments (or regions), the data mentioned zones, if there is an update operation, will be assigned a new physical space to the child process to achieve an independent address space on semantics. For a thread, as it would duplicate the parent process's virtual address space, but is not set to private, but shared, it is equivalent to a process all threads share the same virtual address space.

 

Second, questions

According to mention a background we know that the threads share the virtual address space of the parent process, but we also know that the knowledge in the thread's stack is private, it is how to achieve it? Here direct answer, thread stack size (non-main thread) is fixed, which will free the stack (near the top of the heap allocated top-down) or an idle stack (bottom-up near the bottom of the stack distribution), Thus local function thread stack variables allocated stack space is located to the respective assigned, it can be said that a thread private, and because the thread stack boundary is good to set, thus fixing the thread stack size.

 

Third, examples

3.1 ulimit -a, see the stack size (-s) 8192, which is the size of the stack of the current system of program execution time, the size of the stack here refers to the size of the thread stack, and each will be a new thread to the the value of the size of the allocated thread stack size, so this is the stack size for each thread, rather than the sum of a process stack size in kb

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 15661
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 65535
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 15661
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

3.2 execute the following procedures, and then view the cat / proc / distribution {pid} / maps virtual address

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void *task(void *a) {
    for (;;) {
        sleep(1000);
    }
}

int main() {
    pthread_t pid1, pid2, pid3;
    int rt = -1;
    rt = pthread_create(&pid1, NULL, task, NULL);
    rt = pthread_create(&pid2, NULL, task, NULL);
    rt = pthread_create(&pid3, NULL, task, NULL);
    pthread_join(pid1, NULL);     
    pthread_join(pid2, NULL);     
    pthread_join(pid3, NULL);     
    return 0;
}

cat / proc / {pid} / maps, see [heap] The following continuous 7f341157f000-7f3411d7f000 RW-P, P-7f3411d80000-7f3412580000 RW, RW 7f3412581000-7f3412d81000-P , the three positions corresponding to the three thread stacks size are exactly 8 * 2 ^ 20 = 8192kb = 8mb ( careful you will find that these three segments are interspersed with a short boundary value for dividing the three thread stack), from here we can see these three thread stacks fixed size is 8192kb (ulimit a consistent view), which is assigned downwardly from near the top of the heap of process

00400000-00401000 r-xp 00000000 fd:01 1326537                            /tmp/c/test_pthread/main
00600000-00601000 r--p 00000000 fd:01 1326537                            /tmp/c/test_pthread/main
00601000-00602000 rw-p 00001000 fd:01 1326537                            /tmp/c/test_pthread/main
0212d000-0214e000 rw-p 00000000 00:00 0                                  [heap]
7f341157e000-7f341157f000 ---p 00000000 00:00 0 
7f341157f000-7f3411d7f000 rw-p 00000000 00:00 0 
7f3411d7f000-7f3411d80000 ---p 00000000 00:00 0 
7f3411d80000-7f3412580000 rw-p 00000000 00:00 0 
7f3412580000-7f3412581000 ---p 00000000 00:00 0 
7f3412581000-7f3412d81000 rw-p 00000000 00:00 0 
7f3412d81000-7f3412f41000 r-xp 00000000 fd:01 402248                     /lib/x86_64-linux-gnu/libc-2.23.so
7f3412f41000-7f3413141000 ---p 001c0000 fd:01 402248                     /lib/x86_64-linux-gnu/libc-2.23.so
7f3413141000-7f3413145000 r--p 001c0000 fd:01 402248                     /lib/x86_64-linux-gnu/libc-2.23.so
7f3413145000-7f3413147000 rw-p 001c4000 fd:01 402248                     /lib/x86_64-linux-gnu/libc-2.23.so
7f3413147000-7f341314b000 rw-p 00000000 00:00 0 
7f341314b000-7f3413163000 r-xp 00000000 fd:01 402247                     /lib/x86_64-linux-gnu/libpthread-2.23.so
7f3413163000-7f3413362000 ---p 00018000 fd:01 402247                     /lib/x86_64-linux-gnu/libpthread-2.23.so
7f3413362000-7f3413363000 r--p 00017000 fd:01 402247                     /lib/x86_64-linux-gnu/libpthread-2.23.so
7f3413363000-7f3413364000 rw-p 00018000 fd:01 402247                     /lib/x86_64-linux-gnu/libpthread-2.23.so
7f3413364000-7f3413368000 rw-p 00000000 00:00 0 
7f3413368000-7f341338e000 r-xp 00000000 fd:01 402246                     /lib/x86_64-linux-gnu/ld-2.23.so
7f341357f000-7f3413583000 rw-p 00000000 00:00 0 
7f341358d000-7f341358e000 r--p 00025000 fd:01 402246                     /lib/x86_64-linux-gnu/ld-2.23.so
7f341358e000-7f341358f000 rw-p 00026000 fd:01 402246                     /lib/x86_64-linux-gnu/ld-2.23.so
7f341358f000-7f3413590000 rw-p 00000000 00:00 0 
7fffa7bf4000-7fffa7c15000 rw-p 00000000 00:00 0                          [stack]
7fffa7d05000-7fffa7d08000 r--p 00000000 00:00 0                          [vvar]
7fffa7d08000-7fffa7d0a000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

3.3 near the bottom stack allocation, ulimit -s unlimited (though here set the stack size is unlimited, but in fact it is not infinite, but also a fixed thread stack size, the size of 1mb)

ulimit -s unlimited 

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 15661
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 65535
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) unlimited
cpu time               (seconds, -t) unlimited
max user processes              (-u) 15661
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

cat / proc / {pid} / maps, look up in [stack], there will be three 2b4f20012000-2b4f20212000 RW-P, P-2b4f20213000-2b4f20413000 RW, RW 2b4f20414000-2b4f20614000-P , which are the size of three 1mb, size is the same (you can assign the program in a local variable close 1mb of data for testing, you will find the current thread stack is not infinite, or fixed-size close around 1mb). Thus this case, in the vicinity of the thread stack is allocated stack bottom, bottom-up growth.

00400000-00401000 r-xp 00000000 fd:01 1326537                            /tmp/c/test_pthread/main
00600000-00601000 r--p 00000000 fd:01 1326537                            /tmp/c/test_pthread/main
00601000-00602000 rw-p 00001000 fd:01 1326537                            /tmp/c/test_pthread/main
0180a000-0182b000 rw-p 00000000 00:00 0                                  [heap]
2b4f1f802000-2b4f1f828000 r-xp 00000000 fd:01 402246                     /lib/x86_64-linux-gnu/ld-2.23.so
2b4f1f832000-2b4f1f835000 rw-p 00000000 00:00 0 
2b4f1fa27000-2b4f1fa28000 r--p 00025000 fd:01 402246                     /lib/x86_64-linux-gnu/ld-2.23.so
2b4f1fa28000-2b4f1fa29000 rw-p 00026000 fd:01 402246                     /lib/x86_64-linux-gnu/ld-2.23.so
2b4f1fa29000-2b4f1fa2a000 rw-p 00000000 00:00 0 
2b4f1fa2a000-2b4f1fa42000 r-xp 00000000 fd:01 402247                     /lib/x86_64-linux-gnu/libpthread-2.23.so
2b4f1fa42000-2b4f1fc41000 ---p 00018000 fd:01 402247                     /lib/x86_64-linux-gnu/libpthread-2.23.so
2b4f1fc41000-2b4f1fc42000 r--p 00017000 fd:01 402247                     /lib/x86_64-linux-gnu/libpthread-2.23.so
2b4f1fc42000-2b4f1fc43000 rw-p 00018000 fd:01 402247                     /lib/x86_64-linux-gnu/libpthread-2.23.so
2b4f1fc43000-2b4f1fc47000 rw-p 00000000 00:00 0 
2b4f1fc47000-2b4f1fe07000 r-xp 00000000 fd:01 402248                     /lib/x86_64-linux-gnu/libc-2.23.so
2b4f1fe07000-2b4f20007000 ---p 001c0000 fd:01 402248                     /lib/x86_64-linux-gnu/libc-2.23.so
2b4f20007000-2b4f2000b000 r--p 001c0000 fd:01 402248                     /lib/x86_64-linux-gnu/libc-2.23.so
2b4f2000b000-2b4f2000d000 rw-p 001c4000 fd:01 402248                     /lib/x86_64-linux-gnu/libc-2.23.so
2b4f2000d000-2b4f20011000 rw-p 00000000 00:00 0 
2b4f20011000-2b4f20012000 ---p 00000000 00:00 0 
2b4f20012000-2b4f20212000 rw-p 00000000 00:00 0 
2b4f20212000-2b4f20213000 ---p 00000000 00:00 0 
2b4f20213000-2b4f20413000 rw-p 00000000 00:00 0 
2b4f20413000-2b4f20414000 ---p 00000000 00:00 0 
2b4f20414000-2b4f20614000 rw-p 00000000 00:00 0 
7ffd283e1000-7ffd28402000 rw-p 00000000 00:00 0                          [stack]
7ffd2842c000-7ffd2842f000 r--p 00000000 00:00 0                          [vvar]
7ffd2842f000-7ffd28431000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

 

IV Summary

Whether thread stack is allocated on the stack or heap allocation, which are fixed size, there are boundaries. And because it is being used by a particular thread, so it can also be said thread private (which is in normal use, but if you will be one thread of a local variable address passed to another thread can also be accessed indirectly but circumstances are not normal access to the local variables of another thread)

Published 140 original articles · won praise 28 · views 180 000 +

Guess you like

Origin blog.csdn.net/qq_16097611/article/details/82592873