为什么要有虚拟内存?
如果CPU直接操作内存的物理地址,那么想在内存中同时运行两个程序是不可能的。而操作系统为每个进程分配独立的一套【虚拟地址】,这样就可以避免不能同时运行程序的问题。但有个前提是每个进程都不能访问物理地址,操作系统会提供一种机制,将不同进程的虚拟地址和不同内存的物理地址映射起来,如果程序要访问虚拟地址的时候,由操作系统转换成不同的物理地址,这样不同的进程运行的时候,写入的是不同的物理地址,这样就不会冲突了。
操作系统引入了虚拟内存,进程持有的虚拟地址会通过 CPU 中的内存管理单元(MMU)的映射关系,来转换变成物理地址,然后再通过物理地址访问内存,如下图所示:
1. 内存管理介绍
操作系统的内存管理单元主要负责内存的分配与回收(malloc函数:申请内存,free函数:释放内存),另外,地址转换也就是将逻辑地址转换成相应的物理地址等功能也是操作系统内存管理要做的事情。
2. 操作系统是如何管理虚拟地址和物理地址之间的关系?/ 常见的内存管理机制
每个进程都有自己的虚拟地址空间,也就是说每个进程都有自己的页表 / 段表等。
简单分为连续分配管理方式和非连续分配管理方式两种。连续分配管理是指为用户程序分配一个连续的内存地址,常见的如块式管理。非连续分配管理方式允许一个程序使用的内存分布在离散或不相邻的内存中,常见的如页式管理、段式管理、段页式管理。
块:太大了,浪费内存空间。
页:相比块划分更小,提高了内存利用率,较少了碎片,但每一页没有具体的意义。
段:相比页划分更小,利用率更高,且每一段都有具体的意义。
(1)块式管理
将内存分为几个固定大小的块,每个块中只包含一个进程。如果程序运行需要内存的话,操作系统就分配一块给它。如果程序运行只需要很小的一块内存,那么分配的内存很大一部分会被浪费,每个块中未被利用的空间称为碎片。
(2)页式管理
把主存分为大小相等且固定的一页一页的离散空间,页较小。相比于块式管理的划分力度更大,提高了内存利用率,减少了碎片。通过页表来完成逻辑地址和物理地址之间的映射。当进程访问的虚拟地址在页表中查不到时就会产生一个缺页异常,并进入系统内核空间分配物理内存、更新进程页表,最后再返回用户空间,恢复进程的运行。
在分页机制下,虚拟内存被分为页号和页内偏移量两部分。页号作为页表的索引,页表包含物理页每页所在物理内存的基地址,这个基地址与页内偏移的组合就形成了物理内存地址。如下,
(3)段式管理
段式管理把主存分为⼀段段的,每⼀段的空间⼜要比一页的空间小很多,并且每个段定义了⼀组逻辑信息,例如,有主程序段MAIN、子程序段 X 等。 段式管理通过段表完成逻辑地址和物理地址之间的映射。
而在分段机制下,虚拟地址分为段选择因子和段内偏移量两部分。段选择子就保存在段寄存器里面。段选择子里面最重要的是段号,用作段表的索引。段表里面保存的是这个段的基地址、段的界限和特权等级等。
(4)段页式管理
分页能提高内存利用率,分段能很好的满足用户需求,而段页式管理结合了两者优点。段页式管理机制就是把主存先分成若干段,然后每个段又分成若干页,。也就是说段页式管理机制中段与段之间以及段的内部都是离散的。
3. 快表和多级页表
页式管理机制中的概念:快表 TLB 和多级页表,分别解决了页式管理中很重要的两个问题。在页式管理中,有很重要的两点:虚拟地址到物理地址的转换要快;解决虚拟地址空间大,页表也会很大的问题。
(1)快表TLB
为了解决虚拟地址到物理地址的转换速度,操作系统在页表方案基础之上引入了快表来加速虚拟地址到物理地址的转换。可以把快表理解为⼀种特殊的⾼速缓冲存储器(Cache),其中的内容是页表的⼀部分或者全部内容。作为页表的 Cache,它的作⽤与页表相似,但是提⾼了访问速率。由于采⽤页表做地址转换,读写内存数据时 CPU 要访问两次主存。有了快表,有时只要访问⼀次⾼速缓冲存储器,⼀次主存,这样可加速查找并提⾼指令执⾏速度。
使用快表之后的地址转换流程:
01 根据虚拟地址中的页号查找快表;
02 如果该页在快表中,直接从快表中读取相应的物理地址;
03 如果该页不在快表中,就访问内存中的页表,再从页表中得到物理地址,同时将页表中的该映射表项添加到快表中;
04 当快表填满后,又要登记新页时,就按照一定的淘汰策略淘汰掉快表中的一个页。
(2)多级页表
为了避免把全部页表一直放在内存中占用过多的空间,特别是那些根本不需要的页表就不需要保存在内存中。多级页表属于时间换空间的典型场景。
4. 分页机制和分段机制的共同点、区别
(1)共同点
01 分页机制和分段机制都是为了提高内存利用率,减少内存碎片;
02 页和段都是离散存储的,所以两者都是离散分配内存的方式。但是,每个页和段中的内存是连续的。
(2)区别
01 页的大小是固定的,由操作系统决定;段的大小不固定,由当前运行的程序决定;
02 分页仅仅是为了满足操作系统内存管理的需求,而段是逻辑信息的单位,在程序中可以体现为代码段、数据段,能更好的满足用户的需要。
5. 逻辑(虚拟)地址和物理地址
编程的时候一般只有可能和逻辑地址打交道。比如C语言中,指针里存储的数值就可以理解为内存里的一个地址,这个地址就是虚拟地址,虚拟地址由操作系统决定。物理地址就是指真实物理内存中地址,也就是内存地址寄存器中的地址,物理地址是存储单元真正的地址。
6. CPU寻址了解?为什么需要虚拟地址空间?
现代处理器使⽤的是⼀种称为虚拟寻址(Virtual Addressing) 的寻址⽅式。使⽤虚拟寻址,CPU 需要将虚拟地址转换成物理地址,这样才能访问到真实的物理内存。实际上完成虚拟地址到物理地址转换的是 CPU 中被称为内存管理单元(Memory Management Unit, MMU) 的硬件。如下,
(1)为什么要有虚拟地址呢?
没有虚拟地址空间的时候,程序直接访问和操作的都是物理内存。这样直接把物理地址暴露出来会带来严重的问题,如可能会造成操作系统崩溃以及很难同时运行多个程序。
(2)通过虚拟地址访问内存,具有以下优势
01 程序可以使用一系列相邻的虚拟地址来访问物理内存中不相邻的大内存缓冲区;
02 不同进程使用的虚拟地址彼此隔离。一个进程中的代码无法更改正在由另一进程或操作系统使用的物理内存。
操作系统引入了虚拟内存,进程持有的虚拟地址会通过 CPU 中的内存管理单元(MMU)的映射关系,来转换变成物理地址,然后再通过物理地址访问内存。
7. 什么是虚拟内存?
这个在我们平时使⽤电脑特别是 Windows 系统的时候太常⻅了。很多时候我们使⽤点开了很 多占内存的软件,这些软件占⽤的内存可能已经远远超出了我们电脑本身具有的物理内存。由于虚拟内存的存在,通过虚拟内存可以让程序可以拥有超过系统物理内存大小的可用内存空间。另外,虚拟内存为每个进程提供了⼀个⼀致的、私有的地址空间,它让每个进程产⽣了⼀种自己在独享主存的错觉(每个进程拥有⼀⽚连续完整的内存空间)。这样会更加有效地管理内存并减少出错。
虚拟内存的重要意义是它定义了⼀个连续的虚拟地址空间,并且把内存扩展到硬盘空间。
8. 局部性原理
程序在执行时往往呈现出局部性规律,也就是说在某个较短的时间段内,程序执行局限于某一小部分,程序访问的存储空间也局限于某个区域。局部性原理表现在以下两方面,
(1)时间局部性:若程序中的某条指令一旦执行,不久以后该指令可能会再次执行;若某条数据被访问过,不久以后该数据可能会被再次访问。产生时间局部性的原因是程序中可能存在着大量的循环操作。
(2)空间局部性:一旦程序访问了某个存储单元,不久以后,其附近的存储单元也将被访问。即程序在一段时间内所访问的地址,可能集中在一定范围之内,这是因为指令通常是顺序存放、顺序执行的,数据也一般是以向量、数组、表等形式存储的。
时间局部性是通过将近来使⽤的指令和数据保存到⾼速缓存存储器中,并使⽤⾼速缓存的层次结构实现。空间局部性通常是使⽤较⼤的⾼速缓存,并将预取机制集成到⾼速缓存控制逻辑中实现。虚拟内存技术实际上就是建立了 “内存⼀外存”的两级存储器的结构,利⽤局部性原理实现髙速缓存。
9. 虚拟存储器
基于局部性原理,在程序装入时,可以将程序的一部分装入内存,而将其他部分留在外存,就可以启动程序执行。由于外存比内存大很多,所以运行的软件的内存实际上是比计算机内存大的。在程序执行过程中,当所访问的信息不在内存时,由操作系统将所需部分调入内存,然后继续执行程序(即,换入);另一方面,操作系统将内存中暂时用不到的内容换到外存上,从而腾出空间存放将要调入内存的信息(即,换出)。这样,计算机就好像为用户提供了一个比实际内存大的虚拟存储器。
10. 虚拟内存的技术实现
虚拟内存的实现需要建立在离散分配的内存管理方式的基础上。虚拟内存的实现有以下三种方式,
(1)请求分页存储管理
建立在分页管理之上,为了支持虚拟存储器功能而增加了请求调页功能和页面置换功能。请求分页是目前最常见的一种实现虚拟存储器的方法。请求分⻚存储管理系统 中,在作业开始运⾏之前,仅装⼊当前要执⾏的部分段即可运⾏。假如在作业运⾏的过程中发现 要访问的⻚⾯不在内存,则由处理器通知操作系统按照对应的⻚⾯置换算法将相应的⻚⾯调⼊到 主存,同时操作系统也可以将暂时不⽤的⻚⾯置换到外存中。
(2)请求分段存储管理
建⽴在分段存储管理之上,增加了请求调段功能和分段置换功能。请求分 段储存管理⽅式就如同请求分⻚储存管理⽅式⼀样,在作业开始运⾏之前,仅装⼊当前要执⾏的 部分段即可运⾏;在执⾏过程中,可使⽤请求调⼊中断动态装⼊要访问但⼜不在内存的程序段; 当内存空间已满,⽽⼜需要装⼊新的段时,根据置换功能适当调出某个段,以便腾出空间⽽装⼊ 新的段。
(3)请求段页式存储管理
请求分页和分页管理有何不同?
请求分⻚存储管理建⽴在分⻚管理之上。他们的根本区别在于是否将程序全部所需的全部地址空间都装⼊主存。请求分⻚存储管理不要求将作业全部地址空间同时装⼊主存。基于这⼀点,请求分⻚存储管理可以提供虚存,⽽分⻚存储管理却不能提供虚存。
11. 页面置换算法的作用?常用的有哪些?
(1)作用
地址映射过程中,若在页面中发现所要访问的页面不在内存中,则发生缺页中断 。当发生缺页中断时,如果当前内存中并没有空闲的页面,操作系统就必须在内存选择⼀个页面将其移出内存,以便为即将调入的页面让出空间。⽤来选择淘汰哪一页的规则叫做页面置换算法,我们可以把页面置换算法看成是淘汰页面的规则。
(2)算法
最佳页面置换算法(OPT ):选择的被淘汰页面是以后永不使用的或在最长时间内不再被访问的页面,这样可以保证获得最低的缺页。但由于人们目前无法预知进程在内存下的若千页面中哪个是未来最长时间内不再被访问的,因而该算法无法实现。一般作为衡量其他置换算法的方法。
先进先出页面置换算法(FIFO): 总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面进行淘汰。
最近最久未使用页面置换算法(LRU ):LRU算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间 T,当须淘汰一个页面时,选择现有页面中其 T 值最大的,即最近最久未使用的页面予以淘汰。
最少使用页面置换算法(LFU): 该置换算法选择在之前时期使用最少的页面作为淘汰页。