前面1-2章节我们说到过MMU地址之间的转换,那么这一文章我们就来详细说明一下其中的细节!通过前面的说明我们知道了物理地址虚拟地址以及变换后的虚拟地址(包括它们之间是如何转换的)
这一章节的主要几个问题如下:
1,CPU发出的虚拟地址包含两个部分:页表索引和页内偏移(什么是页表索引什么是页内偏移?)
2,S3c2440是如何将cpu发出的VA转换成MVA的?
在S3C2440虚拟内存管理中(或者说在ARM Linux中)一个进程大小被限制在32MB范围,Linux中的进程从软件角度来看,就是main()函数,都是从0x0地址开始的,那我们该如何区分不同的进程呢?
使用进程标识(PID)来区分,PID是一个整数,也称进程号,每创建一个进程Linux内核就会为该进程分配一个PID,进程结束退出后PID又被系统收回,可分配给其他进程,而在Linux中是多个进程并发的:这个并发的进程cpu发出的虚拟地址VA都是从0x0地址开始的,地址范围:0~32MB即0x00000000~0x01ffffff
使用MVA来标识不同的进程空间:2,如何将cpu发出的VA变换成能够识别进程的MVA?
由系统控制协处理器CP15来完成的,CP15的寄存器C13存放的是当前运行的进程的PID
MVA = VA|(PID<<25); //由硬件自动转换
如果cpu发出的虚拟地址VA的地址大于32MB,则要认为访问的是内存/外设地址(由PA来读写外设和内存),而不是某一个进程,ARM,Linux中,一个进程的空间大小被限制在32MB范围的
VA转换成MVA的过程方法示意:由硬件协处理器CP15完成
if(VA<32m)
{
MVA = VA\(PID<<25);//PID通过都CP15的C13获得
}
else
{
MVA = VA;
}
注意:无论进行哪种有效转换都要先进行一级页表的转换
关键是mmu如何将MVA变成PA?将MVA变换成PA可以有2种方法
1,建立MVA与PA之间的数学关系式
2,建立MVA与PA之间地址映射表格,通过查表进行转换(现代计算机系统基本上都是采用这种方法,这个MVA到PA的地址映射称为页表Page Table)
S3C2440中最多会用到2级页表:
1,以段(Section)的方式进行地址变换,只使用一级页表
2,以页(Page)的方式进行地址变换,则使用两级页表
S3C2440中MVA到PA的转换过程(在进行地址变换时,将虚拟内存空间和物理内存空间划分成不同大小的内存块,以内存块为单位进行地址变换)
1,以段的的方式进行地址变换时,是将虚拟地址的内存空间(4GB)划分成2的32次方=2的20次方乘以2的12次方等于4096=4K个段(1MB大小的内存块称为段Section)
每一个Section的地址是由2部分组成:
同样的,把物理地址内存也划分成若干个大小为1MB的段,虚拟内存的段与物理地址的段是一样的只是段号不一样
以段的方式进行MVA到PA的转换过程:
举例说明:假设将虚拟空间中的1段(地址范围在0x00100000~0x001fffff)映射到物理空间中的0段(0x00000000~0x0000ffff)
设虚拟地址MVA为0x0011 2300,只需要将这个MVA高12bit(段号)变换成物理空间的0段的高12bit地址(物理段号)就可以了
MVA : 0x001 12300(虚拟地址)
PA :0x000 12300(物理地址\实际地址)
这样,cpu对MVA为0x001 12300单元的访问,实际上是访问地址为0x000123的内存单元
为了将整个4GB的虚拟空间进行地址映射,需要一个共有4096个表项的表格,用来记录4GB虚拟空间中的每一个段与物理内存空间中段地址对应关系(称为一级页表,这个表格就是MVA到PA的的映射表(页表)通常称为一级页表也称为页表基址(TTB Base)寄存器