我正在使用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-)是否可以完全禁用线程堆栈而不会有太多痛苦?
答案 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位。