深入linux内核35节.docx

上传人:b****5 文档编号:7647634 上传时间:2023-01-25 格式:DOCX 页数:11 大小:1.51MB
下载 相关 举报
深入linux内核35节.docx_第1页
第1页 / 共11页
深入linux内核35节.docx_第2页
第2页 / 共11页
深入linux内核35节.docx_第3页
第3页 / 共11页
深入linux内核35节.docx_第4页
第4页 / 共11页
深入linux内核35节.docx_第5页
第5页 / 共11页
点击查看更多>>
下载资源
资源描述

深入linux内核35节.docx

《深入linux内核35节.docx》由会员分享,可在线阅读,更多相关《深入linux内核35节.docx(11页珍藏版)》请在冰豆网上搜索。

深入linux内核35节.docx

深入linux内核35节

物理内存的管理

3.5.1伙伴系统的结构

系统中每个物理内存页都对应于一个structpage实例,每个内存域都关联一个structzone的实例。

 

 

order:

描述了内存分配的数量单位。

order范围0~MAX_ORDER

 

 

●第0个链表包含的内存区为单页,第1为2的一次方..........

●内存区中第1页内的链表元素,可用于将内存区维持在链表中,所以不必引入新的数据结构来管理,否则这些页不可能在同一内存区。

●主要优点之一:

管理工作较少。

●备用列表:

连接所有内存域和节点。

●内存分配原则:

在首选的内存域或节点无法满足内存分配请求时,首先尝试同一节点的另一个内存域,接下来再尝试另一个节点,直至满足要求。

3.5.2避免碎片

1、依据可移动性组织页

 

 

上图表示所有的空闲内存和非空闲内存都是连续的,而下面的图不是连续的,空闲内存最大只有一个页。

●内核的方法是反碎片。

不可移动页:

在内存中有固定位置,不能移动到其他地方。

可回收页:

不能直接移动,但可以删除,其内容可以从某些源重新生成。

可移动页:

可以随意移动。

●内核使用反碎片技术,基于将具有相同可移动性的页分组的思

●如图所示:

 

●数据结构:

内核定义的迁移类型

 

 

●初始化基于可移动性的分组

在内存子系统初始化期间,memmap_init_zone负责处理内存域的page实例,所有页最初都标记为可移动的!

分配内存时,如果必须“盗取”不同于预定迁移类型的内存区,内核在策略上倾向于“盗取”更大的内存区。

2、虚拟可移动内存域

●虚拟内存域ZONE_MOVABLE,必须由管理员显式激活。

●基本思想:

可用的物理内存分为两个内存域,一个用于可移动分配,一个用于不可移动分配。

●数据结构:

Kernelcore指定用于不可移动分配的内存数量;

Movablecore控制用于可移动内存分配的内存数量。

●物理内存域提取的用于ZONE_MOVABLE的内存数量必须考虑下面两种情况:

1 用于不可移动分配的内存会平均地分布到所有内存结点。

2 只使用来自最高内存域的内存。

在内存较多的32位系统上,通常为ZONE_HIGHMEM,但在64位系统上,将使ZONE_NORMAL或ZONE_DMA32。

 

3.5.3初始化内存域和结点数据结构

体系结构相关代码需要在启动期间建立以下信息:

1.系统中各个内存域的页帧边界,保存在max_zone_pfn中

2.个结点页帧的分配情况,保存在全局变量early_node_map中。

从内核版本2.6.10开始提供一个通用的框架,用于将上述信息转换为伙伴系统预期的结点和内存域数据结构。

在这以前,各个体系结构必须自行建立相关结构。

现在,体系结构相关代码只需要建立前述的简单结构,将繁重的工作留给free_area_init_nodes即可。

图给出了该过程概述和free_area_init_nodes的代码

3.5.4分配器API

●alloc_pages(mask,order)分配2order页并返回一个structpage的实例,表示分配的内存块的起始页

●get_zeroed_page(mask)分配一页并返还一个page实例,页对应的内存填充0。

●_get_free_pages(mask,order)和_get_free_page(mask)的工作方式与上述函数相同,但返回分配内存块的虚拟地址,而不是page实例。

●get_dma_pages(gfp_mask,order)用来获得适用于DMA的页。

注意:

分配失败的情况下,上述函数返回空指针或者0。

1、分配掩码

只要设置了_GPF_DMA就从_GPF_DMA内存域扫描。

内核定义的下列标志意义很明确:

2、内存分配宏

上述的函数主要是通过宏定义联系起来的,具体参考书本。

3.5.5分配页

alloc_pages_node只执行一个简单检查,避免分配过大的内存块。

主要工作委托给_alloc_pages,它是“伙伴系统的心脏”。

1、选择页

前几个标志判断页是否可分配时要考虑那些水印。

通过相应的标识,内存分配过程中的努力程度也有所不同。

主要包括:

内存足够时实现分配比较简单;内存不足就会唤醒守护程序kswapd,通过缩减内存缓存和页面回收获得等等;如果再次失败内核也会采取相应措施,比如采取OOMkiller机制。

2、移除选择的页

如果内核找到适当的内存域,并具有足够的空闲页可供支配,首先必须检查这些页是否是连续的,其次,必须按伙伴系统的方式从free_lists移除这些页,可能需要分解并重排内存区。

如果只分配一页,内核会进行优化,该页并不是从伙伴系统直接取得,而是取自per_cpu的页缓存。

●如果需要分配的内存块长度小于所选择的连续页范围,那么该内存块必须按照伙伴系统的原理分裂成小的块,通过expand函数。

●分配内存的最后手段:

如果遍历了所有分配阶和所有迁移类型,仍然无法满足分配请求,内核可以尝试从MIGRATE_RESERVE列表满足分配请求。

3.5.6释放页(__free_pages)

●可以看到,落脚点是__free_pages()这个函数,它执行的工作的流程图如下图所示

●可以通过一个简单的情形来模拟一下这个过程,假设现在有一个将要释放的页,它的order为0,page_idx为10。

则先计算它的伙伴10^(1<<0)=11,然后计算合并后的起始页偏移为10&~(1<<0)=10,现在就得到了一个order为1的块,起始页偏移为10,它的伙伴为10^(1<<1)=8,合并后的起始页偏移为10&~(1<<1)=8,如此推导下去,我们可以通过下图和下表更清晰地分析这个过程

3.5.7内核中不连续页的分配

3.5.8内核映射

内核提供了其它函数用于将ZONE_HIGHMEM页帧显式映射到内核空间,这些函数与vmalloc机制无关。

1.持久内核映射

图中vitualaddressspace里面的每一个格子的空间大小为4kB,及一个页的大小,该空间及虚拟空间。

pkmap_count所指代的数组的每个单位大小是4B,及int类型,该数组主要是为了对vitualaddressspace中的虚拟地址被映射多少次的计数。

2.临时内核映射原理

上文描述的持久映射因为不能用于中断处理程序,所以系统还需要一种原子执行的函数来完成任务,逻辑上称为kmap_atomic,他的主要优点是执行速度快,但是不能用于进入睡眠的代码。

但在描述临时映射之前,阐明固定映射是必要的,毕竟它是基于固定映射的。

固定映射在3.4节中有所提及。

在内核虚拟内存的划分中,最后一段FIXMAPS即为固定映射所处的虚拟地址段。

 

●虚拟地址的计算过程:

idx=type+KM_TYPE*smp_processor_id();

vaddr=__fix_to_virt(FIX_KMAP_BEGIN+idx);

FIX_KMAP_BEGIN来自固定映射的枚举类型

从上面的计算公式我们知道每一个临时内核映射对于不同的cpu是分开的。

如下图:

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 农林牧渔 > 林学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1