衡阳网站优化教程,android 移动网站开发,微商平台怎么注册,网站建设备案书模板内存管理1.虚拟内存2.内存分段3.内存分页多级页表TLB1.虚拟内存
众所周知:单片机是没有操作系统的,所以单片机的CPU是直接操作内存的物理地址(physical address,PA) 在这种情况下,程序内存中是无法同时运行多个程序。例如第一个程序在10位置的位置存放立一个数值#xff0c;…
内存管理1.虚拟内存2.内存分段3.内存分页多级页表TLB1.虚拟内存
众所周知:单片机是没有操作系统的,所以单片机的CPU是直接操作内存的物理地址(physical address,PA) 在这种情况下,程序内存中是无法同时运行多个程序。例如第一个程序在10位置的位置存放立一个数值当运行第二个程序时会擦掉第一个程序在10位置上存储的数值。因此单片机是无法同时运行多个程序的。 但我们用的电脑几乎都可以同时运行多个个程序这是如何实现的呢。
由单片机的示例可知两个程序都使用了绝对物理地址那么这就是我们需要解决的问题。
我们可以使用虚拟寻址的方法解决即让操作系统为每个进程分配独立的一套虚拟地址每个程序都有互不干涉。但每个进程都不能直接操作物理内存地址。那么虚拟地址如何与物理地址相对应呢这就需要操作系统出手了
操作系统会提供一种机制将不同进程的虚拟地址和不同内存的物理地址映射起来
如上图程序访问虚拟地址的时候由操作系统将其转换为不同的物理地址这样不同的程序运行时写入的物理地址是不同的这样就不会产生冲突了。
这就引出了两种地址的概念
程序使用的地址叫做虚拟内存地址virtual memory address实际存在硬件里面的空间地址叫物理内存地址physical memory address
操作系统引入虚拟内存进程持有的虚拟地址会通过CPU芯片中的内存管理单元MMU1 的映射关系 那么操作系统是如何管理虚拟地址与物理地址之间的关系呢
内存分段内存分页 内存分段的提出比较早所以我们先看看内存分段。
2.内存分段
程序是由若干逻辑分段组成的如可有代码分段数据分段栈段堆段组成。不同的段是有不同的属性的所以就用分段segmentation的形式把这些段分离出来。
分段机制下虚拟地址和物理地址是如何映射的分段机制下的虚拟地址由两部分组成段选择子 和 段内偏移量。
段选择子就保存在段寄存器里面。段选择子里面最重要的是段号用作段表的索引。段表里面保存的是这个段的基地址、段的界限和特权等级等。虚拟地址中的段内偏移量应该位于 0 和段界限之间如果段内偏移量是合法的就将段的基地址加上段偏移量这样就得到了该段全部的地址范围。
我们知道了虚拟地址是通过段表与物理地址进行映射的分段机制会将程序的虚拟地址分成4个段每个段在段表中有一个项在这一项中找到段的基地址再加上段内偏移量这样就得到段的物理地址了。 假如我们要访问段 2 中偏移量为3000 的虚拟地址我们可以计算出物理地址为 30003000 6000 那么物理地址 3000~6000 就是段 3 对应的物理地址范围。
分段的方法虽然很好但是也有两个缺点
第一个就是内存碎片的问题第二个就是内存交换效率低的问题
我们接下来讨论为什么会有这两个问题。 产生内存碎片的的原因 我们来看个例子。假设有 1G 的物理内存用户执行了多个程序其中
游戏占了 512 MB 内存浏览器占了 128 MB 内存音乐占了 256 MB 内存
这个时候如果我们关闭浏览器则空闲内存还有 1024 - 512 - 256 256 MB。
如果这个 256 MB 内存不是连续的 被分成两个128 MB 内存这样就会导致无法打开一个 200 MB 内存的程序。 这里的内存碎片主要有两部分
外部内存碎片也就是产生了多个不连续的小物理内存导致新的程序无法被装载内部内存碎片程序所有的内存都被装载到了物理内存但是这个程序有部分的内存可能并不是很常使用这也会导致内存的浪费
针对以上两种内存碎片解决方式有所不同。
解决外部内存碎片的方式j就是内存交换
我们可以把音乐程序占用256 MB 内存写到硬盘上然后再从硬盘上加载到内存中但我们不能加载回原来的位置而是加载到 512 MB 内存的后面这样就可以空出 258 MB 内存 这样就满足了 200 MB 内存的要求。
在Linux系统中这个内存交换空间就是我们常其实不常看到的swap 空间这块空间是从硬盘中划分出来的专门用于内存交换。
但是这就引出了第二个问题内存交换效率低
因为硬盘的访问速度要比内存慢多了
3.内存分页
分段的好处就是能够产生连续的内存空间但是会出现内存碎片和内存交换速率低的问题
要解决这些问题那么就要想出能少出现一些内存碎片的方法。另外当需要进行内存交换是让需要交换写入或从磁盘装载的数据更少一点这样就解决问题了 。这个办法就是内存分页 内存分页是吧整个虚拟和物理内存空间切成一段段固定尺寸的大小
这样一个连续并且尺寸固定的内存空间我们叫页。在Linux下每一页的大小为 4 KB。 虚拟地址与物理地址之间通过页表2进行映射如下图 页表实际上存储在CPU的内存管理单元(MMU) 中于是CPU可以通过MMU找出实际要访问的物理内存地址。
而当进程访问的虚拟内存空间在页表中查询不到时系统会产生一个缺页异常,j进入系统内核空间分配物理内存、更新进程页表最后再返回用户空间恢复进程运行。
分页是怎么解决分段的内存碎片、内存交换效率低的问题 由于内存空间都是预先划分好的也就不会像分段会产生间隙非常小的内存这正是分段会产生内存碎片的原因。**而采用分页那么释放内存都是以页为单位释放的就不会产生无法给进程使用的小内存。
如果内存不够用了那么操作系统会将其他正在运行的进程的【最近没有使用内存页面】给释放掉也就是暂时写在硬盘上成为换出空间swap up。一旦需要的时候在加载进来称为换入。所以一次性写入磁盘的也只有少数的一个页或者几个页不会花太多时间内存交换的效率就此相对比较高 进一步讲分页的方式使得我们在加载程序的时候不需要一次性都把程序加载到物理内存中。我们完全可以在虚拟内存的页和物理内存的页进行映射后并不需要真的把页加载到物理内存中而只是在需要的时候将需要的虚拟内存中的数据或指令加载到物理内存中
分页机制下虚拟地址和物理地址是如何映射的
在分页的机制下虚拟地址分为两部分页号和页内偏移。页号作为页表的索引页表包含虚拟内存页每页所在的物理内存的基地址这个基地址与页内偏移的组合就形成了物理内存的地址见下图 总结一下对于每个内存地址的转换有三个步骤
虚拟内存地址切分成页号和偏移量根据页号从页表里面查询对应的物理页号直接拿到物理页号加上前面的偏移量就得到了物理内存地址。 但是这种分页在实际操作中会有缺陷的。
简单的分页有什么缺陷呢
有空间上的缺陷
当操作系统运行非常多的的进程时那就意味着页表会非常的大。
至于为什么会非常大呢我就不写了嘿嘿嘿
这时就需要一个更高端的方式来解决简单的分页带来的问题了
多级页表
要解决上面的问题就需要采取多级页表的解决方案
假设有100多万个【页表项】的单级页表再分页将页表一级页表分为1024个页表二级页表每个表二级页表中包含1024个页表项形成二级分页
如下图所示 这是你就有可能问了整这么·多的表那所占的空间不就更大了吗
其实不是这样的我们应该换一个角度去看问题记得计算机组成原理里面无处不在的局部性原理么
每个进程都有 4GB 的虚拟地址空间而显然对于大多数程序来说其使用到的空间远未达到 4GB因为会存在部分对应的页表项都是空的根本没有分配对于已分配的页表项如果存在最近一定时间未访问的页表在物理内存紧张的情况下操作系统会将页面换出到硬盘也就是说不会占用物理内存。
如果使用了二级分页一级页表就可以覆盖整个 4GB 虚拟地址空间但如果某个一级页表的页表项没有被用到也就不需要创建这个页表项对应的二级页表了即可以在需要时才创建二级页表。 那么为什么不分级的页表就做不到这样节约内存呢我们从页表的性质来看保存在内存中的页表承担的职责是将虚拟地址翻译成物理地址。假如虚拟地址在页表中找不到对应的页表项计算机系统就不能工作了。所以页表一定要覆盖全部虚拟地址空间不分级的页表就需要有 100 多万个页表项来映射而二级分页则只需要 1024 个页表项此时一级页表覆盖到了全部虚拟地址空间二级页表在需要时创建。
我们把二级分页再推广到多级页表就会发现页表占用的内存空间更少了这一切都要归功于对局部性原理的充分应用。
TLB
多级页表虽然解决了空间上的问题但是虚拟地址到物理地址的转换就多了几道工序那么所花费的时间就更长了
程序是有局限性的即在某一段时间内整个程序的执行仅限于程序中的某一部分。相应的执行所访问的存储空间页局限于某个内存区域。 我们就可以利用这一特性把最常访问的几个表项存储到访问速度更快的硬件于是计算机科学家们就在 CPU 芯片中加入了一个专门存放程序最常访问的页表项的 Cache这个Cache 就是 TLB Translation lookaside buffer通常称为页表缓存转址旁路缓存快表等。 在cpu 芯片里面封装了内存管理的单元芯片它用来完成地址转换和与TLB的交互。 在CPU 寻址时会先查找TLB 如果没找到在查找常规表。 CPU上的芯片叫做内存管理单元memory management unitMMU 的专用硬件利用存放在主存中的查询表来动态翻译虚拟地址该表的内存由操作系统管理 ↩︎ 页表将虚拟页映射到物理页。每次地址翻译硬件将一个虚拟地址装转换为物理地址时都会读取页表。操作系统负责维护页表的内容以及在磁盘与DRAM之间来回传页 ↩︎