Linux中虚拟地址和物理地址互相转化之页表的详解
小编在又一次学习完页表之后,终于是很明白了页表的构造及原理,今天在这里就告诉大家!!!
一、页表和虚拟地址的由来
为什么在Linux中会有虚拟地址和页表,在Linux中,假如没有页表和虚拟地址,每一个程序的数据区,代码区,栈空间都会把这个物理内存分割成各种离散的,大小不同的块,然后等程序退出后,这些空间被释放,但是物理内存被切割成了大小不同的碎片,对于Linux来说很不好管理,下次使用这个内存碎片的时候也不好使用,所以就引入了页表和虚拟地址空间的概念,来帮助操作系统更好的管理物理内存。具体页表和虚拟地址如下图:
二、虚拟地址通过页表如何映射物理地址
这里咱们以32位的机器来说,因为机器是32位的机器,所以这个机器的最大虚拟空间大小就为 4 * 2 ^ 32 byte = 4 GB,所以这个这个机器的虚拟地址最多可映射 4 GB 的真实物理空间大小,那该如何映射呢,在这里先告诉大家,计算机中一般物理内存空间是通过4 KB 来把物理内存划分为不同的一个一个页框,为什么是 4KB 当然每个平台或者每个机器都会不同吧,一般都是 521 byte ---- 8 KB,知道了这个,咱们先来分析一下,如下图:
经过图片上的分析,显然这样子的页表是不符合情况的,那我们该如何把虚拟地址向物理地址映射呢,继续往下看!
所以操作系统中真实储存的页表的结构如下图:
操作系统采用这样的方式进行对页表进行管理,我们计算一下大小,总共页表的大小 = 1024 * 1024 * 4 byte = 4 MB。所以页表一共的大小只有4 MB,但是作为1024个页表中的1个页表,它只有4KB的大小,并且他所管理的空间大小为 1024 * 4 KB = 4 MB的大小空间,所以这才是正确的页表的格式。并且操作系统中的一个程序不会占用4GB的大小,所以他的页表的大小也要远远小于4MB。举个例子,一个程序的一般大小就是10MB,根据咱们上面计算的总的页表中的一个页表所管理的大小为4MB,所以这个程序只需要总的页表中的3个页表足以管理。
还有对页表进行管理的页目录,他的大小是一直固定的,只有有了这个页目录的起始物理地址,咱们就可以对这个页表进行管理了,具体请看下面注释及图片:
三、虚拟地址如何通过页表转化为物理地址
有了上面的认识,我们就可以对虚拟地址通过页表转化为物理地址了,具体转化逻辑如下图,大家看图片及注释,我再给大家讲解:
在页表储存的真实的物理页框地址,页框的个数只有 4GB / 4KB = 1024 * 1024 = 2 ^ 20个页框的地址,也就是说在页表中只需要20个bit位就可以确定页框的真实起始地址,再通过虚拟地址的后12位来确定页框内的偏移量来确定真实的访问的物理地址,那页表中还有12个bit位闲置了,但其实这不是闲置了,还要被使用,起始页表中还有几个标记位,刚好占用了闲置的12个bit位,具体标志位如下图:
这里我也给大家找了源码的信息,大家可以对照看一下这12个标记位,如下图:
在我们加载磁盘上的内容到物理内存中的时候,标记位就会被设置,在这里我给大家说一下是否命中这个标记位和RWX标记位
是否命中标记位:首先这个标记为代表的是我们要请求的虚拟地址是否是合法的,如果越界了或者是野指针,那就代表这个虚拟地址我们无法转化,就会出现错误,CPU中的MMU硬件就会出现缺页中断进行报错,交由CPU处理。其次是否命中这个标记位也可以进行加载磁盘上的内容到物理内存中,比如,我们在进行malloc或者new的时候,操作系统可能不会直接给我们开空间,而只是给我们填充页表,给我们虚拟地址,等到我们真正要使用这个内存的时候,通过MMU对虚拟地址进行转化,发现物理地址还没有被填充,就会出现缺页中断,告诉操作系统帮我们开空间。虽然这两个都是缺页中断,但是缺页中断的类型不同。
RWX标记位:这个标记位是对我们进行操作的权限检查,例如我们这个虚拟内存对应的空间只能进行R也就是只读,但是我们进行W操作的话就会报错,他不允许修改,只允许我们读取数据,不能做修改,这里的报错也是MMU在进行转化的时候进行报错。
以上就是我们今天虚拟地址到物理地址的页表讲解的所有内容,下期再见!!!