专栏名称: Jiau
目录
相关文章推荐
兰州大学萃英在线  ·  lzuer们,请查收这份安全指南! ·  3 天前  
每日经济新闻  ·  刚刚,字节跳动出手:辞退353人! ·  3 天前  
每日经济新闻  ·  张学友,突发! ·  3 天前  
每日豆瓣  ·  三十岁才知道的,后悔没早些明白的道理 ·  4 天前  
51好读  ›  专栏  ›  Jiau

Linux内核源码分析之setup_arch (二)

Jiau  · 掘金  ·  · 2021-05-18 18:32

正文

阅读 39

Linux内核源码分析之setup_arch (二)

1. 概述

接着上一篇《Linux内核源码分析之setup_arch (一)》继续分析,本文首先分析arm_memblock_init函数,然后分析内核启动阶段的是如何进行内存管理的。

2. arm_memblock_init

该函数的功能比较简单,主要就是把meminfo中记录的内存条信息添加到memblock.memory中,然后把内核镜像所在内存区域添加到memblock.reserved中,arm_mm_memblock_reserve把页表所在内存区域添加到memblock.reserved中;如果使用了设备树,则使用arm_dt_memblock_reserve来保留所占用的内存,最后则是调用CPU相关的mdesc->reserve,其对应的调用为cpu_mem_reserve,该函数定义在cpu.c中。

/* arch/arm/mm/init.c */
void __init arm_memblock_init(...) {
  for (i = 0; i < mi->nr_banks; i++)
    memblock_add(mi->bank[i].start, mi->bank[i].size);

  memblock_reserve(__pa(_stext), _end - _stext);
  arm_mm_memblock_reserve();
  arm_dt_memblock_reserve();

  if (mdesc->reserve)
    mdesc->reserve();

  arm_memblock_steal_permitted = false;
  memblock_allow_resize();
  memblock_dump_all();
}
/* include/kernel/memblock.h */
struct memblock {
 phys_addr_t current_limit;
 struct memblock_type memory;
 struct memblock_type reserved;
};
复制代码

3. memblock_alloc

接下来就该执行paging_init函数了,在分析paging_init之前先来点内核启动阶段的内存管理相关的内容。从arm_memblock_init开始引入memblock数据结构,其作用是实现内核启动初期的内存管理功能,严格来说,其生命周期到paging_init::bootmem_init为止,memblock_alloc调用流程如下。

实际查找空闲内存的函数为memblock_find_in_range_node,而该函数中真正实现空闲内存查找的是for_each_free_mem_range_reverse这个宏定义。

/* mm/memblock.c */
phys_addr_t memblock_find_in_range_node(...)
{
 ...
 for_each_free_mem_range_reverse(i, nid, &this_start, &this_end, NULL) {
      ...
      if (cand >= this_start)
        return cand;
 }
 return 0;
}
复制代码

该宏定义如下,然而其中又嵌套了一个函数Orz...

/* include/linux/memblock.h */
#define for_each_free_mem_range_reverse(i, nid, p_start, p_end, p_nid) \
 for (i = (u64)ULLONG_MAX,                                             \
      __next_free_mem_range_rev(&i, nid, p_start, p_end, p_nid);       \
      i != (u64)ULLONG_MAX;                                            \
      __next_free_mem_range_rev(&i, nid, p_start, p_end, p_nid))
复制代码

首先需要说明的是,memblock.reserved标识的区域表示的是已被占用的内存区域,memblock.memory中记录的是内存条信息。现在回到__next_free_mem_range_rev函数,代码段(1)(2)的目的是找出内存条上两个reserved区域之间的内存区域,即空闲区域。找到之后再经过代码段(3)对空闲区域的起始地址和结束地址进行修正,因为代码段(1)(2)只能保证空闲区与当前内存条存在交集,并不能保证该空闲区域完全处于当前内存条之中,主要原因在于无法保证这两个reserved区域都在当前内存条上。

/* mm/memblock.c */
void __init_memblock __next_free_mem_range_rev(...)
{
 struct memblock_type *mem = &memblock.memory;
 struct






请到「今天看啥」查看全文