感谢支持
我们一直在努力

Linux内存模型之bootmem分配器<二>

简介:介绍一下上文遗留的两个结构memblock以及meminfo.


相关阅读:http://www.linuxidc.com/Linux/2012-02/53139.htm 


**********************************


*  在arch/arm/kernel/setup.c中,
*  sanity_check_meminfo();


**********************************
arm_memblock_init(&meminfo, mdesc);


arch/arm/mm中,
void __init sanity_check_meminfo(void)
{
 int i, j, highmem = 0;


        //遍历所有的bank
 for (i = 0, j = 0; i < meminfo.nr_banks; i++) {
  struct membank *bank = &meminfo.bank[j];
  *bank = meminfo.bank[i];


#ifdef CONFIG_HIGHMEM
       //如果定义了高端内存,地址范围在高端内,则标记
  if (__va(bank->start) >= vmalloc_min ||
      __va(bank->start) < (void *)PAGE_OFFSET)
   highmem = 1;


  bank->highmem = highmem;       //标记


  /*
   * Split those memory banks which are partially overlapping
   * the vmalloc area greatly simplifying things later.
   */
                //范围在低端内存,但是size大于低端范围也就是
                //起始地址在低端,结束地址超过低端范围
  if (__va(bank->start) < vmalloc_min &&
      bank->size > vmalloc_min – __va(bank->start)) {
                        //banks号大于等于总数量,则直接忽略该bank
                        //否则将该bank分成两个bank,高端部分标记成高端
   if (meminfo.nr_banks >= NR_BANKS) {
    printk(KERN_CRIT “NR_BANKS too low, “
       “ignoring high memory\n”);
   } else {
    memmove(bank + 1, bank,
     (meminfo.nr_banks – i) * sizeof(*bank));
    meminfo.nr_banks++;
    i++;
    bank[1].size -= vmalloc_min – __va(bank->start);
    bank[1].start = __pa(vmalloc_min – 1) + 1;
    bank[1].highmem = highmem = 1;
    j++;
   }
   bank->size = vmalloc_min – __va(bank->start);
  }
#else
  bank->highmem = highmem;   //没定义就赋值为0


  /*
   * Check whether this memory bank would entirely overlap
   * the vmalloc area.
   */
                //没定义高端地址,那么高端部分全部忽略
  if (__va(bank->start) >= vmalloc_min ||
      __va(bank->start) < (void *)PAGE_OFFSET) {
   printk(KERN_NOTICE “Ignoring RAM at %.8llx-%.8llx “
          “(vmalloc region overlap).\n”,
          (unsigned long long)bank->start,
          (unsigned long long)bank->start + bank->size – 1);
   continue;
  }


  /*
   * Check whether this memory bank would partially overlap
   * the vmalloc area.
   */
  if (__va(bank->start + bank->size) > vmalloc_min ||
      __va(bank->start + bank->size) < __va(bank->start)) {
   unsigned long newsize = vmalloc_min – __va(bank->start);
   printk(KERN_NOTICE “Truncating RAM at %.8llx-%.8llx “
          “to -%.8llx (vmalloc region overlap).\n”,
          (unsigned long long)bank->start,
          (unsigned long long)bank->start + bank->size – 1,
          (unsigned long long)bank->start + newsize – 1);
   bank->size = newsize;
  }
#endif
  if (!bank->highmem && bank->start + bank->size > lowmem_limit)
   lowmem_limit = bank->start + bank->size;


  j++;
 }
#ifdef CONFIG_HIGHMEM
        //如果是高端内存,还要进行进一步支持的确认,vipt的不支持
 if (highmem) {
  const char *reason = NULL;


  if (cache_is_vipt_aliasing()) {
   /*
    * Interactions between kmap and other mappings
    * make highmem support with aliasing VIPT caches
    * rather difficult.
    */
   reason = “with VIPT aliasing cache”;
  }
  if (reason) {
   printk(KERN_CRIT “HIGHMEM is not supported %s, ignoring high memory\n”,
    reason);
   while (j > 0 && meminfo.bank[j – 1].highmem)
    j–;
  }
 }
#endif
 meminfo.nr_banks = j;
 memblock_set_current_limit(lowmem_limit);
}



这里其中vmalloc_vin 定义为static void * __initdata vmalloc_min = (void *)(VMALLOC_END – SZ_128M);
而vmalloc_end在2440上定义为arch/arm/mach-s3c2410/include/mach/vmalloc.h
#define VMALLOC_END 0xF6000000UL

上面又提到了meminfo看来不解决他也不行了,
先看定义,这个东西大概是这个位置,
arch/arm/kernel/setup.c–>setup_arch–>setup_machine_tags
这个函数中


if (mdesc->fixup)            //一种方法,可惜2440没有
  mdesc->fixup(tags, &from, &meminfo);


 if (tags->hdr.tag == ATAG_CORE) {
  if (meminfo.nr_banks != 0)
   squash_mem_tags(tags);
  save_atags(tags);
  parse_tags(tags);        //另一个地方
 }


跟进去最终会到这里
/*
 * Scan the tag table for this tag, and call its parse function.
 * The tag table is built by the linker from all the __tagtable
 * declarations.
 */
static int __init parse_tag(const struct tag *tag)
{
 extern struct tagtable __tagtable_begin, __tagtable_end;
 struct tagtable *t;


 for (t = &__tagtable_begin; t < &__tagtable_end; t++)
  if (tag->hdr.tag == t->tag) {
   t->parse(tag);
   break;
  }


 return t < &__tagtable_end;
}


__tagtable_begin同样单独的一个段,定义在arch/arm/vmlinux.lds,
__arch_info_begin = .;
            *(.arch.info)
        __arch_info_end = .;
        __tagtable_begin = .;
            *(.taglist)
        __tagtable_end = .;
            *(.data.init)
        . = ALIGN(16);
其中同文件下
tatic int __init parse_tag_mem32(const struct tag *tag)
{
 return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
}


__tagtable(ATAG_MEM, parse_tag_mem32);


又有
#define __tag __used __attribute__((__section__(“.taglist.init”)))
#define __tagtable(tag, fn) \
static const struct tagtable __tagtable_##fn __tag = { tag, fn }


可见parse_tag_mem32就被定义于这个段,那么就会调用它,跟进去又会调用arm_add_memory(tag->u.mem.start, tag->u.mem.size);这个是我们的重点函数,会把参数列表传递过来的内存信息对齐后打包到meminfo,找到了meminfo怎么来的,回来再继续看刚才剩下的一个函数,arm_memblock_init(&meminfo, mdesc);这个函数比较简单,这里就不贴出来了,主要是把刚才得到的内存布局中已经使用的部分标记出来比如kernel占用部分,异常表占用部分等等…


总结:分析了上文遗留的两个结构memblock以及meminfo,bootmem结构到现在应当很清晰了,下文会简单分析下具体的bootmem的分配内存
函数 ^.^!

赞(0) 打赏
转载请注明出处:服务器评测 » Linux内存模型之bootmem分配器<二>
分享到: 更多 (0)

听说打赏我的人,都进福布斯排行榜啦!

支付宝扫一扫打赏

微信扫一扫打赏