static unsigned long __init bootmem_init_node(int node, struct meminfo *mi)

in arch/arm/mm/init.c

1.1 根据内存信息重新映射页表,此处为低端内存的线性映射

  -->map_memory_bank(bank);

    -->create_mapping(&map);

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

        -->/*如果地址按SECTION对齐,只需一级页表,映射1MB空间*/

        /*如果地址不是SECTION对齐,需二级页表*/

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

          /*最终调用的是proc_info_list->proc->set_pte_ext,汇编代码在arch/arm/mm/proc-macros.S*/

          -->set_pte_ext(pte, pfn_pte(pfn, __pgprot(type->prot_pte)), );

map_memory_bank(bank)

1.2 Allocate the bootmem bitmap page

bootmem分配器用每一bit表示一个物理页框的使用情况,该函数计算表示所有的物理页框共需申请多少页的内存。

函数以总的物理页框数为输入参数,返回bitmap需要使用的页数。

/*

Convert a physical address to a Page Frame Number and back

#define __phys_to_pfn(paddr) ((paddr) >> PAGE_SHIFT)
#define __pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT) end_pfn,start_pfn物理内存的起止页框号, */
/**
* bootmem_bootmap_pages - calculate bitmap size in pages
* @pages: number of pages the bitmap has to represent
*/
unsigned long __init bootmem_bootmap_pages(unsigned long pages)
{
unsigned long bytes = bootmap_bytes(pages); return PAGE_ALIGN(bytes) >> PAGE_SHIFT;
}
static unsigned long __init bootmap_bytes(unsigned long pages)
{
unsigned long bytes = (pages + ) / ; return ALIGN(bytes, sizeof(long));
}

bootmem_bootmap_pages

1.3 boot_pfn = find_bootmap_pfn(node, mi, boot_pages);

寻找1.2中计算出的bitmap使用的若干页该对应到物理页框的什么位置。寻找的依据是从kernel的bss段结束位置开始寻找,找到能够放置bootmap_pages个页框的内存位置。

static unsigned int __init
find_bootmap_pfn(int node, struct meminfo *mi, unsigned int bootmap_pages)
{
unsigned int start_pfn, i, bootmap_pfn; start_pfn = PAGE_ALIGN(__pa(_end)) >> PAGE_SHIFT;
bootmap_pfn = ; for_each_nodebank(i, mi, node) {
struct membank *bank = &mi->bank[i];
unsigned int start, end; start = bank_pfn_start(bank);
end = bank_pfn_end(bank); if (end < start_pfn)
continue; if (start < start_pfn)
start = start_pfn; if (end <= start)
continue; if (end - start >= bootmap_pages) {
bootmap_pfn = start;
break;
}
} if (bootmap_pfn == )
BUG(); return bootmap_pfn;
}

find_bootmap_pfn

1.4 init_bootmem_node

初始化pg_data_t->bdtat结构体,

将不同node的bdata添加到以bdata_list为首的链表。标记所有的bitmap位为1。

/*
* node_bootmem_map is a map pointer - the bits represent all physical
* memory pages (including holes) on the node.
*/
typedef struct bootmem_data {
unsigned long node_min_pfn;
unsigned long node_low_pfn;
void *node_bootmem_map;
unsigned long last_end_off;
unsigned long hint_idx;
struct list_head list;
} bootmem_data_t;
/*
* Called once to set up the allocator itself.
*/
static unsigned long __init init_bootmem_core(bootmem_data_t *bdata,
unsigned long mapstart, unsigned long start, unsigned long end)
{
unsigned long mapsize; mminit_validate_memmodel_limits(&start, &end);
bdata->node_bootmem_map = phys_to_virt(PFN_PHYS(mapstart));
bdata->node_min_pfn = start;
bdata->node_low_pfn = end;
link_bootmem(bdata); /*
* Initially all pages are reserved - setup_arch() has to
* register free RAM areas explicitly.
*/
mapsize = bootmap_bytes(end - start);
memset(bdata->node_bootmem_map, 0xff, mapsize); bdebug("nid=%td start=%lx map=%lx end=%lx mapsize=%lx\n",
bdata - bootmem_node_data, start, mapstart, end, mapsize); return mapsize;
} init_bootmem_core

init_bootmem_core

1.5 free_bootmem_node(pgdat, bank_phys_start(bank), bank_phys_size(bank));

把节点下所有的页框对应的bitmap位都设为0,标记为空闲。

这里最终调用bootmem底层的__free函数和__reserve函数。

static int __init mark_bootmem_node(bootmem_data_t *bdata,            unsigned long start, unsigned long end,int reserve, int flags)
{
unsigned long sidx, eidx; bdebug("nid=%td start=%lx end=%lx reserve=%d flags=%x\n",
bdata - bootmem_node_data, start, end, reserve, flags); BUG_ON(start < bdata->node_min_pfn);
BUG_ON(end > bdata->node_low_pfn); sidx = start - bdata->node_min_pfn;
eidx = end - bdata->node_min_pfn; if (reserve)
return __reserve(bdata, sidx, eidx, flags);
else
__free(bdata, sidx, eidx);
return ;
}
static int __init __reserve(bootmem_data_t *bdata, unsigned long sidx,
unsigned long eidx, int flags)
{
unsigned long idx;
int exclusive = flags & BOOTMEM_EXCLUSIVE; bdebug("nid=%td start=%lx end=%lx flags=%x\n",
bdata - bootmem_node_data,
sidx + bdata->node_min_pfn,
eidx + bdata->node_min_pfn,
flags); for (idx = sidx; idx < eidx; idx++)
if (test_and_set_bit(idx, bdata->node_bootmem_map)) {
if (exclusive) {
__free(bdata, sidx, idx);
return -EBUSY;
}
bdebug("silent double reserve of PFN %lx\n",
idx + bdata->node_min_pfn);
}
return ;
}

__reserve

static void __init __free(bootmem_data_t *bdata,
unsigned long sidx, unsigned long eidx)
{
unsigned long idx; bdebug("nid=%td start=%lx end=%lx\n", bdata - bootmem_node_data,
sidx + bdata->node_min_pfn,
eidx + bdata->node_min_pfn); if (bdata->hint_idx > sidx)
bdata->hint_idx = sidx; for (idx = sidx; idx < eidx; idx++)
if (!test_and_clear_bit(idx, bdata->node_bootmem_map))
BUG();
}

__free

1.6 在bitmap中标记bitmap所占用的页框为使用状态

    /*
* Reserve the bootmem bitmap for this node.
*/
reserve_bootmem_node(pgdat, boot_pfn << PAGE_SHIFT, boot_pages << PAGE_SHIFT, OOTMEM_DEFAULT);

bootmem_init_node的更多相关文章

  1. Uboot与Linux之间的参数传递

    U-boot会给Linux Kernel传递很多参数,如:串口,RAM,videofb等.而Linux kernel也会读取和处理这些参数.两者之间通过struct tag来传递参数. U-boot把 ...

  2. linux内存管理初始化

    内存管理子系统是linux内核最核心最重要的一部分,内核的其他部分都需要在内存管理子系统的基础上运行.而对其初始化是了解整个内存管理子系统的基础.对相关数据结构的初始化是从全局启动例程start_ke ...

  3. 内存管理 初始化(二)bootmem位图分配器建立 及 使用

    本地的笔记有点长,先把bootmem位图分配器的建立 及  使用过程做下梳理. 都是代码,上面做了标注.开始的汇编部分省略了(涉及的内容不多,除了swapper_pg_dir的分配). 该记录不会再添 ...

  4. ARM Linux内核源码剖析索引

    start_kernel -->asm-offset.h 生成 -->proc_info_list   -->machine_desc -->__vet_atags --> ...

随机推荐

  1. openstack修改增加网卡及更改ip

        1.neutron更改及mysql数据库更改网卡及ip:     neutron port-update ae22c84b-22a9-4618-b046-1eb61379bcea  --all ...

  2. hubbledotnet 使用笔记

    Hubble vs 字符串 <connectionStrings> <add name="Search" connectionString="serve ...

  3. windows下利用intellij idea等工具开发erlang

    今天突然想在家里去年新买的电脑上写点erlang代码,然后可耻的发现家里的电脑上竟然没有开发环境,果然是去年6月以后没写过erlang代码么╮(╯▽╰)╭?        首先下载需要用的几样东西:  ...

  4. 基本类型包装类、System类、Math类、Arrays类、大数据运算

    1 基本类型包装类 Java中想对8种基本数据类型进行复杂操作很困难. 实际程序界面上用户输入的数据都是以字符串类型进行存储的. 程序开发中,需要把字符串转换成指定的基本数据类型. 1.1基本数据类型 ...

  5. iOS 最新判断机型设备方法

    #define isIphoneXXS [UIScreen mainScreen].bounds.size.width == 375  && [UIScreen mainScreen] ...

  6. Python之查询最新的文件

    import os # 定义文件的目录 result_dir = r'E:\python\测试报告' lists = os.listdir(result_dir) # 重新按时间对目录下的文件进行排序 ...

  7. 【Python图像特征的音乐序列生成】GitHub已经有人将mingus改到了Python3版本

    https://github.com/bspaans/python-mingus/issues/45 注意此时的安装方法应该是: git clone https://github.com/edudob ...

  8. python爬虫之路——正则表达式初识

    正则表达式:是一个特殊的符号系列,检查字符串是否与指定模式匹配. python中的re模块拥有全部的正则表达式功能. 判断字符: 类型: 数目:有无:   个数:单值     区间      离散 判 ...

  9. codeforce Gym 100685F Flood (topo排序)

    如果直接模拟水向周围流会TLE,因为某些个结点被重复扩展了多次, 科学做法是topo排序,每次只把入度为0的点放入队列,这样就严格保证了每个结点只被扩展一次. #include<bits/std ...

  10. [Tracking] KCF + KalmanFilter目标跟踪

    基于KCF和MobileNet V2以及KalmanFilter的摄像头监测系统 简介 这是一次作业.Tracking这一块落后Detection很多年了,一般认为Detection做好了,那么只要能 ...