版權聲明:本文為部落客原創文章,未經部落客允許不得轉載。
程序是作業系統的最小資源管理單元, 線程是作業系統最小的執行單元。 一個程序可以有多個線程, 也就是說多個線程分享程序的資源,包括棧區,堆區,代碼區,資料區等。
sundh@linhaoIPTV:~$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 31675
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 31675
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
32bit x86機器上面,執行ulimit -a的指令, 可以看到
stack size (kbytes, -s) 8192 這是否說明線上程中可以配置設定8M的局部變量(或者說配置設定7M的局部變量,還有1M的空間存儲其他的局部變量或者寄存器狀态資訊(例如bp等)或者函數壓棧資訊等)
寫代碼驗證如下:
//test2.cpp
#include <iostream>
#include <string.h>
#include <pthread.h>
#include <stdio.h>
using namespace std;
void* func(void*a)
{
cout << "enter func" << endl;
int b[1024*1024*2] = {0};
}
int main()
int a[1024*1024*3/2]={0};
pthread_t pthread ;
pthread_create(&pthread, NULL, func, NULL);
cout << "This is a test" << endl;
//pthread_join(pthread, NULL);
return 0;
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)
//test1.cpp
int b[1024*1024*5] = {0};
int a[1024*1024*5]={0};
ulimit -s 21504 (也就是21M) , 把預設的stack size設定為21M
sundh@linux:~ulimit−s21504sundh@linux: ulimit−s21504sundh@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()
代碼如下:
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
struct thread_info { /* Used as argument to thread_start() */
pthread_t thread_id; /* ID returned by pthread_create() */
int thread_num; /* Application-defined thread # */
char *argv_string; /* From command-line argument */
};
/* Thread start function: display address near top of our stack,
and return upper-cased copy of argv_string */
static void *
thread_start(void *arg)
struct thread_info *tinfo = arg;
char *uargv, *p;
<span style="color:#FF0000;">int a[1024*1024*5] = {0};</span>
printf("Thread %d: top of stack near %p; argv_string=%s\n",
tinfo->thread_num, &p, tinfo->argv_string);
uargv = strdup(tinfo->argv_string);
if (uargv == NULL)
handle_error("strdup");
for (p = uargv; *p != '\0'; p++)
*p = toupper(*p);
return uargv;
int
main(int argc, char *argv[])
int s, tnum, opt, num_threads;
struct thread_info *tinfo;
pthread_attr_t attr;
int stack_size;
void *res;
/* The "-s" option specifies a stack size for our threads */
stack_size = -1;
while ((opt = getopt(argc, argv, "s:")) != -1) {
switch (opt) {
case 's':
stack_size = strtoul(optarg, NULL, 0);
break;
default:
fprintf(stderr, "Usage: %s [-s stack-size] arg...\n",
argv[0]);
exit(EXIT_FAILURE);
}
}
num_threads = argc - optind;
/* Initialize thread creation attributes */
s = pthread_attr_init(&attr);
if (s != 0)
handle_error_en(s, "pthread_attr_init");
if (stack_size > 0) {
s = <span style="color:#FF0000;">pthread_attr_setstacksize</span>(&attr, stack_size);
if (s != 0)
handle_error_en(s, "pthread_attr_setstacksize");
/* Allocate memory for pthread_create() arguments */
tinfo = calloc(num_threads, sizeof(struct thread_info));
if (tinfo == NULL)
handle_error("calloc");
/* Create one thread for each command-line argument */
for (tnum = 0; tnum < num_threads; tnum++) {
tinfo[tnum].thread_num = tnum + 1;
tinfo[tnum].argv_string = argv[optind + tnum];
/* The pthread_create() call stores the thread ID into
corresponding element of tinfo[] */
s = pthread_create(&tinfo[tnum].thread_id, &attr,
&thread_start, &tinfo[tnum]);
handle_error_en(s, "pthread_create");
/* Destroy the thread attributes object, since it is no
longer needed */
s = pthread_attr_destroy(&attr);
handle_error_en(s, "pthread_attr_destroy");
/* Now join with each thread, and display its returned value */
s = pthread_join(tinfo[tnum].thread_id, &res);
handle_error_en(s, "pthread_join");
printf("Joined with thread %d; returned value was %s\n",
tinfo[tnum].thread_num, (char *) res);
free(res); /* Free memory allocated by thread */
free(tinfo);
exit(EXIT_SUCCESS);
$ ./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的局部變量了。
本文轉自張昺華-sky部落格園部落格,原文連結:http://www.cnblogs.com/sky-heaven/p/7654950.html,如需轉載請自行聯系原作者