文章目录

  • 1、虚拟内存是什么,为什么要有虚拟内存
  • 2、内存分段
  • 3、内存分页
    • 3.1 TLB
    • 3.2 TTW
    • 3.3 多级页表
  • 4、linux中的分页机制:
    • 4.1 线性映射与非线性映射
      • x86内核空间划分:
      • arm内核空间划分:
    • 4.2 buddy算法
  • 5、内存保护:
  • 6、总结

1、虚拟内存是什么,为什么要有虚拟内存

如果进程直接访问物理内存,那么不同进程是能够直接访问其它进程的内存空间的,这种行为不安全。
为保证不同进程之间内存空间不可见,实现进程内存隔离,需要有一种机制,能够将不同进程的内存物理空间实现隔离。

这个机制就是 虚拟内存,为不同的进程分配各自的虚拟地址,这些虚拟地址落在不同的物理地址,实现了不同进程使用的地址隔离。而虚拟地址怎么映射到不同的物理地址,上层程序不需要关心。对进程来讲,他感觉自己能够访问到完整的整个内存空间。

虚拟地址与不同的物理地址映射的机制,由操作系统提供。程序访问虚拟地址的时候,由操作系统将虚拟地址转换不同的物理地址。

处理器中的内存管理单元MMU)负责管理这种映射关系。提供虚拟地址和物理地址的映射、内存访问权限保护和cache缓存控制等硬件支持。

主要有两种方式,分别是内存分段和内存分页,分段是比较早提出的,我们先来看看内存分段。

2、内存分段

最初是为了解决8086 16位处理器寻址20内存空间的问题。8086上涉及4个寄存器,

CS(Code Segment):代码段寄存器;
DS(Data Segment):数据段寄存器;
SS(Stack Segment):堆栈段寄存器;
ES(Extra Segment):附加段寄存器。

每个程序在执行前,都要决定程序的代码段、数据段、堆栈段需要用到内存的哪些位置,并设定CS DS SS寄存器来指定这些位置。
将程序所需要的内存空间大小的虚拟空间,通过映射机制映射到某个物理地址空间(映射的操作由硬件完成)。

分段系统的逻辑地址结构由段号(段名)和段内地址(段内偏移量)所组成。

缺点:
1、分段内存映射单位是整个程序,占用内存空间大;如果内存空间不够,还要将整个程序所需要的空间换入换出到磁盘空间,这个动作造成大量磁盘访问,严重降低程序运行速度;事实上,大多程序运行时所需数据只是很小一部分,不需要整体的写入和写出。
2、内存碎片,同样会导致内存swap。

3、内存分页

内存分页能够解决分段的缺点。

分页模式下,程序不是一次性全部加载到物理内存中,暂时没用到的数据和代码保存在磁盘中,程序运行需要用到这些数据时,再从磁盘中加载到内存中。这样不会产生大量的磁盘写入写出操作。

内存分页就是将物理地址分成一页一页固定尺寸的大小。在linux下,每页的大小是4KB。
虚拟地址到物理地址的映射关系,由页表来完成。页表存储在内存中,MMU通过查询页表,负责将虚拟地址转换为物理地址。
分页机制下,虚拟地址分为两部分,页号和页内偏移(简单来讲,实际还有很多标志位)。页号作为页表的索引,通过页号查询到页表中存储的页的物理内存起始地址,页的物理地址加上页内偏移,就组成了实际物理地址。

3.1 TLB

上述内存分页的转换表保存在内存中。
为加快地址转换速度,减少地址转换的时钟周期,CPU会维护一个转换旁路缓存(Translation Lookaside Buffer)TLB。
TLB是MMU的核心部件,缓存了少量的虚拟地址与物理地址的转换关系,是一个保存转换表的cache。也被称为快表。
TLB添加一项ASID(Address Space ID)的匹配。ASID就类似进程ID一样,用来区分不同进程的TLB表项。进程ID和每个进程的ASID一般是不相等的,每创建一个新进程,就为之分配一个新的ASID。当ASID分配完后,flush所有TLB,重新分配ASID。
内核空间是所有进程共享,进程A切换进程B的时候,如果进程B访问的地址位于内核空间,完全可以使用进程A缓存的TLB。但是现在由于ASID不一样,导致TLB miss。我们针对内核空间这种全局共享的映射关系称之为global映射。

3.2 TTW

转换表漫游(Translation Table walk)TTW。当在TLB中没有查询到对应的地址转换关系条目时,需要通过查询内存中转换表来获取映射关系。这个动作叫做转换表漫游。

3.3 多级页表

每个进程都要单独维护一个页表,多级页表是为了解决什么问题的呢?
先举个例子,假设虚拟地址空间大小为4G,在linux下,每页的大小是4k,那么页表项就是2^20个,如果每个页表占用4B,那么整个页表占用4M内存。那么问题来了
1、每个进程都要维护一个页表,也就是每个进程都要占用4M内存大小,整个开销是很大的。那么多级页表能解决这个问题吗,是的!
如上所说,使用一级页表,每个进程占用4M内存大小。假设使用2级页表,将2^20个一次页表分成1024组,每组包含1024个页表,如此形成二级分页。
也就是32位地址,10位表示二级页号,10位表示1级页号,12位表示页内偏移。寻址时先寻址二级页,在二级页表查找到一级页并索引到实际物理地址。
这时候会发现,采用二级页表,内存需要维护4k二级页表+4M一级页表,内存占用不是更大了么?不是的!
计算机的局部性原理,每个进程都分配了4G的虚拟地址空间,但是大部分进程使用的空间都远未达到4G。因此大部分二级页表下的一级页表项是空的,不需要占用空间
所以说多级页表可以节省内存
2、使用一级页表的话,每个进程的页表项需要在内存中连续存储,这个对内存管理是增加很大开销的。尤其是内存碎片多、内存空间不足等情况下。下面看看多级页表为什么能解决这个问题:
多级页表实际上是对每个一级页表项增加了索引,可以通过上层页表索引到下层页表。因此只需要顶层页表在物理内存中连续、低层不同页表不需要连续 只有页表中的项连续就OK了,最底层页表项不需要在物理空间上连续。

4、linux中的分页机制:

linux采用四级分页机制,即

页全局目录(Page Global Directory)
页上级目录(Page Upper Directory)
页中间目录(Page Middle Directory)
页表(Page Table)

对于不同的物理架构,这个分页机制也是兼容的。例如对于i386而言,仅采用二级页表,即页上层目录和页中层目录长度为0。

linux主要使用分页机制管理内存,而使用了较少的分段机制。

给每一个进程分配一块不同的物理地址空间,这确保了可以有效地防止寻址错误。
允许将某页内存存在磁盘上。

在硬件上会有一个叫做页表基地址寄存器,它存储PGD页表的首地址。MMU就是根据页表基地址寄存器从PGD页表一路查到PTE,最终找到物理地址(PTE页表中存储物理地址)。
CR3含有存放页目录表页面的物理地址,因此CR3也被称为PDBR。CR3寄存器的改变与操作系统的关联主要是由于进程切换,每当进程切换时,CR3的内容需要被操作系统修改

4.1 线性映射与非线性映射

linux在内核空间执行内存管理,实际上给内核分配的虚拟地址空间是1G,如果实际物理空间小于1G,可直接将物理空间线性映射到内核空间,提高访问速度。
但是如果物理空间大于1G,内核无法在1G虚拟内存空间直接线性映射高于1G的物理地址空间,这就需要非线性映射,通常不映射,只有使用时候才映射,kmap等。
线性空间最大只能896M.

x86内核空间划分:

保留区
专用页面映射区
高端内存映射区
vmalloc虚拟内存分配区
物理内存映射区(内部最底层划分DMA区)

实际上,物理内存的0~896M线性映射到内核空间的物理内存映射区;
物理内存大于896M的空间,由内核空间的高端内存映射区管理。

arm内核空间划分:

向量表
vmalloc
DMA+常规区域内存映射
高端内存映射区
内核模块

4.2 buddy算法

DMA、常规内存、高端内存这三个区域都用buddy算法管理,将空闲页面以2的n次方为单位进行管理,因此,linux最底层内存申请都是以2n为单位的。buddy算法最主要优点是避免了外部碎片,任何时候,区域中的空闲内存都能以2n进行拆分或合并。
/proc/buddyinfo会显示每个区域中2^n的空闲页面的分布情况:

Node 0, zone      DMA      3      3      1      1      1      0      1      0      0      0      0
Node 0, zone    DMA32      5      6      6      8      7      6      4      6      8      9    325
Node 0, zone   Normal   4795   4161   2183    639    301     84     25      9     13      4   2711

5、内存保护:

1、虚拟内存就是一种内存保护机制:实现不同进程访问的物理内存隔离。
2、同一任务内,定义四种不同的特权级别,用于限制对内存的访问权限。特权级分为4级,特权级0、1、2、3。
CS代码段寄存器,一般用于存放代码,它就含有一个特殊的两位字段,用以标识CPU当前的特权级别(CurrentPrivilegeLevel,CPL),值为0代表最高优先级,值为3代表最低优先级。在linux和windows均只使用特权级0和特权级3。分别称为内核态和用户态。

例如:
1、页目录项中的字段 User/Supervisor标志 ,表示了访问页或页表所需要的的特权级。若这个标志为0,只有当CPL小于3(这意味着对于Linux而言,处理器处于内核态)时才能对页寻址;若该标志为1,则总能对页寻址。
2、与段的3种存取权限(读,写,执行)不同的是,页的存取权限只有两种(读,写)。如果页目录项或页表项的Read/Write标志等于0,说明相应的页表或页是只读的,否则是可读写的。

6、总结

文章讲述了计算机内存管理之虚拟内存,在此再次总结:

为了保证进程之间的内存地址相互隔离,于是操作系统就为每个进程独立分配一套虚拟地址空间,每个程序只关心自己的虚拟地址就可以,实际上大家的虚拟地址都是一样的,但分布到物理地址内存是不一样的。作为程序,也不用关心物理地址的事情。

每个进程都有自己的虚拟空间,而物理内存只有一个,所以当启用了大量的进程,物理内存必然会很紧张,于是操作系统会通过内存交换技术,把不常使用的内存暂时存放到硬盘(换出),在需要的时候再装载回物理内存(换入)。

那既然有了虚拟地址空间,那必然要把虚拟地址「映射」到物理地址,这个事情通常由操作系统来维护。

那么对于虚拟地址与物理地址的映射关系,可以有分段和分页的方式,同时两者结合都是可以的。

内存分段是根据程序的逻辑角度,分成了栈段、堆段、数据段、代码段等,这样可以分离出不同属性的段,同时是一块连续的空间。但是每个段的大小都不是统一的,这就会导致内存碎片和内存交换效率低的问题。

于是,就出现了内存分页,把虚拟空间和物理空间分成大小固定的页,如在 Linux 系统中,每一页的大小为 4KB。由于分了页后,就不会产生细小的内存碎片。同时在内存交换的时候,写入硬盘也就一个页或几个页,这就大大提高了内存交换的效率。

再来,为了解决简单分页产生的页表过大的问题,就有了多级页表,它解决了空间上的问题,但这就会导致 CPU 在寻址的过程中,需要有很多层表参与,加大了时间上的开销。于是根据程序的局部性原理,在 CPU 芯片中加入了TLB,负责缓存最近常被访问的页表项,大大提高了地址的转换速度。

Linux 系统主要采用了分页管理,但是由于 Intel 处理器的发展史,Linux 系统无法避免分段管理。于是 Linux 就把所有段的基地址设为 0,也就意味着所有程序的地址空间都是线性地址空间(虚拟地址),相当于屏蔽了 CPU 逻辑地址的概念,所以段只被用于访问控制和内存保护。

内存完整性:由于虚拟内存到物理内存的映射,每个进程都认为自己占用了4G完整内存,并认为内存是连续的,每个进程都认为自己获取的内存是一块连续的地址,故各进程不需要关心内存问题。

安全性:通过虚拟内存的映射,实现各进程间访问的物理内存的隔离;另外,在虚拟内存映射到物理内存的查表过程中,页表中还记录了内存的访问权限,实现了内存的访问权限控制。

内存swap:linux 系统引入swap分区,在可用物理内存不足时,将暂时不用的内存数据拷贝到存储介质(磁盘)上,让出内存让出给优先进程使用,进程使用完,再将原数据从磁盘加载到内存中。通过这种swap技术,linux系统可以让进程有“无限”内存可以用。

计算机内存管理之虚拟内存相关推荐

  1. iOS 的内存管理和虚拟内存机制具体是怎么运作的?

    iOS 的内存管理和虚拟内存机制具体是怎么运作的? 众所周知,iOS 设备的内存普遍较小.但就最终用户体验而言,流畅舒服.想知道虚拟内存在其中是否发挥了作用? 3 条评论 分享 按投票排序按时间排序 ...

  2. 计算机内存 管理,试析计算机内存的优化及管理

    摘 要:现如今,计算机设备已经成为人们生活中必不可少的必需品.计算机设备的构成部分主要包括硬件设备和软件设备两大类.计算机硬件系统包含的内容相对较多,其中典型性较强,重要性较大的就是内存.计算机设备研 ...

  3. 操作系统内存管理及虚拟内存技术

    一.内存管理 操作系统的内存管理主要负责内存的分配与回收(malloc 函数:申请内存,free 函数:释放内存),另外地址转换也就是将逻辑地址转换成相应的物理地址等功能也是操作系统内存管理做的事情. ...

  4. 剩余 大小 查看内存_计算机内存管理介绍

    作者:Adam原文:https://www.cnblogs.com/adamwong/p/10678015.html 计算机操作系统内存管理是十分重要的,因为其中涉及到很多设计很多算法.<深入理 ...

  5. C++内存管理,虚拟内存

    操作系统内存管理 概念: 内存管理就是操作系统对内存的划分和动态分配.操作系统内存管理包括物理内存管理和虚拟内存管理.我们程序所使用的内存地址叫做虚拟内存地址,实际存在硬件里面的空间地址叫物理内存地址 ...

  6. 内存管理(四)——虚拟内存

    前言 上一篇介绍完了内存分页,接下来就是内存管理的重头戏--虚拟内存了. 在正式介绍虚拟内存之前,先简单地介绍一下相关技术的发展过程.虽然我们的物理内存相较于过去已经变大了很多,但是程序所要占用的内存 ...

  7. 操作系统内存管理之虚拟内存

    9.1 背景 虚拟地址空间:进程在内存中存放的逻辑视图.如图所示. 虚拟内存:是一种内存管理技术,它会使程序自己认为自己拥有一块很大且连续的内存,然而,这个程序在内存中不是连续的,并且有些还会在磁盘上 ...

  8. win7总是显示计算机内存不足怎么办,虚拟内存不足,教您电脑提示虚拟内存不足怎么办...

    内存在计算机中的作用很大,电脑中所有运行的程序都需要经过内存来执行,而当人们在运行一些大型的软件,或者是刚刚退出游戏的时候经常会提示"你的虚拟内存过低"的提示,下面,小编跟大家讲解 ...

  9. 全面介绍Windows内存管理机制及C++内存分配实例(三):虚拟内存

    本文背景: 在编程中,很多Windows或C++的内存函数不知道有什么区别,更别谈有效使用:根本的原因是,没有清楚的理解操作系统的内存管理机制,本文企图通过简单的总结描述,结合实例来阐明这个机制. 本 ...

最新文章

  1. C#制作图片压缩工具
  2. javaweb里边的重定向与转发的区别
  3. Hadoop 安装详解--新手必备
  4. centos 安装配置ftp服务器
  5. Android学习笔记篇1. 从按钮的点击事件开始
  6. MySQL(7)索引
  7. 15.2. important
  8. Vaadin介绍与开发练习之二(创建第一个Vaadin类)
  9. 白板推导系列Pytorch-隐马尔可夫模型-学习问题
  10. springboot_poi思路
  11. 使用Asp.net MVC源代码调试你的应用程序
  12. rpa打开浏览器_免费开源RPA财务机器人Taskt入门
  13. 项目中的通用查询参数类,它体现了项目架构的大局观
  14. cad字体安装_为什么CAD图纸打开后会显示很多问号“???”,该怎么解决
  15. linux 中gnu的含义是,GNU是什么意思
  16. 胜利vs50线跟vs100线区别_BV线与BVR电线的区别
  17. C语言实现【小游戏——飞机大战】
  18. #边学边记 必修4 高项:对事的管理 第1章 项目立项管理 之 立项管理内容
  19. 《因子投资 - 方法与实践》新书上市
  20. 制导武器的分布式半实物仿真系统研究

热门文章

  1. 超实用的 IPTV 管理工具,xTeVe 助你定制专属电视频道。
  2. 初中学历程序员面试被HR吐槽,初中学历还有要月薪3万5,到底是学历重要还是能力重要?...
  3. 路由器级联方式(二级路由为例)
  4. unity导入模型昏暗(对比度低)解决办法
  5. YTU 3921 游戏
  6. linux下hwclock及clock命令详解
  7. 交换机与路由器技术-05-路由器工作原理
  8. WinDbg非常简单的调试dmp文件
  9. fone喜获“2018中国企业绩效管理信息化最佳产品奖”
  10. 使用openssl命令 生成指定有效时间的ssl证书,cer格式