使用setrlimit设置线程的堆栈大小

时间:2014-07-29 15:58:50

标签: c multithreading memory stack setrlimit

我正在使用一个使用默认堆栈大小8MB创建pthread的库。是否有可能以编程方式减少库创建的线程的堆栈大小?我尝试在setrlimit(RLIMIT_STACK...)函数中使用main(),但这似乎没有任何效果。 ulimit -s似乎可以完成这项工作,但我不希望在执行程序之前设置堆栈大小。

任何想法我能做什么?感谢

更新1: 好像我要放弃能够使用setrlimit(RLIMIT_STACK,...).设置堆栈大小我检查了常驻内存并发现它比虚拟内存少得多。这足以让我放弃尝试限制堆栈大小。

2 个答案:

答案 0 :(得分:1)

我觉得你运气不好。如果您使用的库未提供设置堆栈限制的方法,则在创建线程后无法更改它。 setrlimit和shell限制会影响主线程的堆栈。

在进程内存空间中创建线程,以便在创建线程时分配它们的堆栈。在Unix上我相信堆栈将按需映射到RAM,因此如果你不需要它,你实际上可能不会使用8兆内存(虚拟和驻留内存)。

答案 1 :(得分:1)

回答这个问题有几个方面。

首先,正如评论中所述,pthread_attr_setstacksize是实现这一目标的正确方法。如果调用pthread_create的库没有办法让你这样做,修复库将是理想的解决方案。如果线程纯粹是库的内部(不调用来自调用应用程序的代码),它实际上应该根据类似PTHREAD_STACK_MIN + ITS_OWN_NEEDS的内容为堆栈大小设置自己的首选项。如果它正在回调您的代码,它应该让您请求所需的堆栈空间。

其次,作为实现细节,glibc使用setrlimit / ulimit的堆栈限制来导出由pthread_create创建的线程的堆栈大小。你也许可以通过这种方式影响大小,但它不是可移植的,正如你所发现的那样,即使在那里也不可靠(当你从进程内部调用setrlimit时它不起作用)。当相关代码首次初始化时,glibc可能只会探测限制一次,因此我会尝试尽早在setrlimit中移动main调用以查看是否有帮助。

最后,线程的堆栈大小甚至可能与您的应用程序无关。即使堆栈大小为8MB,只有实际已被修改的页面(可能是4k或最多8k,除非堆栈上有大数组)实际上正在使用物理内存。其余的只是占用虚拟地址空间(其中至少有2-3 GB)并且可能提交费用。默认情况下,Linux允许过度使用,因此不会严格执行提交费用,因此glibc请求过多的事实可能甚至不重要。通过将1写入/proc/sys/vm/overcommit_memory,您可以使过度使用检查更加严格,但这会导致您丢失有关何时“内存不足”的信息并使程序崩溃。在这样一个受约束的系统上,您可能更喜欢更严格的过度使用会计,但是您必须修复线程堆栈大小问题......