操作系统
内存管理相关知识
虚拟内存
-
虚拟内存:操作系统会提供一种机制,将不同进程的虚拟地址和不同内存的物理地址映射起来。
-
我们程序所使用的内存地址叫做虚拟内存地址,实际存在硬件里面的空间地址叫物理内存地址。
-
操作系统主要通过内存分段和内存分页来管理虚拟地址与物理地址的关系。
内存分段
- 内存分段:程序是由若干个逻辑分段组成的如可由代码分段、数据分段、栈段、堆段组成。不同的段是有不同的属性的,所以就用分段的形式把这些段分离出来。
- 分段机制下的虚拟地址由两部分组成段选择子和段内偏移量。
- 段选择子:段选择子就保存在段寄存器里面。段选择子里面最重要的是段号,用作段表的索引;段号指向段表中的段内描述符,其中存在着段基地址、段界限等信息。
- 段内偏移量:段基地址加段内偏移量得到物理内存地址。
- 虚拟内存是通过段表和物理地址映射的,分段机制会把程序的虚拟地址分成4个段,每个段在段表中有一个主项,在这一项找到段的基地址,再加上偏移量,于是就能找到物理内存中的地址。
- 内存分段的不足:
- 内存碎片化问题
- 内存交换的效率低的问题
内存分页
-
内存分页:分页是把整个虚拟和物理内存空间切成一段段固定尺寸的大小。在linux下每一页的大小为4KB。
-
虚拟地址与物理地址之间通过页表来映射,页表是存储在内存中的,内存管理单元MMU就做将虚拟内存地址转换成物理地址的工作。
-
分页解决分段的内存碎片、内存交换的效率低的问题:
采用了分页,那么释放的内存都是以页为单位释放的,也就不会产生无法给进程使用的小内存。
如果内存空间不够,操作系统会把其他正在运行的进程中的最近没被使用的内存页面给释放掉,也就是暂时写在硬盘上,称为换出。一旦需要的时候,再加载进来,称为换入。所以一次性写入磁盘的也只有少数的一个页或者几个页,不会花太多时间,内存交换的效率就相对比较高。
更进一步地,分页的方式使得我们在加载程序的时候,不再需要一次性都把程序加载到物理内存中。我们完全可以在进行虚拟内存和物理内存的页之间的映射之后,并不真的把页加载到物理内存中去,而是只有在程序运行中,需要用到对应虚拟内存页里面的指令和数据时,再加载到物理内存里面去。
-
在分页机制下,虚拟地址分为两部分,页号和页内偏移,页号作为页表的索引,页表包含物理页每页所在物理内存的基地址,这个基地址与页内偏移的组合就形成了物理内存地址。
段页式内存管理
-
内存分段和内存分页并不是对立的,它们是可以组合起来在同一个系统中使用的,那么组合后称为段页式内存管理
-
段页式内存管理实现的方式:
- 先将程序划分为多个有逻辑意义的段,也就是前面提到的分段机制。
- 再把每个段分为多个页,也就是对分段划分出来的连续空间、再划分固定的页。
这样地址结构就由段号、段内页号、页内位移三部分组成
-
段页式内存方式要得到物理地址必须经过三次访问:
- 第一次访问段表,得到页表起始地址。
- 第二次访问页表,得到物理页号。
- 第三次将页号与页内位移结合,得到物理地址。
Linux内存管理
Linux内存主要采用的是页式内存管理,但同时也不可避免的涉及了段机制。于是Linux把所有段的基地址设置为0,也意味所有程序的地址空间都是虚拟地址,相当于屏蔽了CPU中逻辑地址概念,段只用于访问控制和内存保护。