我有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)在可用内存低于时失败 线程堆栈大小?
答案 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)
这是操作系统优雅地失败操作的唯一机会。如果实现允许此操作成功,则在操作期间可能会耗尽内存,因为它无法返回失败代码,例如堆栈增长。操作系统更喜欢让操作失败,而不是必须杀死一个完全无辜的进程。