1. 一个进程有自己独立的进程空间,存在于虚地址,在32位机上都是0-4G
2. 创建了多线程,各个线程要求有自己独立的栈,这些独立的栈是怎么分布的呢?
单线程程序只不过是多线程的一种特殊形式,每创建一个线程时,为每一线程在进程内的栈空间上化分出一片区域,作为该线程的栈空间.并且在线程的描述结构里面应当有保存某些寄存器如esp,ebp之类的数据结构的定义.进程的子线程们有各自的私有栈,可以共享父进程分配的堆内存空间,只有一个主线程的进程也就是有主线程对应的栈,所以进程栈对应的空间就是主线程栈。
ulimit -s 进程资源限制中栈大小的限制是10240K,即10M
//test2.c
#include
#include
#include
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指定的栈大小。
//test4.c
#include
#include
#include
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的栈空间的。
//test5.c
#include
#include
#include
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. 进程的栈(进程栈可以理解为主线程栈)大小是在进程执行的时刻才能指定的,即不是在编译的时刻决定,也不是链接的时刻决定。