进程超过RedHat Enterprise Linux 6的线程堆栈大小限制?

时间:2012-11-01 14:56:09

标签: linux linux-kernel pthreads redhat ulimit

我在RHEL 6.3上运行了几个进程,但由于某种原因,它们超出了线程堆栈大小。

例如,Java进程在启动时在运行时被赋予-Xss256k的堆栈大小,并且在实际代码中使用pthread_attr_setstacksize()为C ++进程提供1MB的线程堆栈大小。

出于某种原因,这些过程并没有遵守这些限制,我不确定原因。

例如,当我跑

pmap -x <pid> 

对于C ++和Java进程,我可以看到每个(我已经确认的是每个进程创建的内部工作线程)的数百个'anon'线程,但是这些线程的每个分配值为64MB,而不是上面设定的限制:

00007fa4fc000000 168 40 40 rw--- [ anon ] 
00007fa4fc02a000 65368 0 0 ----- [ anon ] 
00007fa500000000 168 40 40 rw--- [ anon ] 
00007fa50002a000 65368 0 0 ----- [ anon ] 
00007fa504000000 168 40 40 rw--- [ anon ] 
00007fa50402a000 65368 0 0 ----- [ anon ] 
00007fa508000000 168 40 40 rw--- [ anon ] 
00007fa50802a000 65368 0 0 ----- [ anon ] 
00007fa50c000000 168 40 40 rw--- [ anon ] 
00007fa50c02a000 65368 0 0 ----- [ anon ] 
00007fa510000000 168 40 40 rw--- [ anon ] 
00007fa51002a000 65368 0 0 ----- [ anon ] 
00007fa514000000 168 40 40 rw--- [ anon ] 
00007fa51402a000 65368 0 0 ----- [ anon ] 
00007fa518000000 168 40 40 rw--- [ anon ] 
...

但是当我使用所有64MB'anon'线程

在上述过程中运行以下内容时
cat /proc/<pid>/limits | grep stack 

Max stack size 1048576 1048576 bytes 

它显示最大线程堆栈大小为1MB,因此对此处发生的事情感到有点困惑。此外,调用这些程序的脚本也设置'ulimit -s 1024'。

应该注意的是,只有在使用非常高端的机器(例如48GB RAM,24个CPU内核)时才会出现这种情况。这个问题不会出现在功能不太强大的机器上(例如4GB RAM,2个CPU内核)。

任何帮助了解这里发生的事情都会非常感激。

4 个答案:

答案 0 :(得分:6)

事实证明,RHEL6 2.11已经更改了线程模型,使得每个线程都可以分配自己的线程池,因此在较大的系统上,您可能会看到它占用64MB。在64位上,允许的最大线程池数量更大。

解决这个问题的方法是添加

export LD_PRELOAD=/path/to/libtcmalloc.so 

在启动进程的脚本中(而不是使用glibc2.11)

可以从以下网站获得更多信息:

Linux glibc&gt; = 2.10(RHEL 6)malloc可能会显示过多的虚拟内存使用情况 https://www.ibm.com/developerworks/mydeveloperworks/blogs/kevgrig/entry/linux_glibc_2_10_rhel_6_malloc_may_show_excessive_virtual_memory_usage?lang=en

glibc bug malloc为多线程应用程序使用过多的内存 http://sourceware.org/bugzilla/show_bug.cgi?id=11261

Apache hadoop通过设置MALLOC_ARENA_MAX解决了这个问题 https://issues.apache.org/jira/browse/HADOOP-7154

答案 1 :(得分:0)

/proc/1234/limits报告的堆栈大小设置为setrlimit(2)(可能在登录时由PAM子系统设置)。

我不知道为什么实际的堆栈段似乎都是64Mb。也许你的大服务器使用huge pages(但你的桌面没有)。

您可以拨打setrlimit(也许使用内置的ulimit bash或内置的limit zsh内容)调用程序的脚本。

答案 2 :(得分:0)

您可以使用ulimit -s <size_in_KB>设置进​​程的最大堆栈大小。您也可以使用ulimit -s查看当前限制。

答案 3 :(得分:0)

@rory关于你的答案,64mb的块地址应该是堆地址,但现在地址就像00007fa50c02a000那样是堆栈地址,对吗?