什么是虚拟内存
虚拟内存一般是相对于物理内存而言,物理内存即RMA(Random Access Memory),也就是常见的4G、8G的用于存储正在运行的程序和数据的那个东西。当一个进程被调用的时候,系统会给该进程在内存中开辟4G大小的空间,其中1G为系统空间(系统层),3G空间为用户空间(用户层)。系统层主要包含PCB,在PCB中有该进程的id以及状态等各种信息。用户层中包含了进程的任务信息,比如该进程的数据段、代码段、堆、栈的资源信息。而这些资源的空间就是虚拟内存,分别映射到各自的物理内存。一个进程需要分配的空间很多,就可以给他分配虚拟内存,让他以为自己被分配到了这么多内存,其实并没有。
操作系统将进程需要的内存空间分配到磁盘上,这样即使实际物理内存不足,进程也可以继续执行。操作系统会根据进程的需要,将数据从磁盘加载到内存中,或者将不常用的数据移出内存,以便为其他进程让出空间。虚拟内存的使用可以提高系统的整体性能和进程的运行效率。
什么是虚拟存储器
虚拟存储器在有些书上也叫虚拟内存(也就是说虚拟内存和虚拟存储器是同一个东西),个人觉得虚拟存储器这一名称更偏向于一种存储机制。而从字面意义上来说虚拟内存就是在磁盘上分配的不在物理内存的虚拟的内存。
调度方式
-
页式调度(Paging):
- 在页式调度中,物理内存被分割成固定大小的页框(page frame),而程序的逻辑地址空间被分割成相同大小的页面(page)。逻辑地址由页号和偏移量组成。
- 页表(Page Table)用于记录每个页号映射到内存中的页框号,通过页表,操作系统能够将程序的逻辑地址映射到实际的物理地址。
- 页式调度使得程序的地址空间可以被离散地分配到物理内存中,简化了内存分配和管理,但可能会产生内存碎片。
-
段式调度(Segmentation):
- 段式调度将程序的逻辑地址空间分割成若干个大小不同的段(segment),每个段代表了程序的一个逻辑单元,如代码段、数据段等。
- 每个段都有自己的基址和界限,基址指示段在内存中的起始位置,界限指示段的大小。逻辑地址由段号和偏移量组成。
- 段式调度允许程序的不同段在内存中独立存在,能够实现逻辑上的分离和保护,但可能引发内存碎片问题。
-
段页式调度(Paged Segmentation):
- 段页式调度结合了页式调度和段式调度的优点。它把程序的逻辑空间分割成若干个段,每个段再细分成大小相等的页。
- 段表记录每个段的页表起始地址和长度,页表记录每个页号映射到内存中的页框号。
- 段页式调度允许程序在逻辑上以段为单位进行管理,同时在物理内存中以页为单位进行存储,可以实现对程序逻辑和物理地址的灵活映射,能够充分利用内存并提供保护机制。
现代计算机系统中,通常会采用页式调度(Paging)作为默认的内存管理方式。
虚拟内存和物理内存的转换通过虚拟存储器的地址映射来转换。
虚拟地址包括两部分,一部分是页号,另一部分是页内偏移。页号用来索引页表,页表中存储了虚拟页号到物理页框号的映射关系。页内偏移则用来确定在物理页框内的具体地址偏移量。操作系统会使用页号在页表(内存映射表)中查找对应的物理页框号,再将页内偏移加上该页框号转换为物理地址。这样就完成了虚拟地址到物理地址的转换过程。从而得到物理地址。
页面置换
在内存页框不足时用来确定哪些页框的内容应该被替换出去,以便为新的页框腾出空间。在分页内存管理中,当所有的物理页框都被占用时,如果需要加载新的页到内存中,就需要选择一个页框来替换出去。这时候就会使用替换算法来确定被替换出去的页框。
常见的替换算法包括最佳(OPT)、先进先出(FIFO)、最近最久未使用(LRU)等。这些算法根据不同的策略来确定哪些页框应该被替换出去。例如,LRU算法会选择最长时间未被访问的页框进行替换,而FIFO算法会选择最先进入的页框进行替换。
将需要的物理页调入到内存页框中后,进程就可以访问其中的数据了。
顺便说一下,使用mmap可以将文件映射到虚拟内存中,也是利用物理内存的页中转过去的,碰到了虚拟内存这个知识点完全懵了,所以回顾了一下,不过linux还有很多不会的,还要继续加油。