简而言之:进程的虚拟地址空间是连续的吗?
我需要知道内核分配给进程的虚拟地址。如果我继续错误,请纠正我。
在创建流程时,内核将虚拟内存分配给流程,并在mm_struct
的{{1}}中存储流程不同部分的虚拟地址的开头和结尾。
现在说一个进程已经用完堆,需要增加堆size.calls task_struct
。
如果虚拟地址范围是连续的,那么新分配的堆块是否是从最初为此进程分配的范围之外提供的?或者它是以新块与原始块相邻的方式分配的。如果没有空间(因为内存映射段正在那里),该怎么办?它是如何跟踪的?
如果虚拟地址范围不连续,brk()
如何跟踪堆(或任何其他段)的地址范围的不同块?
请你清楚我的概念吗?
答案 0 :(得分:8)
虚拟地址空间不连续。请参阅cat /proc/<pid>/mem
的输出。
启动进程时,内核为动态链接器和进程本身分配几个映射。然后,动态链接器通过mmap()
分配更多映射,并且进程可以通过mmap()
分配更多映射,并通过brk()
扩展堆。 dlmalloc上的malloc()
和衍生产品使用brk()
进行短于阈值的分配,mmap()
进行大于或等于该阈值的分配(约128K IIRC)。
在任何情况下,当调用mmap()
时,内核通常会将内存远离堆映射,因此通常有足够的空间来扩展堆。如果没有剩余的虚拟空间来扩展堆,brk()
将失败。
答案 1 :(得分:6)
不,进程的虚拟地址空间不一定是连续的。在过去,一个进程通过brk
获得了内存,这确实迫使进程堆成为一个连续的内存区域。现在内存分配是通过mmap
来完成的,它可以逐页操作进程的虚拟内存。
如果你对内核方面感到好奇,我推荐两个引用:
mm
directory;从mmap.c
或mm.h
开始。如果您想浏览系统,可以在/proc/$pid/maps
中查看每个进程的内存映射。有关详细信息,请参阅How do I read from /proc/$pid/mem under Linux?。
答案 2 :(得分:1)
感谢.. 按照我的理解,经过上述文献后,
虚拟地址空间在整个过程中不连续,甚至在整个给定的内存段中也不连续。并且使用vm_area_struct
(虚拟内存区域)的AVL树在内核中管理不同的虚拟地址范围块。从而轻松地将虚拟内存区域的块添加和删除到进程的task_struct
。参考:Virtual Memory。但虚拟内存区域本身是连续的。
即。实际上task_struct
包含一个指向mm_struct
的指针,该指针包含一个指向AVL树头的指针(每个内存区域有一棵树)。树的节点只是vm_area_struct
s,它有开始和结束指针来标记虚拟内存区域的开始和结束
非常感谢