博客参考:点击打开链接
关于进程栈和线程栈总结:
(1)进程栈大小时执行时确定的,与编译链接无关
(2)进程栈大小是随机确认的,至少比线程栈要大,但不会超过2倍
(3)线程栈是固定大小的,可以使用ulimit -a 查看,使用ulimit -s 修改
(4)一般默认情况下,线程栈是在进程的堆中分配栈空间,每个线程拥有独立的栈空间,为了避免线程之间的栈空间踩踏,线程栈之间还会有以小块guardsize用来隔离保护各自的栈空间,一旦另一个线程踏入到这个隔离区,就会引发段错误。
看我的测试代码:
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
void *thread_task(void *arg){
// int a[1024] = {0};
// a[1] = 10;
return (void *)0;
}
int main(void)
{
pthread_t tid;
int ret = pthread_create(&tid, NULL, thread_task, (void *)NULL);
if(ret < 0){
perror("pthread_create");
exit(0);
}
while(1){}
pthread_join(tid, NULL);
}
代码很简单,创建了一个线程。下面我们查看它的内存分配:
cd /proc/11858
vim maps
通过计算可以看出一个线程实际分配了8m+4k的空间。当然8m可以通过ulimit -s来调整。为什么有4k保护页呢?
一般默认情况下,线程栈是在进程的堆中分配栈空间,每个线程拥有独立的栈空间,为了避免线程之间的栈空间踩踏,线程栈之间还会有以小块guardsize用来隔离保护各自的栈空间,一旦另一个线程踏入到这个隔离区,就会引发段错误。
看下面追踪代码的执行:
这4k是通过mprotect来分配的4096字节。
补充:最近写代码用到一个命令可以查看线程内存分配的命令----pmap
使用这个命令输出的结果同样证明上面的结论,截图+说明如下:
图上圈出来的就是线程的内存,8192k+4k。