在低可用内存情况下,pthread_create因ENOMEM而失败

时间:2011-08-23 21:47:45

标签: c linux pthreads

我有SH4板,这是规格......

uname -a
Linux LINUX7109 2.6.23.17_stm23_A18B-HMP_7109-STSDK #1 PREEMPT Fri Aug 6 16:08:19 ART 2010
sh4 unknown

并且假设我吃掉了几乎所有的记忆,并且只留下了9 MB。

free
 total       used       free     shared    buffers     cached
Mem:         48072      42276       5796          0        172       3264
-/+ buffers/cache:      38840       9232
Swap:            0          0          0

现在,当我尝试使用默认堆栈大小(8 MB)启动单个线程时 pthread_create因ENOMEM而失败。如果我测试代码,我可以看到失败的函数是mmap:

old_mmap(NULL, 8388608, PROT_READ|PROT_WRITE|PROT_EXEC,                       
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory)

但是,当我使用ulimit -s:

将堆栈大小设置为较低值时
ulimit -s 7500

我现在可以启动10个线程。每个线程都没有分配任何东西,所以它 只消耗最小的开销(aprox。每线程8 kb,对吧?)。

所以,我的问题是:

知道mmap实际上并没有消耗内存, 为什么pthread_create()(或mmap)在可用内存低于时失败 线程堆栈大小?

4 个答案:

答案 0 :(得分:6)

VM设置/proc/sys/vm/overcommit_memory(又名。sysctl vm.overcommit_memory)控制Linux是否愿意分发比计算机的组合RAM +交换更多的地址空间。 (当然,如果你真的尝试访问那么多内存,就会崩溃。尝试搜索“linux oom-killer”......)

此设置的默认值为0.我将推测有人将其设置为您系统上的其他内容。

答案 1 :(得分:3)

在glibc下,线程的默认堆栈大小为2-10 兆字节(通常为8)。您应该使用pthread_attr_setstacksize并使用生成的属性对象调用pthread_create来请求具有较小堆栈的线程。

答案 2 :(得分:2)

mmap消耗地址空间

指针必须在内存中唯一标识一段“内存”(包括mmap文件)。

32位指针只能处理2 / 3GB内存(32位= 2 ^ 32 = 4GB。但内核保留一些地址空间)。 地址空间是有限的。

进程中的所有线程共享相同的地址空间,但不同的进程具有单独的地址空间。

答案 3 :(得分:0)

这是操作系统优雅地失败操作的唯一机会。如果实现允许此操作成功,则在操作期间可能会耗尽内存,因为它无法返回失败代码,例如堆栈增长。操作系统更喜欢让操作失败,而不是必须杀死一个完全无辜的进程。