1.前言

本文所述关于内存管理的系列文章主要是对陈莉君老师所讲述的内存管理知识讲座的整理。

本讲座主要分三个主题展开对内存管理进行讲解:内存管理的硬件基础、虚拟地址空间的管理、物理地址空间的管理.

本文将主要以X86架构为例来介绍Linux内存管理的分页机制。

2.分页机制

  • 页(Page)

将线性地址空间划分成若干大小相等的片,称为页

  • 页框(Page Frame)

物理地址空间划分成与页大小相等的若干存储块,称为页框

图 线性地址空间与物理地址空间的映射

上图说明线性地址空间是连续的(如程序经过编译链接后是连续的线性地址),而物理地址空间可能是不连续的。

  • 页表

页表是把线性地址映射到物理地址的一种数据结构

  • 页表项内容

1.物理页面的起始地址;

2.该页的属性,表示页的特性,比如该页是否在内存,是否可以被读出或写入,具体的属性位如下:

(1) 第0位是P(Present),如果P=1,表示页装入到内存中,如果P=0,表示不在内存中。

  (2) 第1位是R/W(Read/Write),第2位是U/S(User/Supervisor)位,这两位为页表或页提供硬件保护。

  (3) 第3位是PWT(PageWrite-Through)位,表示是否采用写透方式,写透方式就是既写内存(RAM)也写高速缓存,该位为1表示采用写透方式

  (4) 第4位是PCD(PageCache Disable)位,表示是否启用高速缓存,该位为1表示启用高速缓存。

  (5) 第5位是访问位,当对相应的物理页面进行访问时,该位置1。

  (6) 第7位是PageSize标志,只适用于页目录项。如果置为1,页目录项指的是4MB的页

  (7) 第9~11位由操作系统专用,Linux也没有做特殊之用。

  • 两级页表

图 两级页表

所谓两级页表就是对页表再进行分页。第一级称为页目录,其中存放的是关于页表的信息,第二级称为页表

页目录的起始地址存放在CR3中的高20位,因此跟踪一个进程的时候,拿到CR3就等于拿到了进程的根:-D

线性地址的最高10位(即22位~ 31位)用来产生第一级的索引,线性地址的中间10位(即21位~12位)对物理页面进行索引,最低12位表示页内偏量

举例:4MB的页表按二级页表再次分页(4MB/4K)可以分为1K个页,同样对每个页的描述需要4个字节,于是可以算出页目录最多占用4KB个字节,正好是一个页

     页目录共有1K个表项,于是,线性地址的最高10位(即22位~ 31位)用来产生第一级的索引。

   两级表结构的第二级称为页表,每个页表也刚好存放在一个4K字节的页中,包含1K个表项,第二级页表由线性地址的中间10位(即21位~12位)进行索引

最低12位表示页内偏量。

  • 线性地址结构

图 线性地址结构

如上结构对应的伪代码:

图 线性地址结构对应的伪代码

  • 页表项结构

图 页表项结构

页目录和页表中的页表项结构都相同,都占用4个字节的长度

  • 硬件保护机制

(1)内核态或用户态对页面的访问权限

对于页表,页的保护是通过页表项的U/S标志和R/W标志来控制的,U/S为0,只有处于内核态的操作系统才能对此页或页表进行寻址,否则内核态和用户态均可寻址

(2)对页可读或可写

如果R/W为0,说明相应的页表或页是只读的,否则是可读写的

  • 线性地址到物理地址的转换

图  线性地址到物理地址的转换过程

(1)用32位线性地址的最高10位第31~22位作为页目录项的索引,将它乘以4,与CR3中的页目录的起始地址相加,获得相应目录项在内存的地址。

(2)从这个地址开始读取32位页目录项,取出其高20位,再给低12位补0,形成的32位就是页表在内存的起始地址。

(3)用32位线性地址中的第21~12位作为页表中页表项的索引,将它乘以4,与页表的起始地址相加,获得相应页表项在内存的地址。

(4)从这个地址开始读取32位页表项,取出其高20位,再将线性地址的第11~0位放在低12位,形成最终32位页面物理地址。

3. 分页示例

  • 假如操作系统给一个正在运行的进程分配的线性地址为:0x2000000~0x2003ffff,这个空间由64页组成

如上进程地址范围最高10位为页目录域0x80,指向进程页目录的128项,如果没有给这个进程分配其它的线性地址,则进程页目录表的其它1023项为0,

也就是这个进程在进程页目录表中只占用一项

图 只有一个目录项的页目录表和页表

  • 假设进程需要读取线性地址为0x20021406中的内容,这个地址由分页机制如何处理?

中间10位的值(即页表域的值)范围从0到0x03f,或十进制的从0到63。因而只有页表的前64个表项是有意义的,其余960表项填为0。

假设进程需要读线性地址0x20021406中的内容。这个地址由分页机制按下面的方法进行处理:

1.目录域的0x80用于选择页目录的第0x80目录项,此目录项指向页表。

2.页表域的第0x21项用于选择页表的第0x21表项,此表项指向页所对应的内存物理页面。

3.最后,偏移量0x406用于在目标物理页面中读偏移量为0x406中的字节。

注:如果页表第0x21表项的Present标志为0,说明此页还没有装入内存中;在这种情况下,分页机制在转换线性地址的同时产生一个缺页异常(参见内存管理一章)。

无论何时,当进程试图访问限定在0x20000000到0x2003ffff范围之外的线性地址时,都将产生一个缺页异常,因为这些页表项都填充了0,尤其是,它们的Present标志都为0。

4.页面高速缓存

图 页面高速缓存的作用

由于在分页情况下,页表是放在内存中的,这使CPU在每次存取一个数据时,都要至少两次访问内存,从而大大降低了访问速度

为了提高速度,在IA32中设置一个最近存取页的高速缓存硬件机制,它自动保持32项处理器最近使用的页表项,因此,可以覆盖128K字节的内存地址。

当访问线性地址空间的某个地址时,先检查对应的页表项是否在高速缓存中,如果在,就不必经过两级访问了,如果不在,再进行两级访问

平均来说,页面高速缓存大约有90%的命中率,也就是说每次访问存储器时,只有10%的情况必须访问两级分页机构。这就大大加快了速度,有些书上也把页面高速缓存叫做“联想存储器”或“转换旁视缓冲器(TLB)”。

5. Linux中的分页

  • Linux主要通过分页机制来实现虚拟存储器管理

原因如下:

Linux分段机制使得所有进程都使用相同的段寄存器值,所有进程使用相同的进程地址空间(0~4G)

Linux设计目标之一就是能够移植到大多数流行的处理器平台,但很多RISC处理器平台对分段机制支持有限

  • 为了保持可移植性,Linux采用三级分页模式而不是两级

图 LInux三级分页模式

注:尽管Linux采用的是三级分页模式,但我们的讨论还是以IA32的两级分页模式为主,因此,Linux忽略中间目录层

6.参考文献

[1] Linux内存管理讲座PPT-陈莉君

Linux内存管理3---分页机制的更多相关文章

  1. Linux内存寻址之分页机制

    在上一篇文章Linux内存寻址之分段机制中,我们了解逻辑地址通过分段机制转换为线性地址的过程.下面,我们就来看看更加重要和复杂的分页机制. 分页机制在段机制之后进行,以完成线性—物理地址的转换过程.段 ...

  2. [转帖]Linux分页机制之概述--Linux内存管理(六)

    Linux分页机制之概述--Linux内存管理(六) 2016年09月01日 19:46:08 JeanCheng 阅读数:5491 标签: linuxkernel内存管理分页架构更多 个人分类: ┈ ...

  3. Linux内存管理2---段机制

    1.前言 本文所述关于内存管理的系列文章主要是对陈莉君老师所讲述的内存管理知识讲座的整理. 本讲座主要分三个主题展开对内存管理进行讲解:内存管理的硬件基础.虚拟地址空间的管理.物理地址空间的管理. 本 ...

  4. 深入理解 Linux 内存管理

    1. 内存地址 以Intel的中央处理器为例,Linux 32位的系统中.物理内存的基本单位是字节(Byte),1个字节有8个二进制位. 每一个内存地址指向一个字节,内存地址加1后得到下一个字节的地址 ...

  5. [转帖]Linux分页机制之分页机制的演变--Linux内存管理(七)

    Linux分页机制之分页机制的演变--Linux内存管理(七) 2016年09月01日 20:01:31 JeanCheng 阅读数:4543 https://blog.csdn.net/gatiem ...

  6. Linux内存管理解析(一) : 分段与分页机制

    背景 : 在此文章里会从分页分段机制去解析Linux内存管理系统如何工作的,由于Linux内存管理过于复杂而本人能力有限.会尽量将自己总结归纳的部分写清晰. 从实模式到保护模式的寻址方式的不同 : 1 ...

  7. 浅谈Linux内存管理机制

    经常遇到一些刚接触Linux的新手会问内存占用怎么那么多?在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,在这 ...

  8. 了解linux内存管理机制(转)

    今天了解了下linux内存管理机制,在这里记录下,原文在这里http://ixdba.blog.51cto.com/2895551/541355 根据自己的理解画了张图: 下面是转载的内容: 一 物理 ...

  9. 【转载】Linux 内存管理机制

    在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,主要特点是,无论物理内存有多大,Linux 都将其充份利用,将 ...

随机推荐

  1. 集成源码深度剖析:Fescar x Spring Cloud

    Fescar 简介 常见的分布式事务方式有基于 2PC 的 XA (e.g. atomikos),从业务层入手的 TCC( e.g. byteTCC).事务消息 ( e.g. RocketMQ Hal ...

  2. 05 Zabbix triggers--action--event

    点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 05 Zabbix triggers--action--event 动作action: 在配置好监 ...

  3. 自学工业控制网络之路1.2-典型的现场总线介绍PROFIBUS

    返回 自学工业控制网络之路 自学工业控制网络之路1.2-典型的现场总线介绍PROFIBUS 目前看来,现场总线标准不会统一,多标准并存现象将会持续. 现场总线国家标准: 中国的DeviceNet和AS ...

  4. 3分钟上手log4net

    1. config里 <log4net> <appender name="ConsoleAppender" type="log4net.Appender ...

  5. 【转】JVM性能调优监控工具jps、jstack、jmap、jhat、jstat使用详解

    http://www.cnblogs.com/therunningfish/p/5524238.html JDK本身提供了很多方便的JVM性能调优监控工具,除了集成式的VisualVM和jConsol ...

  6. 结构体练习(C)

    结构体存储学生学号.姓名.总分,动态内存分配增加信息,然后排序 # include <stdio.h> # include <malloc.h> //# include < ...

  7. protobuf for java

    本文档为java编程人员使用protocol buffer提供了一个基本的介绍,通过一个简单的例程进行介绍.通过本文,你可以了解到如下信息: 1.在一个.proto文件中定义一个信息格式. 2.使用p ...

  8. A1047. Student List for Course

    Zhejiang University has 40000 students and provides 2500 courses. Now given the registered course li ...

  9. [luogu2657][windy数]

    luogu2657 思路 数位dp,记录下上个位置的数,如果当前的数字与上个数字的差值小于2,就不再转移.还是要注意排除前导0.在记忆化的时候,全都是前导0的情况不能记忆化. 代码 #include& ...

  10. 我们一起来详细的了解react的语法以及组件的使用方法

    jsx的介绍 React 使用 JSX 来替代常规的 JavaScript. JSX 是一个看起来很像 XML 的 JavaScript 语法扩展. jsx的优点 JSX 执行更快,因为它在编译为 J ...