bootmem_init_node
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的更多相关文章
- Uboot与Linux之间的参数传递
U-boot会给Linux Kernel传递很多参数,如:串口,RAM,videofb等.而Linux kernel也会读取和处理这些参数.两者之间通过struct tag来传递参数. U-boot把 ...
- linux内存管理初始化
内存管理子系统是linux内核最核心最重要的一部分,内核的其他部分都需要在内存管理子系统的基础上运行.而对其初始化是了解整个内存管理子系统的基础.对相关数据结构的初始化是从全局启动例程start_ke ...
- 内存管理 初始化(二)bootmem位图分配器建立 及 使用
本地的笔记有点长,先把bootmem位图分配器的建立 及 使用过程做下梳理. 都是代码,上面做了标注.开始的汇编部分省略了(涉及的内容不多,除了swapper_pg_dir的分配). 该记录不会再添 ...
- ARM Linux内核源码剖析索引
start_kernel -->asm-offset.h 生成 -->proc_info_list -->machine_desc -->__vet_atags --> ...
随机推荐
- C#微信支付
回归主题,16年1月初我对微信开发比较好奇,由于自己是一个比较喜欢钱的人,所以对支付功能颇为冲动,就用公司信息在微信平台申请了一个服务号,还给腾讯打赏了300大洋做了下认证,抽空看了下微信支付官方的文 ...
- VS2010/OpenGL配置
1.下载glut:http://www.opengl.org/resources/libraries/glut/glutdlls37beta.zip 2.把解压得到的glut.h放到"C:\ ...
- 【Unity3D】资源对象、预设、查找对象、组合模式等知识点
1.解释对象与资源区别于联系,根据官方案例,分别总结资源和对象组织的规则/规律. 下载并查看了Adam和Survival Shooter tutorial两个官方资源案例,这些案例作为资源,可以 ...
- countUp 动画展示数字变化
html <p id="countUp" style="font-size:25px;height:25px;background-color:#0aa;" ...
- python os,sys模块的使用
首先,os模块是用来与操作系统进行交互的模块,可以对操作系统上的一些东西进行操作 而sys是用来对解释器进行一些操作的 一.os os.getcwd() 获取当前工作目录,即当前python脚本工作的 ...
- 网站安全webshell扫描
做个记录,使用Detector进行php网站webshell扫描 开源项目托管地址:https://github.com/emposha/PHP-Shell-Detector安装使用都很简单
- NVM for Windows下载与安装
下载NVM for Windows https://github.com/coreybutler/nvm-windows/releases nvm-noinstall.zip: 这个是绿色免安装版本, ...
- COGS 147. [USACO Jan08] 架设电话线
★★☆ 输入文件:phoneline.in 输出文件:phoneline.out 简单对比时间限制:1 s 内存限制:16 MB Farmer John打算将电话线引到自己的农场,但电 ...
- 编写C#程序,自动将bing首页图片设为壁纸
任务目标: 1,获取图片 2,设为壁纸 3,自动化 环境需求: .NET Framework 4.0+, Visual Studio 2017 ==================== 1,获取图片 ...
- 【TensorFlow入门完全指南】神经网络篇·MLP多层感知机
前面的不做过多解释了. 这里定义了两个占位符,各位也知道,在训练时,feed_dict会填充它们. 定义相关网络. 这里是权值矩阵和偏差. 这里是实例化了网络,定义了优化器和损失,和上一篇一样. 最后 ...