Linux内存空间以及内存管理

虚拟内存:

Linux操作系统采用虚拟内存管理技术,使得每个进程都有各自互不干涉的进程地址空间,该空间是大小为4G的线性虚拟空间,用于看到和接触的都是虚拟地址(逻辑地址),无法看到实际的物理内存地址。利用这种虚拟地址不但能起到保护操作系统的效果(用户不能直接访问物理内存),而且更重要的是用户程序可使用比实际物理内存更大的地址空间。

Linux将4G的虚拟地址空间划分为两个部分——用户空间与内核空间。用户空间从0-3G(0XC0000000),内核空间从3G到4G。用户进程通常情况下只能访问用户空间的虚拟地址,不能访问内核空间虚拟地址。例外的情况是用户进程通过系统调用访问内核空间。

进程空间:

用户空间对应进程,所以每当进程切换,用户空间就会跟着变化;而内核空间是由内核负责映射,它不会跟着进程改变,是固定的。内核空间地址有自己对应的页表,用户进程各自有不同的页表。每个进程的用户空间都是完全独立、互不相干的。

创建进程fork()、程序载入()、动态内存分配malloc()等进程相关操作都需要分配内存给进程。这时进程申请和获得的不是物理地址,仅仅是虚拟地址。

实际的物理内存只有当进程真的去访问新获取的虚拟地址时,才会由“请页机制”产生“缺页”异常,从而进入分配实际页框的程序。该异常是虚拟内存机制赖以存在的基本保证——它会告诉内核去为进程分配物理页,并建立对应的页表,这之后虚拟地址才实实在在地映射到了物理地址上。

Linux内存管理——地址类型

物理地址:

物理地址是指CPU放到地址总线上,用于寻找物理上存在的存储单元的地址,简单理解为地址总线上使用的地址。

逻辑地址:

硬件平台段式管理转换前的地址。

线性地址:

硬件平台页式管理转换前的地址,又名虚拟地址。

地址关系:

程序代码产生出的是逻辑地址,CPU要将一个逻辑地址转换为物理地址,需要两步:首先CPU利用段式内存管理单元,将逻辑地址转换成线性地址,再利用页式管理单元,把线性地址最终转换为物理地址。

Linux内存管理——段式管理、页式管理

段式管理(16位CPU):

 计算机的内存是以“字节”为最小单位进行线性编址的,字节也是80X86对内存管理的最小元素。16位CPU内部拥有20根地址线,它的寻址范围就是2的20次方,也就是1M的内存空间。但是16位CPU用于存储地址单元额寄存器(IP,SP....)只有16位,因此只能访问65526个存储单元,64K。

为了能够够访问1M的内存空间,CPU就采用了内存分段的管理模式,并在CPU内部加入了段寄存器。

16位CPU把1M内存空间分为若干个逻辑段,每个逻辑段的要求如下:

1)逻辑段的起始地址(段地址)必须是16的倍数,即最后4个二进制必须全为0.

2)逻辑段的最大容量为64K,这是由16位寄存器的寻址空间所决定。

物理地址的形成方式:

由于段地址必须是16的倍数,所以值的一般形式为XXXX0H,即前16位二进制位是变化的,后四位是固定的0,鉴于段地址的这种特性,可以只保存前16位二进制来保存整个段基地址,所以每次使用时要用段寄存器左移补4个0(乘以16)来得到实际的段地址。

在确定了某个存储单元所属的段后,只是知道该存储单元所属的方位(段地址->段地址—+65536),如果想确定内存的具体位置,还必须知道该单元距离该段基地址有多远(段内偏移)。有了段地址和偏移量,就可以唯一的确定内存单元在寄存器中的具体位置。

逻辑地址由两部分构成,表示为:

[段标识符:段内偏移量]

由逻辑地址得到物理地址(PA - Physical Address)的公式为:

PA=段寄存器的值*16+偏移量

段式管理(32位CPU)

32位PC采用了两种不同的工作方式:实模式和保护模式。

1)实模式:

在实模式下,32位微机的内存管理与16位微机是相一致的。

2)保护模式

段基地址可以达到长达32位,每个段的最大容量可达4G,段寄存器的值是表示段地址的“选择器”(Selector),用该“选择器”可以从内存中得到一个32位的段地址,存储单元的物理地址就是该段地址加上段内偏移量,这与16位微机的物理地址计算方式完全不容。

分页管理:

 CPU的页式内存管理单元,负责把一个线性地址,最终翻译为一个物理地址。从管理和效率的角度出发,线性地址被分为固定长度为单位的组,称为页(page),例如一个32位的机器,线性地址最大可为4G,可以用4KB为一个页进行划分,这样整个线性地址就可以被划分为一个tatol_page[2^20]的大数组,共有2的20次次方个页。这个大数组我们称之为页目录。目录中的每一个目录项,就是一个地址——对应的页的地址。

另一类“页”,称之为物理页,或者是页框、页帧。分页单元把所有的物理内存也划分为固定长度的管理单位,它的长度一般与线性地址页相同的。

这里注意到,这个total_page数组有2^20个成员,每个成员是一个地址(32位机,一个地址也就是4字节),那么这个数组,要占去4MB的内存空间。为了节省空间,引入了一个二级管理模式的机器来组织分页单元。

Linux内存管理——段式管理、页式管理 - 六月的水 - 六月的水的博客

 

Linux内存管理中,段的基地址全部为0X0000000,由此可以得出,每个段的逻辑地址空间范围为0-4GB。因为每个段的基地址为0,因此,逻辑地址到线性地址映射保持不变,也就是说,偏移量就是线性地址,在linux中所提到的逻辑地址(或虚拟地址)和线性地址指的也就是同一地址。Linux巧妙地把段机制给绕过去而完全利用了分页机制。

内核为MMU设置好所有的页面表,MMU用线性地址中的PT字段作为下标找到相应的表项PTE,该表项中存放的就是物理页面的指针。

线性地址中的最后位段为物理页面内的相对偏移量,MMU将此偏移与目标页面的起始地址相加就得到相应的物理地址。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值