虚拟内存、物理内存、硬盘
物理内存:
在应用中,真实存在的,插在主板内存槽上的内存条的容量的大小。从本质上来说,物理内存是代码和数据在其中运行的窗口。用来保存CPU运算的中间数据和计算结果
虚拟内存:
把硬盘的一部分内存当作物理内存来用,以弥补物理内存的不足。
虚拟内存的容量限制:物理内存+硬盘容量
区分虚拟内存和虚拟地址空间的区别
虚拟内存:就是把硬盘上的内存当成物理内存来用的那一部分内存
虚拟地址空间:它是连续的地址,虽然把硬盘那部分内存当成物理内存来用,但是它和真正的物理内存毕竟不是连续的,虚拟地址空间就是把这两部分的地址统一连续起来
硬盘内存:
一般都是用来存储数据的,相当于数据仓库,比如系统,文件等都是保存在硬盘里面
物理地址和逻辑地址
1、用户编制程序时使用的地址称为虚地址或逻辑地址,其对应的存储空间称为虚存空间或逻辑地址空间;
2、计算机物理内存的访问地址则称为实地址或物理地址,其对应的存储空间称为物理存储空间或主存空间。
虚存的访问过程:
虚存空间的用户程序按照虚地址编程并存放在硬盘中。程序运行时,由地址变换机构依据当时分配给该程序的实地址空间把程序的一部分调入实存。
每次访存时,首先判断该虚地址所对应的部分是否在实存中。如果是,则进行地址转换并用实地址访问主存;否则,按照某种算法将辅存中的部分程序调度进内存,
再按同样的方法访问主存。由此可见,每个程序的虚地址空间可以远大于实地址空间,也可以远小于实地址空间。
前一种情况以提高存储容量为目的,后一种情况则以地址变换为目的。
后者通常出现在多用户或多任务系统中:实存空间较大,而单个任务并不需要很大的地址空间,较小的虚存空间则可以缩短指令中地址字段的长度。
引入虚拟存储技术的好处:
1、可在较小的可用内存中执行较大的用户程序;
2、可在内存中容纳更多程序并发执行;
3、不必影响编程时的程序结构(与覆盖技术比较);
4、提供给用户可用的虚拟内存空间通常大于物理内存。
进程与虚拟内存的关系:
1、进程使用的是虚拟内存,每个进程都有各自独立的4G 字节的虚拟地址空间。4G的进程空间分为两部分,0~3G-1 为用户空间,3G~ 4G-1 为内核空间。
2、一个新进程建立的时候,将会建立起自己的内存空间,此进程的数据,代码等从磁盘拷贝到自己的进程空间,哪些数据在哪里,都由进程控制表中的task_struct记录,
task_struct中记录中一条链表,记录中内存空间的分配情况,哪些地址有数据,哪些地址无数据,哪些可读,哪些可写,都可以通过这个链表记录
3、每个进程已经分配的内存空间,都与对应的磁盘空间映射
4、每个进程的内存空间完全独立,因此在不同进程之间交换虚拟地址毫无意义。
注意:
事实上,在每个进程创建加载时,内核只是为进程“创建”了虚拟内存的布局,具体就是初始化进程控制表中内存相关的链表,
实际上并不立即就把虚拟内存对应位置的程序数据和代码(比如.text .data段)拷贝到物理内存中,只是建立好虚拟内存和磁盘文件之间的映射就好(叫做存储器映射),
等到运行到对应的程序时,才会通过缺页异常,来拷贝数据。
还有进程运行过程中,要动态分配内存,比如malloc时,也只是分配了虚拟内存,即为这块虚拟内存对应的页表项做相应设置,当进程真正访问到此数据时,才引发缺页异常。
物理内存与虚拟内存的关系
1、用户程序中使用的都是虚拟地址空间中的地址,永远无法直接访问实际物理地址。
2、虚拟内存到物理内存的映射由操作系统动态维护。
3、虚拟内存一方面保护了操作系统的安全,另一方面允许应用程序使用比实际物理内存更大的地址空间。
4、虚拟内存到物理内存的映射,以页(4096字节)为单位
用户空间
1、用户空间中的代码不能直接访问内核空间中的代码和数据,但是可以通过系统调用进入内核态,间接地与内核交互。
2、对内存的越权访问,或访问未建立映射的虚拟内存(野指针、不在映射表中),将会导致段错误。
3、 用户空间对应进程,进程一切换,用户空间随即变换。
内核空间
1、内核空间由操作系统内核使用,不会随进程切换而变化。
2、内核空间由内核根据独立且唯一的页表init_mm.pgd 进行映射,而用户空间的页表则每个进程一份。
虚拟内存使用中的实际问题:
1、上面提到过,每个进程都有各自独立的4G的虚拟内存,但是计算机明明没有那么多内存(n个进程的话就需要n*4G)内存,根本不够
2、新建进程的时候就会建立自己的内存空间,同时把需要的程序文件从磁盘上拷贝到进程对应的内存中去,对于一个程序对应的多个进程这种情况,会十分浪费内存!
进程在实际使用中往往是通过共享内存来避免内存浪费的
1.每个进程的4G内存空间只是虚拟内存空间,每次访问内存空间的某个地址,都需要把地址翻译为实际物理内存地址
2.所有进程共享同一物理内存,每个进程只把自己目前需要的虚拟内存空间映射并存储到物理内存上。
3.进程要知道哪些内存地址上的数据在物理内存上,哪些不在,还有在物理内存上的哪里,需要用页表来记录
4.页表的每一个表项分两部分,第一部分记录此页是否在物理内存上,第二部分记录物理内存页的地址(如果在的话)
5.当进程访问某个虚拟地址,去看页表,如果发现对应的数据不在物理内存中,则缺页异常
6.缺页异常的处理过程,就是把进程需要的数据从磁盘上拷贝到物理内存中,如果内存已经满了,没有空地方了,那就找一个页覆盖,当然如果被覆盖的页曾经被修改过,需要将此页写回磁盘
在程序需要分配连续的内存空间的时候,只需要在虚拟内存空间分配连续空间,而不需要实际物理内存的连续空间,可以利用碎片。
以上内容转载自https://blog.csdn.net/zhyfxy/article/details/70157248