操作系统--虚拟内存

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"一.前言","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在之前研究进程上下文切换和golang内存分配器的过程中,发现虚拟内存在其中都扮演着十分重要的角色,之前有学习和了解过虚拟内存,但是随着时间推移也只知道一个概念,现在想要带着问题去再学习一遍虚拟内存,希望这篇文章也能帮助你们更好的理解虚拟内存。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1.进程初始化的时候是如何分配的内存","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2.虚拟内存的具体工作流程","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"二.详细介绍","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2.1 简介","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"虚拟内存是一个抽象概念,它为每个进程提供了一个假象,即每个进程都在独占的使用主存。每个进程看到的内存都是一致的,称为「","attrs":{}},{"type":"text","marks":[{"type":"bgcolor","attrs":{"color":"#ffffff","name":"user"}}],"text":"虚拟地址空间」","attrs":{}},{"type":"text","text":"。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"虚拟内存主要提供了","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"三个能力","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"它将主存看做是一个存储在磁盘上的地址空间的高速缓存,在主存中只保存活动区域,并根据需要在磁盘和主存之间来回传送数据,通过这种方式高效使用了主存","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"它为每个进程提供了一致的地址空间,简化了内存管理","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"它保护了每个进程的地址空间不被其他进程破坏","attrs":{}}]}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2.2 如何工作","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/fa/fa83b9fc3be8370acf7eeb6e09dcd253.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如图所示,cpu通过生产一个虚拟地址4001访问主存,虚拟地址再mmu的转换下映射为物理地址中的2,通过讲翻译后的物理地址传给主存,主存读取从物理地址2开始的4个字节将其返回给cpu。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2.3 名词解释","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"知道了大概的处理流程,接下来讲解一下虚拟内存相关的几个名词。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.3.1 地址空间","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一个非负整数地址的有序集合,在带有虚拟内存的系统中,cpu从一个有N=2^n个地址的地址空间中生成虚拟地址,这个地址空间成为","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"虚拟地址空间","attrs":{}},{"type":"text","text":",要求是2的幂,一般由计算机的位数决定,如32位对应2^32,64对应2^64。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"物理地址空间","attrs":{}},{"type":"text","text":"则对应的是系统中物理内存的M个字节,没有2的幂的要求 ","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.3.1 页表","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"页表将虚拟页映射到物理页","attrs":{}},{"type":"text","text":",每次地址翻译硬件将一个虚拟地址转换为物理地址时,都会读取页表,操作系统负责维护页表内容,以及在磁盘与DRAM(Dynamic Random Access Memory)之间来回传送页。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/cb/cb51aea6a413ff78a5dd3fbe210e2747.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"页面分配的三种情况","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"页表是一个页表条目(pte:page table entry)的数组,每一条由一个有效位和一个n位地址字段组成,有效位表明了该虚拟页是否被缓存在DRAM,如果有效,那么地址字段就表明了DRAM中的物理页起始地址。图中vp1,vp2,vp4都是这种情况。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"若是空地址,则表明这个虚拟页还没有被分配,vp0就是这种情况。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"若是有地址,但是有效位为0,那么就表明虚拟页被分配在了磁盘上,地址指向的就是虚拟页在磁盘的起始地址。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"缺页","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"DRAM缓存不被命中就叫做缺页。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果我们去访问vp3,就会发现vp3不在DRAM中,由于磁盘和DRAM的访问速度差了100000多倍,那么我们就需要将vp3缓存到DRAM中,此时我们将vp3从磁盘复制到物理内存(如果此时物理内存不够,就按照一定的算法将原本保存在里面的页面移出,并设置页表中对应的标记位为无效),再将vp3在页表中对应的pte有效位设置为有效,修改地址从磁盘指向DRAM。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"进程页表","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"虚拟内存为每个进程提供了一个独立页表,因而是一个独立的虚拟地址空间,一来方便用户操作,二来方便用户共享内存,因为不同的页表支持映射到同一个共享物理页面上。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2.4 地址翻译","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.4.1 名词介绍","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"页表基址寄存器","attrs":{}},{"type":"text","text":"(page table base register PTBR):在cpu寄存器中指向当前页表(进程上下文切换中要更换)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"n位虚拟地址","attrs":{}},{"type":"text","text":":包含一个p位的虚拟页面偏移(virtual Page Offset,VPO)和一个n-p位的虚拟页号(virtual","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" page number,VPN),MMU利用VPN来选择适合的pte。物理页面的偏移量则与虚拟页面一致。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"MMU","attrs":{}},{"type":"text","text":"(Memory Management Unit,内存管理单元):用于翻译虚拟地址和物理地址映射关系","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.4.2 地址翻译整体流程","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/65/65c9ae817006c39013423a1c46ee47f9.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"cpu生成虚拟地址,传递给MMU","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"mmu生成pte地址(这一步是mmu通过虚拟地址的虚拟页号获取的),并从高速缓存/主存得到它","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"高速缓存/主存将pte返回给mmu","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"mmu通过页表,构造物理地址,将其传给高速缓存/主存","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"text","text":"高速缓存/主存将请求的数据字给处理器","attrs":{}}]}]}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.4.3 TLB","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由上面的知识,每次获取内存mmu都需要去内存取一次pte,利用","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"缓存思想(设计系统或者提高请求效率的时候都可以往这个上面靠,最基本原理就是空间换取时间)","attrs":{}},{"type":"text","text":",操作系统发明了tlb(translation lookaside buffer),他是一个关于pte的小缓存(注意进程上下文切换也需要清空tlb)。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有了tlb,如果发生命中,那么过程如下。","attrs":{}}]},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"cpu生成虚拟地址,传递给MMU","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"mmu从tlb取出相应的pte","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"mmu将虚拟地址翻译成一个物理地址,并将它发送到高速缓存/贮存","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"高速缓存/主存将请求的数据字给处理器","attrs":{}}]}]}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"三.问题思考","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"经过书本的系统学习,我已经了解了虚拟内存的工作原理,解决了问题二,还有进程初始化的时候是如何分配的内存这一问题。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以linux为例子,先看看在linux系统下进程的虚拟内存结构","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/cb/cb3a454275819c0851dc0a9caac2706c.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"进程能获取多少内存主要取决于运行时堆的内存分配,其余的内存消耗都是每个进程必要的,也就是说一个没有跑起来的进程消耗的内存都在物理内存上,等进程跑起来,会由操作系统对进程申请的内存进行动态分配,决定哪些放在物理内存,哪些放在主存,这是我们所不需要感知的。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"四.参考文档","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"深入理解计算机系统","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.guru99.com/stack-vs-heap.html","title":"","type":null},"content":[{"type":"text","text":"https://www.guru99.com/stack-vs-heap.html","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章