centos系统-线程栈空间

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sunny04/article/details/80548135

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显示的值
展开阅读全文

没有更多推荐了,返回首页