#include <stdio.h>#include <pthread.h>#include <stdlib.h>#define MiB * 1 << 20int times = 0;void* stack_overflow(void* args) {printf("times = %d\n", ++times);char s[1 << 20]; // 1 MiBstack_overflow(NULL);return NULL;}int main() {pthread_attr_t attr;pthread_attr_init(&attr); // 对变量 attr 进行初始化操作pthread_attr_setstacksize(&attr, 24 MiB); // 设置栈帧大小为 24 MiB 这里使用了一个小的 trick 大家可以看一下 MiB 的宏定义pthread_t t;pthread_create(&t, &attr, stack_overflow, NULL);pthread_join(t, NULL);pthread_attr_destroy(&attr); // 释放线程属性的相关资源return 0;}
上面的程序执行结果如下图所示:

文章插图
从上面程序的执行结果来看我们设置的 24 MB 的栈空间大小起到了效果,我们可以通过线程的递归次数可以看出来我们确实申请了那么大的空间 。在上面的程序当中我们对属性的操作如下,这也是对属性操作的一般流程:
- 使用
pthread_attr_init
对属性变量进行初始化操作 。 - 使用各种各样的函数对属性 attr 进行操作,比如
pthread_attr_setstacksize
,这个函数的作用就是用于设置线程的栈空间的大小 。 - 使用
pthread_attr_destroy
释放线程属性相关的系统资源 。
pthread_attr_setstacksize
给栈空间设置了新的大小,并且使用程序检查验证了新设置的栈空间大小,在这一小节当中我们将介绍使用我们自己申请的内存空间也可以当作线程的栈使用 。我们将使用两种方法取验证这一点:- 使用
malloc
函数申请内存空间,这部分空间主要在堆当中 。 - 使用
mmap
系统调用在共享库的映射区申请内存空间 。
#include <stdio.h>#include <pthread.h>#include <stdlib.h>#define MiB * 1 << 20int times = 0;staticvoid* stack_overflow(void* args) {printf("times = %d\n", ++times);char s[1 << 20]; // 1 MiBstack_overflow(NULL);return NULL;}int main() {pthread_attr_t attr;pthread_attr_init(&attr);void* stack = malloc(2 MiB); // 使用 malloc 函数申请内存空间 申请的空间大小为 2 MiBpthread_t t;pthread_attr_setstack(&attr, stack, 2 MiB); // 使用属性设置函数设置栈的位置 栈的最低地址为 stack 栈的大小等于 2 MiBpthread_create(&t, &attr, stack_overflow, NULL);pthread_join(t, NULL);pthread_attr_destroy(&attr); // 释放系统资源free(stack); // 释放堆空间return 0;}
上述程序的执行结果如下图所示:
文章插图
从上面的执行结果可以看出来我们设置的栈空间的大小为 2MB 成功了 。在上面的程序当中我们主要使用
pthread_attr_setstack
函数设置栈的低地址和栈空间的大小 。我们申请的内存空间内存布局大致如下图所示:
文章插图
使用 mmap 申请内存作为栈空间
#define _GNU_SOURCE#include <stdio.h>#include <pthread.h>#include <stdlib.h>#include <sys/mman.h>#define MiB * 1 << 20#define STACK_SIZE 2 MiBint times = 0;staticvoid* stack_overflow(void* args) {printf("times = %d\n", ++times);char s[1 << 20]; // 1 MiBstack_overflow(NULL);return NULL;}int main() {pthread_attr_t attr;pthread_attr_init(&attr);void* stack = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE,MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);if (stack == MAP_FAILED)perror("mapped error:");pthread_t t;pthread_attr_setstack(&attr, stack, STACK_SIZE);pthread_create(&t, &attr, stack_overflow, NULL);pthread_join(t, NULL);pthread_attr_destroy(&attr);free(stack);return 0;}
经验总结扩展阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 2023年1月29日艾灸吉日一览表 2023年1月29日适合艾灸吗
- 2023年9月17日上学吉日一览表 2023年9月17日是上学吉日吗
- 2023年1月29日洗澡好吗 2023年1月29日洗澡吉日一览表
- 2023年1月29日剪头发行吗 2023年1月29日剪头发吉日一览表
- 2023年1月29日分居行吗 2023年1月29日分居好不好
- 2023年9月17日训马吉日一览表 2023年9月17日适合训马吗
- 2023年9月17日搭窝吉日一览表 2023年农历八月初三宜搭窝吗
- 2023年9月17日制作猫窝黄道吉日 2023年9月17日制作猫窝吉日一览表
- 2023年1月29日给佛像开光吉日一览表 2023年1月29日给佛像开光行吗
- 2023年1月29日玉石开光好吗 2023年1月29日玉石开光吉日一览表