1

我正在使用 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 输出)没有改变:

旧:10485760,新:65536 - 最小:16384

当我ulimit -s MY_STACK_SIZE_LIMIT在开始应用程序之前使用时,我达到了预期的结果。

我的问题是:

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

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

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

4

2 回答 2

2

#2和#3的答案是no和no。每个线程都需要一个堆栈(您的局部变量和返回地址还去哪里?)并且它们必须是每个线程唯一的(否则线程会覆盖彼此的局部变量和返回地址,使每个人都崩溃)。

至于#1... set stack size 调用正是这个问题的答案。我建议你找出一个可接受的大小来创建你的线程,然后设置它。

至于为什么事情对你来说看起来不正确top…… top是一个臭名昭著的关于内存使用的骗子。:-) 东西真的没有被分配或被OOM杀死吗?线程创建是否失败?性能下降和磁盘分页是否增加?如果这些问题的答案是否定的,那么我认为没有什么可担心的。

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

于 2009-12-04T06:20:58.777 回答
1

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

于 2010-05-15T17:39:37.487 回答