我很困惑内存分配(malloc / calloc)在linux / c中的工作原理 . 假设我有一台16GB RAM的机器,我以root身份运行程序 . 它是64位机器,因此所有16GB都可以作为单个段进行寻址 . 我可以使用单个malloc调用分配所有这些(当然,减去操作系统的数量)吗?有很多malloc电话?
它是如何与“堆内存”和“虚拟内存”相关的?如果我分配一个小内存块,并且它发生在堆内存中,那么我调整(放大)这个块,当我接近堆栈区域时会发生什么?
如果我想(几乎)将所有RAM分配给我的单个进程,甚至认为它以root身份运行,我是否必须使用setrlimit RLIMIT_AS?
3 回答
64位进程可以分配所有内存 . 除非系统为非root用户定义了
ulimit
设置,否则它甚至不需要是root用户 . 尝试ulimit -v
以查看是否设置了限制 .在Linux默认设置下,进程可以请求几乎任何数量的内存,并且它将被授予 . 内存将在使用时实际分配,并且它将根据需要来自物理RAM或磁盘交换 .
内存分配调整大小通常在C库中完成,方法是分配新的更大的大小并将旧数据复制到新的分配中 . 通常不会通过扩展现有分配来完成 . 选择内存分配不与其他分配(如程序堆栈)冲突 .
在虚拟内存OS(例如Linux)上,malloc()不分配内存 . 它分配地址空间例如,编译并运行以下片段,并(在另一个终端中)运行
top
:在我的电脑上,TOP显示:
这意味着:a.out有16GB的虚拟大小,并且只使用324(字节?KB?)驻留内存(可能只是二进制)
发生了什么?
malloc()调用已要求操作系统扩展 address space ,增加16 GB
操作系统已完成此请求,并为其设置页面表等 .
这些页面表没有附加到它们的物理内存(可能除了表格本身)
一旦程序开始引用此地址空间,将附加页面(操作系统将故障)
(页面可能是/ dev / 0的COW,但这只是一个细节)
但是,在程序确实引用地址时,内存必须由OS分配并附加到进程 . (它将显示在
RES
字段中,相信我)在某个时刻,一旦操作系统认为它已经使用了很长时间,附加的内存也可以分离 . 它将被添加到可用内存池中或/和用于其他目的 . 在这种情况下,其内容可能会被推送到后备存储(磁盘)
`
malloc()
可以通过扩展堆或mmap()
足够大的内存块来分配内存 . 它使用哪个取决于您请求的大小和几个mallopt()
选项 .如果它使用通常位于虚拟内存区域开头的“真实”堆部分,它可以长到它到达下一个分配的内存块的位置,该内存块远离开始 .
如果它使用
mmap()
,则取决于是否有可用的连续地址空间 ./proc/<PID>/maps
是查找进程的地址空间情况的好查询点 .我刚刚使用Python和ctypes测试了我的64位服务器:
现在我有
m
,它用作对libc的malloc()
函数的调用 .现在我能做到
但由于任何原因我不能做
因为它返回0分 . 一个NULL指针 .
现在就做
向我展示了所述文件的行;某处
我得到了我的分配 .
但是,如果我改为
内存地址来自
指定的堆 .
请注意,虽然我可以分配这个内存,但使用它会造成伤害,因为我的进程可能会被着名的OOM杀手杀死 .