栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

操作系统内存管理——内存分页

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

操作系统内存管理——内存分页

内存管理主要解决:如何使进程的地址空间隔离,如何提高内存的使用效率,如何解决程序运行时的重定位问题?
引入虚拟地址层。

分段内存


 每个程序都有其独立的虚拟的独立的进程地址空间,可以看到程序A和B的虚拟地址空间都是从0x00000000开始的。我们将两块大小相同的虚拟地址空间和实际物理地址空间一一映射,即虚拟地址空间中的每个字节对应于实际地址空间中的每个字节,这个映射过程由软件来设置映射的机制,实际的转换由硬件来完成。
 1、解决地址空间隔离:比如A访问超过0x00A0000的虚拟地址,内核就会拒绝它;
 2、解决重定位问题:应用程序A只需要关心其虚拟地址空间0x00000000-0x00A00000,而其被映射到哪个物理地址我们无需关心,所以程序永远按照这个虚拟地址空间来放置变量,代码,不需要重新定位。
 3、无法处理内存效率低,因为内存映射机制仍然是以程序为单位,当内存不足时仍然需要将整个程序交换到磁盘,这样内存使用的效率仍然很低。


分页内存(类似于ext文件系统的磁盘分割类似)


1、进程1和进程2的虚拟地址空间都被映射到了不连续的物理地址空间内;
2、甚至他们共用了一部分物理地址空间PP3,这就是共享内存;
3、进程1的虚拟页VP2和VP3被交换到了磁盘中,在程序需要这两页的时候,Linux内核会产生一个缺页异常,然后异常管理程序会将其读到内存中。

地址类型

1、逻辑地址:是由一个段选择符加上一个指定段内相对地址的偏移量(Offset)组成的,表示为 [段选择符:段内偏移量];

2、虚拟地址:其实就是逻辑地址的段内偏移Offset。所以:
 逻辑地址可以表示为 [段标识符:虚拟地址];
 驱动代码或者应用程序中所用的地址就是虚拟地址。

虚拟地址是逻辑地址选定完段之后,再偏移得到的;具体过程如下:
(1)先从段选择符(selector)中得到段描述符;
(2)从段描述符中得到段基地址;
(3)线性地址=段基地址+段内偏移(Offset);


13位的索引号对应到段描述符表中的位置,而T1字段表示使用的是哪个段描述符表。


逻辑地址、虚拟地址和线性地址的关系

Linux内核将所有类型的段的 segment base address 都设成0(包括内核数据段、内核代码段、用户数据段、用户代码段等)。那么这样一来所有段都重合了,也就是不分段了,此外由于段限长是地址总线的寻址限度,所以这也就相当于所有段内空间跟整个线性空间重合了。

这样逻辑地址也就简化为了段内的偏移量(逻辑地址=虚拟地址);由于段基地址变为了0,那么线性地址=逻辑地址=虚拟地址。

所以,在x86 linux内核里,逻辑地址、虚拟地址、线性地址,这是三个地址是一致的。


分页管理 概念

1、 线性地址页:从管理和效率的角度出发,线性地址被分为固定长度的组,称为页(page)。例如32位机器,线性地址最大可为4G,如果用4KB为页容量,这样将线性地址划分为2^20个页。

2、 物理页:也是**“页框”**。分页单元把所有的物理内存也划分为固定长度的管理单位,它的长度一般与线性地址页是相同。

页式管理

说明

1、正在使用的页目录的地址放在CPU的CR3寄存器中,是进行地址转换的起始点。
2、每个进程都有其独立的虚拟地址空间,运行一个进程,首先需要将它的页目录地址放到CR3寄存器中,将其他进程保存下来。
3、每一个32位的线性地址被划分三部分:页目录索引(10位):页表索引(10位):偏移(12位)。
线性地址分为三部分,每个部分都是一种偏移量;以CR3为起点最终找到物理地址页。

步骤

第一步:装入进程的页目录地址(操作系统在调度进程时,把这 地址装入CR3)

第二步:根据线性地址前十位加CR3为偏移量,在页目录下找到对应的索引项即页表地址。

第三步:根据线性地址中间十位加当前页表初始位,在页表下找到对应的索引项即页的起始地址。

第四步:将页的起始地址与线性地址最后12位相加,等到物理地址。

伙伴Buddy算法


一个页是4kb的物理内存,被内核使用struct page结构体描述,也叫页框;

使用场景:当需要申请连续的页框且数量不定时,如四个五个九个等等;
实现:Linux把所有空闲的页框分组为11块链表,每一个链表上的页框块是固定的。第i条链表中每一个页框都含有2^i个连续页。
比如:如果需要8kb内存,可以从链表1中取一个页框(这个页框包含2^1个页大小,8kb);最大支持4M内存。

static inline struct page * alloc_pages(gfp_t gfp_mask, unsigned int order)
分配2^oder个连续的物理页,并返回一个指向第一个页的page结构体

void *page_address(const struct page *page)
返回page页面所映射的虚拟地址
slab实现了内存分配和管理:实现对非常小块的内存管理

1、slab层把不同对象划分为高速缓存(cache)组,每一个高速缓存组都可以存放不同类型的对象;
2、每种对象类型对应一个高速缓存(cache);
3、slab由一个或者多个物理上连续的页(通过伙伴算法申请)组成,每个高速缓存由多个slab组成。

对象:一个或者多个物理上连续的页(伙伴算法链表中的页框)


左侧专门管理高速缓存的列表:cache_chain;
不同的cache中不同的slab的列表,并分为几种状态:
slabs_full:表示管理的对象都已经分配完了;
每个slab由多个物理页构成,物理页上才是被保存的对象

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/993261.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号