thread线程栈size及局部变量最大可分配size【转】

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

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

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

[cpp] view plain copy

  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等)或者函数压栈信息等)

写代码验证如下:

[cpp] view plain copy

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

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)

[cpp] view plain copy

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

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()

代码如下:

[cpp] view plain copy

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

$ ./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的局部变量了。

时间: 2024-09-27 03:11:08

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

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

转自:http://www.cnblogs.com/xzzzh/p/6596982.html 原文链接:http://blog.csdn.net/freeelinux/article/details/53782986[侵删] 本文转自多个博客,以及最后有我的总结.我没有单独从头到尾写一个总结的原因是别人已经写得很好了,我不花大量时间是无法达到这水平的.   一:Linux虚拟地址空间布局 (转自:Linux虚拟地址空间布局)    在多任务操作系统中,每个进程都运行在属于自己的内存沙盘中.这个沙

数据管理-实时监控- 操作列表显示查看线程栈功能(linux系统)

问题现象 解决方法: 以CentOS 6 Linux 为例,运行命令: yum -y install pstack 安装完成后,重新打开页面 参考 查看线程栈

thread-java Thread线程tickets问题

问题描述 java Thread线程tickets问题 刚学thread,怎么控制台输出会有重复的数目,求大神解答 public class Ticket implements Runnable{ public static int count = 5; private String name; public void run(){ for(int i=0;i<=4;i++){ try{ Thread.sleep(1000); }catch(Exception e){ e.printStackT

Android中断并重启一个Thread线程的简单方法

这里简单的总结下(大概思路,没调试,可能会有错!): MyThread.java pulbic class MyThread implemets Thread{ @overide public void run{ while(!Thread.interrputed()){ } } } xxx.java Thread mThread = new MyThread(); public static void startThread(){ mThread = new MyThread(); mThre

测量block size 为8K ,自动分配的本地管理表空间的位图block一位能管理多少空间

从oracle8i起,oracle推出了本地管理表空间的来代替数据字典管理的表空间,数据字典管理表空间是用uet$,fet$这两个表来管理的,它们现在依然存在于数据库中,不过不起任何作用. SQL> select count(*) from uet$;   COUNT(*) ----------          0 SQL> select count(*) from fet$;   COUNT(*) ----------          0 下面来探究自动分配的本地管理表空间中一个bit

你知道Thread线程是如何运作的吗?

[引自CoorChice的博客]背景介绍 我们在Android开发过程中,几乎都离不开线程.但是你对线程的了解有多少呢?它完美运行的背后,究竟隐藏了多少不为人知的秘密呢?线程间互通暗语,传递信息究竟是如何做到的呢?Looper.Handler.MessageQueue究竟在这背后进行了怎样的运作.本期,让我们一起从Thread开始,逐步探寻这个完美的线程链背后的秘密. 注意,大部分分析在代码中,所以请仔细关注代码哦! 从Thread的创建流程开始 在这一个环节,我们将一起一步步的分析Thread

在Android中使用Handler和Thread线程执行后台操作

大家都知道,在PC上的应用程序当需要进行一些复杂的数据操作,但不需要界面UI的时候 ,我们会为应用程序专门写一个线程去执行这些复杂的数据操作.通过线程,可以执行例如 :数据处理.数据下载等比较耗时的操作,同时对用户的界面不会产生影响.在Android应用 程序开发中,同样会遇到这样的问题.当我们需要访问网络,从网上下载数据并显示在我们 的UI上时,就会启动后台线程去下载数据,下载线程执行完成后将结果返回给主用户界面线 程. 对于线程的控制,我们将介绍一个Handler类,使用该类可以对运行在不同

Java 里的thread (线程)简介

在Java里 thread 就是线程的意思. 说到线程的概念, 自然离不开另外两个词: 程序和进程. 从最基本的程序讲起: 一. 什么是程序(Program) 所谓程序, 就是1个严格有序的指令集合. 程序规定了完成某一任务时,计算机所需要做的各种操作, 以及操作的顺序. 1.1 单道程序运行环境 所谓单道程序环境就是指, 计算机除了操作系统之外, 只允许运行1个用户程序. 以前的DOS系统就是1个典型的单道程序运行环境. 单道程序有如下特点: 1. 资源的独占性: 任何时候, 内存内只有1个用

java中thread线程start和run的区别_java

最近看到一个题目,代码如下: 复制代码 代码如下: public static void main(String args[]) {Thread t = new Thread() {public void run() {pong();}}; t.run();System.out.println("ping");}static void pong() {System.out.println("pong");} 问,结果会输出什么? 我运行了很多次,结果都是pong p