Linux内存分析(3) -- create_mapping

在start_kernel对内存的初始化中,会调用arch_setup对平台进行初始化。在该函数中,为创建一级页表,有这样的调用顺序:bootmem_init() --> bootmem_init_node() ->map_memory_bank() --> create_mapping()。

 

create_mapping函数的开始是一系列的检查,有意义的代码是最后的这个循环:

       pgd = pgd_offset_k(addr);            //一级数组中addr对应的段在init_mm->pgd的下标

       end = addr + length;                    //计算结束地址

       do {

              unsigned long next = pgd_addr_end(addr, end);   //获得下一段开始地址

 

              //申请并初始化一个段

              //段码,虚拟地址,结束地址,物理地址,内存类型

              alloc_init_section(pgd, addr, next, phys, type);

 

              phys += next - addr;             //物理地址累加

              addr = next;                         //地址为下一段的开始地址

       } while (pgd++, addr != end);             //下一段,地址不等于结束地址

 

可见,核心函数是alloc_init_section:

static void __init    alloc_init_section(

       pgd_t                   *pgd,            //段码

       unsigned long        addr,                     //虚拟地址

       unsigned long        end,              //结束地址

       unsigned long        phys,              //物理地址

       const struct mem_type   *type)     //内存类型

{

       pmd_t    *pmd = pmd_offset(pgd, addr);           //直接将pdgpmd

 

       //addr, end, phys都是1M对齐,则直接进行段映射(大部分情况下应该是满足条件)

       if (((addr | end | phys) & ~SECTION_MASK) == 0) {

              pmd_t    *p = pmd;

 

              if (addr & SECTION_SIZE)

                     pmd++;          //奇数段(段的处理总是2段一起处理的)

 

              do {

                     //物理地址 | 段属性à填充进段描述符中。(2410规格书P560

                     *pmd = __pmd(phys | type->prot_sect);             

                     phys += SECTION_SIZE;                          //下一段(1M)

              } while (pmd++, addr += SECTION_SIZE, addr != end);

              //这个循环只运行一次

 

              flush_pmd_entry(p);             //同步数据进RAM(由于有cache机制,所以数据操作的时候是先保存在cache中的,这里是强制将数据从cache中刷进RAM)

       } else {

       //没有按1M对齐,直接初始化二级页表。

              //由于这个函数实际是调用不到的,所以这里我们就不做分析了。

              alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);

       }

}

 

小结:

在系统初始化的时候,会开辟内存的前16K空间来保存一级页表数组(内存一共4G,每个段为1M,共4K个段,由于ARM是32位的,所以字长为4个字节,所以保存这4K个段就需要16K内存)。

在看create_map之前,我们需要下看一下S3C2410的规格书中MMU部分一级页表的说明,我们可以知道:

1、高10位为段地址

2、19..12位未用

3、11..0 为一级页表的描述属性。

 

而create_map函数实际上就是根据参数指定的内存类型,将段和其属性合成为一级页表的描述符,然后保存到前16K的管理数组中。

 

可见,create_map和MMU其实并不神秘。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值