虚拟内存和物理内存

数据总线

数据总线是CPU和内存之间传输数据的单元。

如果主板是一个城市,总线就是公共汽车,而数据总线就是最常见的一种公共汽车,在CPU和内存之间传输比特。

数据总线的单位是每秒多少MB。

地址总线

地址总线是CPU用来管理内存的单元。

一根地址总线代表1位,位宽是同时能传递二进制数据的数量(位数),也就是说:一次性可以传递0或者1的数量。

位宽为n,理论寻址范围是2的n次方。比如32的位宽,寻址范围是2的32次方,大约4G,

我们常说的线性地址空间就是地址总线的寻址范围

这也是为什么,32位的系统最大支持4G的物理内存(因为最大的线性地址空间就是4G)。

拓展:我们常说的总线,就是系统总线,是数据总线、地址总线和控制总线的统称。

线性地址空间

系统中从0x00000000-0xFFFFFFFF的虚拟存储空间。

逻辑地址

程序中由程序员指定的地址,也就是代码对应的地址。

逻辑地址由段和偏移量组成。

内存寻址

linux系统内存寻址首先是执行分段机制,把逻辑地址转化为线性地址;然后执行分页机制,将线性地址转化为物理地址。

物理内存

这个就是电脑中DRAM内存条的大小。

虚拟内存

CPU最早的时候,寻址方式采用的是直接访问物理内存。后来才改变为现在所采用的,通过虚拟内存间接的访问物理内存的机制。

我们知道进程由fork产生,每个进程都有独立的内存空间,这就是常说的用户空间;以及进程共用的内存空间——内核空间。

一般来说,对于4G的内存,用户空间3G,内核空间1G。

 用户空间可能存在磁盘上,但是内核空间永远在主内存上。

用户空间的映射方式是通过页表来实现,内核空间的映射方式是通过线性来实现。

对于64位的系统,寻址空间有2的64次方大小,理论支持非常大的虚拟内存。但是,实际上最大支持的虚拟内存被厂商限制了,比如最大支持64G或者128G。

如果你的电脑物理内存为8G,但是进程所需要的内存32G,这个时候怎么办呢?

采用早期的CPU直接访问物理内存的方式,直接死路一条!

而虚拟内存这种机制,恰好提供了合适的解决方案:

虚拟内存的大小是物理内存+交换分区的大小,交换分区是在硬盘上划分一个区域来充当内存,一般是物理内存的2倍。

这样一来,如果笔记本物理内存是8G,设置交换分区为32G,虚拟内存大小就为32G+8G=40G,内存就够用了!(其本质是拆东墙补西墙而已)

采用虚拟内存这种机制,其运作原理是怎么样的呢?下面来说说:

计算机会对虚拟内存地址空间(也就是线性地址空间)(32位为4G)分页产生页(page),对物理内存地址空间(假设256M)分页产生页帧(page frame),

所以呢,在这里,虚拟内存的页数势必要大于物理内存的页帧数。

在计算机上有一个页表(page table),就是映射虚拟内存页到物理内存页的,更确切的说是页号到页帧号的映射,而且是一对一的映射。

但是问题来了,虚拟内存页的个数 > 物理内存页帧的个数,岂不是有些虚拟内存页的地址永远没有对应的物理内存地址空间?

不是的,系统是这样处理的。

系统有个页面失效(page fault)机制:

操作系统找到一个最少使用的页帧,让他失效,并把它写入磁盘,这样就有空闲的物理内存空间了。
随后把需要访问的页放到页帧中,并修改页表中的映射,这样就保证所有的页都有被调度的可能了。

这就是处理虚拟内存地址到物理内存的步骤。

而这个工作是由CPU上叫做MMU(内存管理单元)的来负责,需要用到分页表

一般来说,每个页的大小为4KB,这也是数据块的大小,因为数据块是文件存储的最小单位。

虚拟内存地址由页号和偏移量组成,页号就是一个编号,用来对应的物理内存地址中页帧这个概念;而偏移量就是页的大小,实际存储数据的空间。

举个例子,有一个虚拟地址它的页号是4,偏移量是20,那么他的寻址过程是这样的:

首先到页表中找到页号4对应的页帧号(比如为8),如果页不在内存中,则用失效机制调入页,否则把页帧号和偏移量传给MMU(CPU的内存管理单元)组成一个物理上真正存在的地址,接着就是访问物理内存中的数据了。

原文地址:https://www.cnblogs.com/leomei91/p/7502439.html