NPTL默认堆栈大小问题

时间:2009-12-04 06:12:53

标签: linux pthreads nptl

我正在使用C编程语言和 NPTL 2.6 开发多线程模块化应用程序。对于每个插件,都会创建一个POSIX线程。问题是每个线程都有自己的堆栈区域,因为默认堆栈大小取决于用户的选择,这可能会在某些情况下导致大量内存消耗。

为了防止不必要的内存使用,我在创建每个线程之前使用类似的东西来改变堆栈大小:

pthread_attr_t attr;
pthread_attr_init (&attr);
pthread_attr_getstacksize(&attr, &st1);
if(pthread_attr_setstacksize (&attr, MODULE_THREAD_SIZE) != 0) perror("Stack ERR");
pthread_attr_getstacksize(&attr, &st2); 
printf("OLD:%d, NEW:%d - MIN: %d\n", st1, st2, PTHREAD_STACK_MIN);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
/* "this" is static data structure that stores plugin related data */
pthread_create(&this->runner, &attr, (void *)(void *)this->run, NULL);

编辑I:添加了pthread_create()部分。

这没有按预期工作,pthread_attr_getstacksize()报告的堆栈大小已更改,但应用程序的总内存使用量(来自ps / top / pmap输出)未更改:

  

OLD:10485760,NEW:65536 - MIN:16384

当我在开始申请之前使用ulimit -s MY_STACK_SIZE_LIMIT时,我会达到预期的效果。

我的问题是:

1-)在启动应用程序之后是否有任何可移植的(在UNIX变体之间)改变(默认)线程堆栈大小的方法(当然在创建线程之前)?

2-)是否可以为每个线程使用相同的堆栈区域?

3-)是否可以完全禁用线程堆栈而不会有太多痛苦?

2 个答案:

答案 0 :(得分:2)

#2和#3的答案是否定的。每个线程都需要一个堆栈(你的局部变量和返回地址还有哪些?)并且每个线程需要是唯一的(否则线程会覆盖彼此的局部变量并返回地址,使每个人都崩溃)。

对于#1 ...设置堆栈大小调用恰恰就是答案。我建议你找出一个可接受的大小来创建你的线程并设置它。

至于为什么top中的事情看起来不合适...... top是一个关于内存使用的臭名昭着的骗子。 :-)是不是实际上没有分配或被OOM杀死?线程创建失败了吗?性能受损和磁盘分页增加了吗?如果这些问题的答案是否定的,那么我认为不用担心。

根据以下一些评论进行更新:
首先,对于你说不需要太多堆栈空间的东西,16KB仍然很大。如果你真的想变小,我很想在x86 Linux上说4096或8192。其次,是的,您可以将CPU的堆栈指针设置为其他东西..但是当您malloc()mmap()时,这将占用空间。我不知道你怎么认为它有助于将堆栈指针设置为其他东西。也就是说,如果你真的强烈地认为调用main()的线程有太大的堆栈(我会说这有点疯狂)而且pthread_attr_setstacksize()不会让你变得足够小(?{ ),那么也许你可以通过调用clone()系统调用来创建线程,并根据主线程的堆栈指针指定堆栈,或者从其他地方指定缓冲区,或者其他什么来查看非可移植的东西。但是你仍然需要为每个帖子添加一个堆栈,我有一种感觉top仍然会让你失望。也许你的期望有点高。

答案 1 :(得分:1)

我也看到了这个问题。目前还不清楚堆栈是如何计算的,但“额外”空间是根据您的总VM计算的,如果您遇到进程边界,则遇到麻烦(即使您没有使用该空间)。它似乎取决于您运行的Linux版本(即使在2.6系列中),以及您是32位还是64位。