我正在使用一个使用默认堆栈大小8MB创建pthread的库。是否有可能以编程方式减少库创建的线程的堆栈大小?我尝试在setrlimit(RLIMIT_STACK...)
函数中使用main()
,但这似乎没有任何效果。 ulimit -s
似乎可以完成这项工作,但我不希望在执行程序之前设置堆栈大小。
任何想法我能做什么?感谢
更新1:
好像我要放弃能够使用setrlimit(RLIMIT_STACK,...).
设置堆栈大小我检查了常驻内存并发现它比虚拟内存少得多。这足以让我放弃尝试限制堆栈大小。
答案 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
,您可以使过度使用检查更加严格,但这会导致您丢失有关何时“内存不足”的信息并使程序崩溃。在这样一个受约束的系统上,您可能更喜欢更严格的过度使用会计,但是您必须修复线程堆栈大小问题......