Linux内存管理3---分页机制
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---分页机制的更多相关文章
- Linux内存寻址之分页机制
在上一篇文章Linux内存寻址之分段机制中,我们了解逻辑地址通过分段机制转换为线性地址的过程.下面,我们就来看看更加重要和复杂的分页机制. 分页机制在段机制之后进行,以完成线性—物理地址的转换过程.段 ...
- [转帖]Linux分页机制之概述--Linux内存管理(六)
Linux分页机制之概述--Linux内存管理(六) 2016年09月01日 19:46:08 JeanCheng 阅读数:5491 标签: linuxkernel内存管理分页架构更多 个人分类: ┈ ...
- Linux内存管理2---段机制
1.前言 本文所述关于内存管理的系列文章主要是对陈莉君老师所讲述的内存管理知识讲座的整理. 本讲座主要分三个主题展开对内存管理进行讲解:内存管理的硬件基础.虚拟地址空间的管理.物理地址空间的管理. 本 ...
- 深入理解 Linux 内存管理
1. 内存地址 以Intel的中央处理器为例,Linux 32位的系统中.物理内存的基本单位是字节(Byte),1个字节有8个二进制位. 每一个内存地址指向一个字节,内存地址加1后得到下一个字节的地址 ...
- [转帖]Linux分页机制之分页机制的演变--Linux内存管理(七)
Linux分页机制之分页机制的演变--Linux内存管理(七) 2016年09月01日 20:01:31 JeanCheng 阅读数:4543 https://blog.csdn.net/gatiem ...
- Linux内存管理解析(一) : 分段与分页机制
背景 : 在此文章里会从分页分段机制去解析Linux内存管理系统如何工作的,由于Linux内存管理过于复杂而本人能力有限.会尽量将自己总结归纳的部分写清晰. 从实模式到保护模式的寻址方式的不同 : 1 ...
- 浅谈Linux内存管理机制
经常遇到一些刚接触Linux的新手会问内存占用怎么那么多?在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,在这 ...
- 了解linux内存管理机制(转)
今天了解了下linux内存管理机制,在这里记录下,原文在这里http://ixdba.blog.51cto.com/2895551/541355 根据自己的理解画了张图: 下面是转载的内容: 一 物理 ...
- 【转载】Linux 内存管理机制
在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,主要特点是,无论物理内存有多大,Linux 都将其充份利用,将 ...
随机推荐
- Twitter数据挖掘:如何使用Python分析大数据 (3)
让我们来拉取Twitter账号@NyTimes的最近20条微博. 我们可以创建变量来存放待拉取的微博数量(即count),以及待拉取的用户(即name).然后用这两个参数调用user_timeline ...
- Luogu 1314 【NOIP2011】聪明的质检员 (二分)
Luogu 1314 [NOIP2011]聪明的质检员 (二分) Description 小 T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有n个矿石,从 1 到n逐一编号,每个矿石都有 ...
- 百度地图手机端单触点单击和长按事件,解决部分手机(小米手机)地图单击事件失效,多触点、拖动依然触发长按的bug
/** * Author 岳晓 * * 对百度地图的事件扩展,目前扩展了fastclick和longclick, * 解决某些设备click不执行的问题 * 解决长按事件在拖动.多触点依然执行的bug ...
- 使用sass切图
明日复明日,明日何其多!我生待明日,万事成蹉跎!ruby挺可爱的.没有进入工程项目中使用sass. 尝试是一件快乐的事情.在页面中直接引进编译出来的css即可.
- Linux下编译安装Lnmp
1.安装nginx 下载链接http://nginx.org/en/download.html (1)下载,解压 wget http://nginx.org/download/nginx-1.15.8 ...
- Python基础学习(四)
菜鸟咀嚼python基础之继续. 一.返回函数 第三章已经简单操作了Python的高阶函数,目前继续练手函数作为返回值的特效:通常,高阶函数除了可以接收函数作为参数外,还可以把函数作为结果值返回. 案 ...
- zTree重命名节点时,操作的那个dom(类似input框那个)怎么写
<script type="text/javascript"> //tree的编辑节点的方法 ztree.editName(nodeNew[0]); /// $(&qu ...
- GO语言的进阶之路-go的程序结构以及包简介
GO语言的进阶之路-go的程序结构以及包简介 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.编辑,编译和运行 A,编辑 Go程序使用UTF-8编码的纯Unicode文本编写.大 ...
- parted分区工具用法
parted分区工具用法 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 随着生产环境中数据量的增大,我们对硬盘的容量也有很大的需求,当硬盘的容量大于2T(工业上的最大磁盘2.2TB ...
- nginx的负载均衡配置,常用策略
场景:nginx是一款非常优秀的负载均衡服务器,小巧而且性能强悍,中小型企业的首选. 下面介绍nginx的负载均衡的几种常见的配置以及优缺点 第一种:轮询(默认) 优点:实现简单 缺点:不考虑每台服务 ...





