libc如何与操作系统(例如,Linux内核)通信以管理内存?具体地说,它如何分配内存,以及如何释放内存?另外,在什么情况下,它会分别无法分配和释放?
发布于 2012-11-24 06:32:07
这是一个非常普遍的问题,但我想谈谈分配失败的问题。重要的是要认识到,内存实际上是由内核在第一次访问时分配的。在调用malloc/calloc/realloc时,您所做的是在进程的虚拟地址空间内保留一些地址(通过syscall brk、mmap等。libc可以做到这一点)。
当我得到malloc或类似的失败时(或者当libc得到brk或mmap失败时),这通常是因为我耗尽了进程的虚拟地址空间。当没有连续的空闲地址块,并且没有空间扩展现有地址块时,就会发生这种情况。您可以耗尽所有可用空间,也可以达到限制RLIMIT_AS。这很常见,尤其是在使用多线程的32位系统上,因为人们有时会忘记每个线程都需要自己的堆栈。堆栈通常会消耗几兆字节,这意味着在没有更多空闲地址空间之前,您只能创建几百个线程。也许地址空间耗尽的一个更常见的原因是内存泄漏。当然,Libc尝试重用堆上的空间(通过brk syscall获得的空间),并尝试munmmap不需要的映射。但是,它不能重用未“释放”的内容。
由于分配失败,无法从进程(或作为进程一部分的libc )中检测到物理内存不足。是的,你可以点击“过量使用限制”,但这并不意味着物理内存都被占用了。当可用物理内存不足时,内核调用称为OOM killer (Out Of memory Killer)的特殊任务,该任务终止一些进程以释放内存。
关于deallocate失败,我的猜测是,除非你做了一些愚蠢的事情,否则它不会发生。我可以想象将程序中断(堆的末尾)设置在它的原始位置之下(通过brk系统调用)。当然,这是一场灾难的秘诀。希望libc不会这样做,而且这也没有多大意义。但它可以被视为失败的重新分配。如果你提供了一些愚蠢的论据,munmap也会失败,但我想不出它失败的一般原因。这并不意味着它不存在。我们必须深入研究glibc/kernel的源代码才能找到答案。
发布于 2012-11-21 03:13:23
1)如何分配内存
libc为C程序提供了malloc()。
通常,malloc从堆中分配内存,并根据需要使用sbrk(2)调整堆的大小。当分配大于MMAP_THRESHOLD字节的内存块时,glibc malloc()实现使用mmap(2)将内存作为私有匿名映射进行分配。默认情况下,MMAP_THRESHOLD为128 kB,但可以使用mallopt(3)进行调整。使用mmap(2)执行的分配不受RLIMIT_DATA资源限制的影响(请参阅getrlimit(2))。
这是关于sbrk的。
sbrk -更改数据段大小
2)在什么情况下它不能分配
也来自malloc
默认情况下,
遵循乐观的内存分配策略。这意味着当malloc()返回非NULL时,不能保证内存确实是可用的。
来自proc
/proc/sys/vm/overcommit_memory
此文件包含内核虚拟内存记帐模式。值包括:
0:启发式过量提交(这是默认设置)
1:总是过量使用,从不检查
2:始终检查,从不过量提交
发布于 2012-11-21 03:13:06
它主要使用sbrk系统调用来调整数据段的大小,从而为其分配更多的内存。以这种方式分配的内存通常不会被释放回操作系统,因为只有当可供释放的块在数据段的末尾时,才有可能这样做。
有时会通过使用mmap分配内存来完成较大的块,并且可以通过munmap调用再次释放该内存。
https://stackoverflow.com/questions/13480235
复制相似问题