通过计算可以得到,PMD_SIZE产生的值为2的21次方,即为2M,PMD_MASK产生的值为0Xffe00000.
PGDIR_SHIFT是全局目录项所能映射的区域大小的对数,PGDIR_SIZE宏是用于计算页全局目录中一个单独表项所能映射区域的大小,它与PMD_SIZE一样。(用户通常可以使用减1取反来产生某个数的掩码)
有了前面基础知识的理解和掌握后,下面来介绍ARM-Linux中真正的页面映射部分的内容,着重从语法角度来介绍。
下面这个函数是嵌入式Linux中非常重要的一个函数,它用于创建页面映射,其源代码位于<arch\arm\mm\mm-armv.c>中,该函数中的关键代码如下所示:
static void _init create_mapping(struct map_desc *md){
unsigned long virt,length;
int prot_set,prot_11,domain;
pgprot_t prot_pte;
long off;
...
/*虚拟地址*/
virt = md->virtual;
/*地址偏移*/
off = md->physical - virt;
/*地址长度*/
length = md->length;
...
/*while1:判断虚拟地址是否与1M对齐,并且其长度大于页面大小*/
while((virt & 0xfffff || (virt+off) & 0xfffff) && length >=PAGE_SIZE){
/*分配中间页表项映射*/
alloc_init_page(virt,virt + off,prot_11,prot_pte);
/*虚拟地址增加PAGE_SEZE大小*/
virt += PAGE_SIZE;
/*长度减小PAGE_SIZE大小*/
length -=PAGE_SIZE;
}
/*while2:判断长度是否大于全局页表项大小的一半*/
while(length >= (PGDIR_SIZE / 2)){
/*逐段建立单层映射*/
alloc_init_section(virt,virt + off, prot_sect);
/*虚拟地址增加PGDIR_SIZE/2大小*/
virt += (PGDIR_SIZE /2);
/*长度减小PGDIR_SIZE/2大小*/
length -=(PGDIR_SIZE /2);
}
/*while3:判断长度是否大于页大小*/
while(length >= PAGE_SIZE){
/*分配中间页表项映射*/
alloc_init_page(virt,virt + off,prot_11,prot_pte);
/*虚拟地址增加PAGE_SIZE大小*/
virt +=PAGE_SIZE;
/*长度减小PAGE_SIZE大小*/
length -=PAGE_SIZE;
}
}