Linux内存管理

目录

一、两种管理物理内存方法

二、结点 pglist_data

三、内存域 zone

四、页帧 page

五、页表

六、内核在内存中的布局

七、内核地址空间划分

八、bootmem分配器

九、伙伴系统

十、VMALLOC

十一、持久内核映射

十二、临时内核映射

十三、slab分配器

十四、进程虚拟内存

十五、内存映射 vm_area_struct


一、两种管理物理内存方法

UMA计算机(一致内存访问),SMP系统中的每个处理器访问各个内存区都是同样快。

NUMA计算机(非一致内存访问),系统的各个CPU都有本地内存,可支持特别快速的访问。各个处理器之间通过总线连接起来,以支持对其它CPU的本地内存的访问。

二、结点 pglist_data

node_zonelists指定了备用结点及其内存域的列表,以便在当前结点没有可用空间时,在备用结点分配内存。在build_all_zonelists中初始化。

为结点2的ZONE_HIGHMEM分配备用结点的情况,如下图:

三、内存域 zone

lowmen_reserve数组分别为各种内存域指定了若干页,用于一些无论如何都不能失败的关键性内存分配。

冷热页帧,在分配内存页时,首先从热页帧列表中分配(除非指定从冷页帧列表中分配),如果没有,则从伙伴系统中分配若干页到该列表中。页面回收时,进入热页帧列表。回收的页帧大概率存在于CPU缓存中,每次先从热页帧列表分配,有助于CPU缓存命中。

四、页帧 page

五、页表

内核内存管理总是嘉定使用四级页表,IA-32体系结构只是用两级。

PGD、PUD、PMD、PTE、Offset

六、内核在内存中的布局

前4KiB是第一个页帧,一般会忽略,通常保留给BIOS使用。

接下来的640KiB原则上是可用的,但也不用于内核加载。其原因是,该区域之后紧邻的区域由系统保留,用于映射各种ROM。内核总是会装载到一个连续的内存区中,如果要从4KiB处作为起始位置来装载内核映像,则要求内核必须小于640KiB。

七、内核地址空间划分

 

八、bootmem分配器

用于伙伴系统启用之前,通过bit位记录各个页帧使用情况(低端内存域页帧,DMA和NORMAL)

九、伙伴系统

struct zone --> struct free_area free_area[MAX_ORDER]  --> struct list_head free_list[MIGRATE_TYPES]

首先区分分配阶,再区分迁移类型(用于防止产生碎片)。

涉及页帧包含直接映射的所有物理页帧。

十、VMALLOC

使用 struct vm_struct 链表记录所分配的虚拟地址空间信息。该结构所用内存通过kmalloc分配。

主要用于分配高端内存域的页帧。

十一、持久内核映射

pkmap_count其中每个元素都对应于一个持久映射页,用于标记对应虚拟内存页是否已经映射。

struct page_address_map用于建立页帧和虚拟内存的映射关系。该结构存储于page_address_htable数组中,散列表。struct page_address_map中的链表元素用于建立溢出链表,以处理散列碰撞。散列函数是page_slot。

page_address函数可以根据指定的page获得对应的虚拟地址。对于高端内存域,使用上述散列表计算。对于直接映射的内存域,则通过偏移量直接计算。

十二、临时内核映射

对应于固定映射区。

相对于持久内核映射,该映射执行是原子的,在固定映射区域中,每个处理器都有一个对应的窗口,每个窗口中,每种映射类型都对应于一项。

十三、slab分配器

嵌入式系统可以使用slob,大型计算机使用slub

着色是为了给slab添加偏移量,否则,对于不同slab中,具有相同偏移的objects大概率会落到同一个cache line上,造成cache line的争用。

struct kmem_cache中的struct array_cache *array[NR_CPUS]用处类似于伙伴系统中使用的冷热页。在申请内存时,首先在array_cache中申请;申请不到时,再从slab中取若干objects放入该结构中;如果slab中也没有足够objects,再从伙伴系统中分配slab。

slab头部管理数据后的数组,每一项对应一个object,数组项纪录了下一个空闲的object便宜值。

slab系统初始化过程中也使用了slab系统,涉及了鸡生蛋蛋生鸡的问题,所以采用了分步初始化,在未完全初始化的时候,采用静态变量来赋值,在初始化过程中,逐渐将静态变量替换为通过slab动态分配的内存。

十四、进程虚拟内存

默认情况下,内存映射区向上增长,起始地址通常是1GiB处(TASK_UNMAPPED_BASE起始于0x4000000),那么意味着堆最多只有1GiBson控件可以使用,为避免此种情况,引入新的虚拟地址空间布局,如下图:

由于栈是有界的,因此安置内存映射的区域可以在栈末端的下方立即开始。

十五、内存映射 vm_area_struct

每个打开文件都表示为struct file的一个实例。该结构包含了一个指向地址空间对象struct address_space的指针。该对象时优先查找树的基础,而文件区间与其映射到地址空间之间的关联即通过优先树简历。此外,每个文件和块设备都表示为struct inode的一个实例。

对于非线性映射,页表项中存储了文件偏移量,以便在从后备设备中读取正确的内容进内存。

 

参考 《深入Linux内核架构》

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值