内存分配如何在极端情况下工作?
我很困惑内存分配(malloc / calloc)如何在linux / c中工作。 假设,我有一台拥有16GB RAM的机器,我以root身份运行一个程序。 它是64位机器,因此所有16GB都可以作为一个单独的网段寻址。 我可以通过一次malloc调用来分配所有这些(减少操作系统的数量)吗? 有很多malloc调用?
这与“堆内存”和“虚拟内存”有什么关系? 如果我分配一个小内存块,它发生在堆内存中,那么我调整(放大)这个块,当我接近堆栈区时会发生什么?
如果我想(几乎)所有RAM都分配给我的单个进程,即使认为它以root身份运行,我是否还必须摆弄selimlimit RLIMIT_AS?
一个64位的进程可以分配所有的内存。 它甚至不需要是root用户,除非系统为非root用户定义了ulimit
设置。 尝试ulimit -v
以查看是否设置了限制。
在Linux默认设置下,进程可以请求几乎任意数量的内存,并且将被授予。 内存将按照使用情况进行实际分配,它将根据需要来自物理RAM或磁盘交换。
内存分配调整大小通常在C库中进行,方法是分配新的较大的大小并将旧数据复制到新分配中。 这通常不是通过扩大现有分配来完成的。 内存分配选择为不与其他分配(如程序堆栈)冲突。
在虚拟内存OS(如Linux)上,malloc()不分配内存。 它分配地址空间例如,编译并运行以下片段,并(在另一个终端中)运行top
:
#include <stdlib.h>
#include <unistd.h>
int main(void) {
char *cp;
cp = malloc( 16ULL * 1024 *1024 *1024);
if (cp) pause();
return 0;
}
在我的电脑上,TOP显示:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
29026 plasser 20 0 16.0g 324 248 S 0 0.0 0:00.00 a.out
这意味着:a.out具有16GB的虚拟大小,并且只使用324(bytes?KB?)常驻内存(可能只是二进制文件)
发生了什么事?
RES
领域,相信我) `
malloc()
可以通过扩展堆或通过mmap()
来分配足够大的内存块来分配内存。 他们使用哪一个取决于您请求的大小以及几个mallopt()
选项。
如果它使用通常位于虚拟内存区域起始处的“真正的”堆部分,则它可以长到它碰到下一个分配的内存块的位置,该内存块离开始处很远。
如果它使用mmap()
,则取决于是否存在可用的连续地址空间。
/proc/<PID>/maps
是查找进程的地址空间情况的良好查询点。
我刚刚使用Python和ctypes测试了我的64位服务器:
import ctypes
import ctypes.util
m=ctypes.CDLL(ctypes.util.find_library("c")).malloc
m.argtypes=(ctypes.c_uint64,)
m.restype = ctypes.c_uint64
现在我有m
,它用作对libc的malloc()
函数的调用。
现在我可以做
>>> hex(m(2700000000))
'0x7f1345e3b010L'
>>> hex(m(2700000000))
'0x7f12a4f4f010L'
>>> hex(m(2700000000))
'0x7f1204063010L'
>>> hex(m(2700000000))
'0x7f1163177010L'
>>> hex(m(2700000000))
'0x7f10c228b010L'
>>> hex(m(2700000000))
'0x7f102139f010L'
>>> hex(m(2700000000))
'0x7f0f804b3010L'
但由于我无法做到的任何原因
>>> hex(m(2900000000))
'0x0L'
因为它返回0和。 一个NULL指针。
现在在做
print open("/proc/self/maps").read()
向我显示所述文件的行; 在某处
7f0ed8000000-7f0ed8021000 rw-p 00000000 00:00 0
7f0ed8021000-7f0edc000000 ---p 00000000 00:00 0
7f0edf5c7000-7f13e6d27000 rw-p 00000000 00:00 0
我得到了我的分配。
但是,如果我这样做
>>> hex(m(1))
'0x1f07320L'
>>> hex(m(1))
'0x1f0c0e0L'
>>> hex(m(1))
'0x1f02d50L'
>>> hex(m(1))
'0x1f02d70L'
>>> hex(m(1))
'0x1ef94f0L'
>>> hex(m(1))
'0x1eb7b20L'
>>> hex(m(1))
'0x1efb700L'
>>> hex(m(270))
'0x1f162a0L'
>>> hex(m(270))
'0x1f163c0L'
>>> hex(m(270))
'0x1f164e0L'
>>> hex(m(270))
'0x1f16600L'
内存地址来自
>>> print open("/proc/self/maps").read()
[...]
01d2e000-01f2b000 rw-p 00000000 00:00 0 [heap]
[...]
指定的堆。
请注意,尽管我可以分配此内存,但使用它们都会造成伤害,因为我的进程可能会被着名的OOM杀手杀死。
链接地址: http://www.djcxy.com/p/82715.html