1. 一个进程有自己独立的进程空间,存在于虚地址,在32位机上都是0-4G
2. 创建了多线程,各个线程要求有自己独立的栈,这些独立的栈是怎么分布的呢?
单线程程序只不过是多线程的一种特殊形式,每创建一个线程时,为每一线程在进程内的栈空间上化分出一片区域,作为该线程的栈空间.并且在线程的描述结构里面应当有保存某些寄存器如esp,ebp之类的数据结构的定义.进程的子线程们有各自的私有栈,可以共享父进程分配的堆内存空间,只有一个主线程的进程也就是有主线程对应的栈,所以进程栈对应的空间就是主线程栈。
3. 实例验证-线程栈空间:
ulimit -s 进程资源限制中栈大小的限制是10240K,即10M
//test2.c #include <stdio.h> #include <stdlib.h> #include <pthread.h> int i = 0; pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER; void * test(void* s) { int buffer[1024]={1}; printf("i=%d,%p\n", i,buffer); pthread_mutex_lock(&mutex); i++; if(i>4500) return; pthread_mutex_unlock(&mutex); test(s); //sleep(1000); } int main() { pthread_t pl,p2,p3; printf("pid=%d\n", getpid()); pthread_create(&pl, NULL, test, NULL); pthread_create(&p2, NULL, test, NULL); printf("================"); sleep(1000); return 0; }
运行结果:
创建了两个子线程,并把子线程栈中的变量地址空间答应出来了。 我们用 cat /proc/xxx/maps 来看下这个进行的进程内存分布:
上图中1标记的地方是进程栈的地址空间-也即是主线程的地址空间。 栈大小是 0x7ffe7e3cd000 - 0x7ffe7e3b8000 = 0x15000=84K;ox7ff73c09a000-0x7ff73c099000=0x1000 =4K,这块空间是 rw-p权限,不是栈的保护页,因为保护页是不可读不可写权限的。
上图中2 和3标记的两个子线程的地址空间和4K的保护页。 程序运行结果: i=4498,0x7ff73af7a5d0, 这个地址空间正好处于 标记2中; i=4500,0x7ff73a645bb0,这个地址空间正好处于标记3中。 7ff73a4c5000-7ff73a4c6000 ---p 和 7ff73aec6000-7ff73aec7000 ---p 是子线程的保护页。 0x7ff73b8c7000-0x7ff73aec7000=10M, 正好是 ulimit -s指定的栈大小。
4. 实例验证-进程栈的大小:
4.1
//test4.c #include <stdio.h> #include <stdlib.h> #include <pthread.h> int i = 0; pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER; void * test(void* s) { int buffer[1024]={1}; printf("i=%d\n", i); pthread_mutex_lock(&mutex); i++; pthread_mutex_unlock(&mutex); if(i>2000) return; test(s); } int main() { printf("pid=%d\n", getpid()); test(NULL); sleep(1000); return 0; }
上面的例子:进程只有一个主线程, 局部变量占用 2000×1024×sizeof(int) = 8000K的栈空间。 查看进程内存空间分布如下:
0x7ffe5efff000-0x7ffe5e813000=0x7EC000=8112K, 包含上面计算的8000K的栈空间的。
4.2
//test5.c #include <stdio.h> #include <stdlib.h> #include <pthread.h> int i = 0; pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER; void * test(void* s) { int buffer[1024]={1}; printf("i=%d\n", i); pthread_mutex_lock(&mutex); i++; pthread_mutex_unlock(&mutex); //if(i>2000) // return; test(s); //sleep(1000); } int main() { printf("pid=%d\n", getpid()); test(NULL); sleep(1000); return 0; }
test5.c的代码对比与test4.c, 注释掉了 if(i>2000) return; 别的都一样。
执行结果如下, 3032×1024×sizeof(int) =12128K,约等于12M,大于 ulimit -s设置的栈大小10M:
对比test4.c 和 test5.c的结果,得出下面的结论:
1. 进程的栈(进程栈可以理解为主线程栈)大小是在进程执行的时刻才能指定的,即不是在编译的时刻决定,也不是链接的时刻决定。2. 进程的栈(可以理解为主线程栈)大小是随机确定的至少比线程的栈要大,但是不到线程栈大小的2倍
3. 线程栈的大小是固定的,也就是ulimit -a显示的值