进程构成:1.代码段 :可执行程序代码
2.数据段:已经初始化的全局变量,静态变量,连续存储
3.BSS段:未初始化的全局变量,连续存储
4.堆(heap):向上分配的内存段,由malloc,new申请,free,delete释放,连续存储
5.栈(stack):向下分配的内存段, 局部变量,函数参数
内核进程内存区域数据结构:
vm_area_struct,以链表、红黑树的形式组织内存区域;链表用于遍历全部节点,红黑树用于定位定位特定内存内存区域虚拟内存:进程申请的内存是虚拟内存(分段),只有当程序真的访问内存时才会(缺页中断)去实际申请物理内存。实例:在go代码中,一次性申请4G内存(显示是虚拟内存)是可以的,不会异常关闭,但当实际使用4G内存时,会收到killed信号,导致程序异常退出。
物理内存管理:
struct_page, 通过分页机制实现,页大小为4K,内核使用“伙伴”关系来管理空闲页面。
伙伴管理原理:
将物理内存分成11个块链表,每个链表包含的是大小为1,2,4,8...512,1024的连续页框块;举例来说要分配256个连续页框,会先到块大小为256的链表中查找空闲块,若有直接返回,若没有,去大小为512的链表中进行查找,将512大小块分为两部分,一部分返回,一部分插入256大小的链表中,若512大小的链表中还没有,到1024大小的链表中查找,取出256大小的块,将剩下的512,256的块分别插入到各个链表中,内存释放的过程则是相反的。
内核内存分配技术slab:
每个 slab 由一个或多个物理连续的页面组成,每个 cache 由一个或多个 slab 组成,每个内核数据结构都有一个 cache
slab 分配器提供两个主要优点:
没有因碎片而引起内存浪费。碎片不是问题,因为每个内核数据结构都有关联的 cache,每个 cache 都由一个或多个 slab 组成,而 slab 按所表示对象的大小来分块。因此,当内核请求对象内存时,slab 分配器可以返回刚好表示对象的所需内存。
可以快速满足内存请求。因此,当对象频繁地被分配和释放时,如来自内核请求的情况,slab 分配方案在管理内存时特别有效。分配和释放内存的动作可能是一个耗时过程。然而,由于对象已预先创建,因此可以从 cache 中快速分配。再者,当内核用完对象并释放它时,它被标记为空闲并返回到 cache,从而立即可用于后续的内核请求。