转自:http://blog.csdn.net/sunny04/article/details/46805261

版权声明:本文为博主原创文章,未经博主允许不得转载。

进程是操作系统的最小资源管理单元, 线程是操作系统最小的执行单元。 一个进程可以有多个线程, 也就是说多个线程分享进程的资源,包括栈区,堆区,代码区,数据区等。

  1. sundh@linhaoIPTV:~$ ulimit -a
  2. core file size          (blocks, -c) 0
  3. data seg size           (kbytes, -d) unlimited
  4. scheduling priority             (-e) 0
  5. file size               (blocks, -f) unlimited
  6. pending signals                 (-i) 31675
  7. max locked memory       (kbytes, -l) 64
  8. max memory size         (kbytes, -m) unlimited
  9. open files                      (-n) 1024
  10. pipe size            (512 bytes, -p) 8
  11. POSIX message queues     (bytes, -q) 819200
  12. real-time priority              (-r) 0
  13. stack size              (kbytes, -s) 8192
  14. cpu time               (seconds, -t) unlimited
  15. max user processes              (-u) 31675
  16. virtual memory          (kbytes, -v) unlimited
  17. file locks                      (-x) unlimited

32bit x86机器上面,执行ulimit -a的命令, 可以看到

stack size              (kbytes, -s) 8192    这是否说明在线程中可以分配8M的局部变量(或者说分配7M的局部变量,还有1M的空间存储其他的局部变量或者寄存器状态信息(例如bp等)或者函数压栈信息等)

写代码验证如下:

  1. //test2.cpp
  2. #include <iostream>
  3. #include <string.h>
  4. #include <pthread.h>
  5. #include <stdio.h>
  6. using namespace std;
  7. void* func(void*a)
  8. {
  9. cout << "enter func" << endl;
  10. cout << "enter func" << endl;
  11. int b[1024*1024*2] = {0};
  12. }
  13. int main()
  14. {
  15. int a[1024*1024*3/2]={0};
  16. pthread_t  pthread ;
  17. pthread_create(&pthread, NULL, func, NULL);
  18. cout << "This is a test" << endl;
  19. //pthread_join(pthread, NULL);
  20. return 0;
  21. }

g++ -g -o test2 test2.cpp -lpthread
sundh@linux:~$ gdb test2
GNU gdb (GDB) 7.5-ubuntu
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/sundh/test2...done.
(gdb) r
Starting program: /home/sundh/test2
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".
[New Thread 0xb7cc1b40 (LWP 10313)]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb7cc1b40 (LWP 10313)]
func (a=0x0) at test2.cpp:10
10          cout << "enter func" << endl;
(gdb)

GDB调试结果如上。   main() 函数中分配1.5M的局部变量,是不会报错的, 但子线程中分配2M的局部变量,就会coredump。 可见,只能分配不大于2M的局部变量,但ulimit -a 查询到的stack size 为8M。

猜想:  线程只能分配不大于 1/4 大小的 stack size 给 局部变量, 这应该是操作系统的规定。(没在网络上面找到相关的文档说明)

那我们现在开始验证我们的猜想:

通过 ulimit -s命令修改默认的栈大小,  下面程序分配5M的局部变量, 也就是说线程栈的大小要 > 20M(5M*4)

  1. //test1.cpp
  2. #include <iostream>
  3. #include <string.h>
  4. #include <pthread.h>
  5. #include <stdio.h>
  6. using namespace std;
  7. void* func(void*a)
  8. {
  9. cout << "enter func" << endl;
  10. cout << "enter func" << endl;
  11. int b[1024*1024*5] = {0};
  12. }
  13. int main()
  14. {
  15. int a[1024*1024*5]={0};
  16. pthread_t  pthread ;
  17. pthread_create(&pthread, NULL, func, NULL);
  18. cout << "This is a test" << endl;
  19. //pthread_join(pthread, NULL);
  20. return 0;
  21. }

ulimit -s 21504 (也就是21M) , 把默认的stack size设置为21M

sundh@linux:~$ ulimit -s 21504
sundh@linux:~$ g++ -g -o test2 test2.cpp -lpthread
sundh@linux:~$ ./test2
This is a testenter func
enter func

可以成功运行, 验证了我们的猜想。

ulimit -s 修改 stack size, 也可以通过 pthread_attr_setstacksize() 来修改。 使用ulimit的一个后果就是它会影响到同一环境(同一shell或者终端)下后续启动的所有程序,如果修改成启动时设置的话就会影响到整个系统。 所以大部分情况下还是使用pthread_attr_setstacksize()

代码如下:

  1. #include <pthread.h>
  2. #include <string.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <unistd.h>
  6. #include <errno.h>
  7. #include <ctype.h>
  8. #define handle_error_en(en, msg) \
  9. do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
  10. #define handle_error(msg) \
  11. do { perror(msg); exit(EXIT_FAILURE); } while (0)
  12. struct thread_info {    /* Used as argument to thread_start() */
  13. pthread_t thread_id;        /* ID returned by pthread_create() */
  14. int       thread_num;       /* Application-defined thread # */
  15. char     *argv_string;      /* From command-line argument */
  16. };
  17. /* Thread start function: display address near top of our stack,
  18. and return upper-cased copy of argv_string */
  19. static void *
  20. thread_start(void *arg)
  21. {
  22. struct thread_info *tinfo = arg;
  23. char *uargv, *p;
  24. <span style="color:#FF0000;">int a[1024*1024*5] = {0};</span>
  25. printf("Thread %d: top of stack near %p; argv_string=%s\n",
  26. tinfo->thread_num, &p, tinfo->argv_string);
  27. uargv = strdup(tinfo->argv_string);
  28. if (uargv == NULL)
  29. handle_error("strdup");
  30. for (p = uargv; *p != '\0'; p++)
  31. *p = toupper(*p);
  32. return uargv;
  33. }
  34. int
  35. main(int argc, char *argv[])
  36. {
  37. int s, tnum, opt, num_threads;
  38. struct thread_info *tinfo;
  39. pthread_attr_t attr;
  40. int stack_size;
  41. void *res;
  42. /* The "-s" option specifies a stack size for our threads */
  43. stack_size = -1;
  44. while ((opt = getopt(argc, argv, "s:")) != -1) {
  45. switch (opt) {
  46. case 's':
  47. stack_size = strtoul(optarg, NULL, 0);
  48. break;
  49. default:
  50. fprintf(stderr, "Usage: %s [-s stack-size] arg...\n",
  51. argv[0]);
  52. exit(EXIT_FAILURE);
  53. }
  54. }
  55. num_threads = argc - optind;
  56. /* Initialize thread creation attributes */
  57. s = pthread_attr_init(&attr);
  58. if (s != 0)
  59. handle_error_en(s, "pthread_attr_init");
  60. if (stack_size > 0) {
  61. s = <span style="color:#FF0000;">pthread_attr_setstacksize</span>(&attr, stack_size);
  62. if (s != 0)
  63. handle_error_en(s, "pthread_attr_setstacksize");
  64. }
  65. /* Allocate memory for pthread_create() arguments */
  66. tinfo = calloc(num_threads, sizeof(struct thread_info));
  67. if (tinfo == NULL)
  68. handle_error("calloc");
  69. /* Create one thread for each command-line argument */
  70. for (tnum = 0; tnum < num_threads; tnum++) {
  71. tinfo[tnum].thread_num = tnum + 1;
  72. tinfo[tnum].argv_string = argv[optind + tnum];
  73. /* The pthread_create() call stores the thread ID into
  74. corresponding element of tinfo[] */
  75. s = pthread_create(&tinfo[tnum].thread_id, &attr,
  76. &thread_start, &tinfo[tnum]);
  77. if (s != 0)
  78. handle_error_en(s, "pthread_create");
  79. }
  80. /* Destroy the thread attributes object, since it is no
  81. longer needed */
  82. s = pthread_attr_destroy(&attr);
  83. if (s != 0)
  84. handle_error_en(s, "pthread_attr_destroy");
  85. /* Now join with each thread, and display its returned value */
  86. for (tnum = 0; tnum < num_threads; tnum++) {
  87. s = pthread_join(tinfo[tnum].thread_id, &res);
  88. if (s != 0)
  89. handle_error_en(s, "pthread_join");
  90. printf("Joined with thread %d; returned value was %s\n",
  91. tinfo[tnum].thread_num, (char *) res);
  92. free(res);      /* Free memory allocated by thread */
  93. }
  94. free(tinfo);
  95. exit(EXIT_SUCCESS);
  96. }

$ ./a.out -s 0x1600000 hola salut servus   (0x1500000  == 20M,0x1600000==21M 

Thread 1: top of stack near 0xb7d723b8; argv_string=hola

Thread 2: top of stack near 0xb7c713b8; argv_string=salut

Thread 3: top of stack near 0xb7b703b8; argv_string=servus

Joined with thread 1; returned value was HOLA

Joined with thread 2; returned value was SALUT

Joined with thread 3; returned value was SERVUS

程序可以正常运行。 这里需要注意的一点是,主线程还是使用系统默认的stack size,也即8M, 不能在main()
里面声明超过2M的局部变量,创建子线程的时候调用了pthread_attr_setstacksize(), 修改stack size为21M,然后就能在子线程中声明5M的局部变量了。

thread线程栈size及局部变量最大可分配size【转】的更多相关文章

  1. C# 类型、对象、线程栈和托管堆在运行时的关系

    我们将讨论类型.对象.线程栈和托管堆在运行时的相互关系,假定有以下两个类定义: internal class Employee    {        public int GetYearsEmplo ...

  2. 关于Linux x64 Oracle JDK7u60 64-bit HotSpot VM 线程栈默认大小问题的整理

    JVM线程的栈默认大小,oracle官网有简单描述: In Java SE 6, the default on Sparc is 512k in the 32-bit VM, and 1024k in ...

  3. WINDOWS操作系统中可以允许最大的线程数(线程栈预留1M空间)(56篇Windows博客值得一看)

    WINDOWS操作系统中可以允许最大的线程数 默认情况下,一个线程的栈要预留1M的内存空间 而一个进程中可用的内存空间只有2G,所以理论上一个进程中最多可以开2048个线程 但是内存当然不可能完全拿来 ...

  4. 关于java的volatile关键字与线程栈的内容以及单例的DCL

    用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最新的值.volatile很容易被误用,用来进行原子性操作. package com.guangshan.test; pub ...

  5. Linux虚拟地址空间布局以及进程栈和线程栈总结【转】

    转自:http://www.cnblogs.com/xzzzh/p/6596982.html 原文链接:http://blog.csdn.net/freeelinux/article/details/ ...

  6. Linux虚拟地址空间布局以及进程栈和线程栈总结

    原文链接:http://blog.csdn.net/freeelinux/article/details/53782986[侵删] 本文转自多个博客,以及最后有我的总结.我没有单独从头到尾写一个总结的 ...

  7. 【摘】Linux虚拟地址空间布局以及进程栈和线程栈总结

    在CSDN上看到的一篇文章,讲的还是满好的. 原文地址:Linux虚拟地址空间布局以及进程栈和线程栈总结 一:Linux虚拟地址空间布局 (转自:Linux虚拟地址空间布局) 在多任务操作系统中,每个 ...

  8. JAVA笔记 之 Thread线程

    线程是一个程序的多个执行路径,执行调度的单位,依托于进程存在. 线程不仅可以共享进程的内存,而且还拥有一个属于自己的内存空间,这段内存空间也叫做线程栈,是在建立线程时由系统分配的,主要用来保存线程内部 ...

  9. 第16章 Windows线程栈

    16.1 线程栈及工作原理 (1)线程栈简介 ①系统在创建线程时,会为线程预订一块地址空间(即每个线程私有的栈空间),并调拨一些物理存储器.默认情况下,预订1MB的地址空间并调拨两个页面的存储器. ② ...

随机推荐

  1. 第63天:json的两种声明方式

    一. json 两种声明方式 1. 对象声明   var  json = {width:100,height:100} 2. 数组声明   var  man = [        //  数组的 js ...

  2. 利用FluidMoveBehavior制作出手机通讯录平滑的效果

    最近学习Blend,原来Blend制作动画等效果非常棒.下面演示一下FluidMoveBehavior应用,利用Blend中行为中的FluidMoveBehavior制作出手机通讯录平滑的效果 1.在 ...

  3. 【bzoj3132】上帝造题的七分钟 二维树状数组区间修改区间查询

    题目描述 “第一分钟,X说,要有矩阵,于是便有了一个里面写满了0的n×m矩阵. 第二分钟,L说,要能修改,于是便有了将左上角为(a,b),右下角为(c,d)的一个矩形区域内的全部数字加上一个值的操作. ...

  4. hdu 3191 How Many Paths Are There (次短路径数)

    How Many Paths Are There Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java ...

  5. (八)Redis事务与连接操作

    事务: multi # 标记一个事务块的开始.事务块内的多条命令会按照先后顺序被放进一个队列当中,最后由EXEC命令原子性地执行 exec # 执行所有事务块内的命令 descard # 取消事务,放 ...

  6. [BZOJ2961] 共点圆 [cdq分治+凸包]

    题面 BZOJ传送门 思路 首先考虑一个点$(x_0,y_0)$什么时候在一个圆$(x_1,y_1,\sqrt{x_1^2+y_1^2})$内 显然有:$x_1^2+y_1^2\geq (x_0-x_ ...

  7. BZOJ1053:[HAOI2007]反素数——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=1053 对于任何正整数x,其约数的个数记作g(x).例如g(1)=1.g(6)=4.如果某个正整数x满 ...

  8. 表单验证:nice Validator

    nice Validator使用文档:http://niceue.com/validator/ 一.自定义验证规则: //大类表单新增修改验证提交 $("#addbigCategory&qu ...

  9. mybatis的模糊查询写法

    mybatis做like模糊查询   1.  参数中直接加入%% param.setUsername("%CD%");      param.setPassword("% ...

  10. HDU3231拓扑排序

    Box Relations Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...