Linux初始化内核临时页表之后的setup_memory函数
2009-12-20 23:44
477 查看
话说在linux内核初始化完内核临时页表来映射前8MB内存后,在欲望的驱使下,linux开始着手抢占
896MB以下的内存了。然而抢夺这896MB内存绝非易事。linux还有许多麻烦的事要做。比如说进攻和占领伊拉克等等。于是
setup_memory函数开始为linux策划和筹备此事。主要任务是建立一张与物理内存页框号对应的位图。如果该页框被占用则对应位图中的位被置
1,否则置0。在伙伴系统建立前对内存进行临时管理。在初始化内核最终页表时alloc_bootmem_low_pages内存分配函数就用到了这个位
图。
核心数据结构:
896MB以下的内存了。然而抢夺这896MB内存绝非易事。linux还有许多麻烦的事要做。比如说进攻和占领伊拉克等等。于是
setup_memory函数开始为linux策划和筹备此事。主要任务是建立一张与物理内存页框号对应的位图。如果该页框被占用则对应位图中的位被置
1,否则置0。在伙伴系统建立前对内存进行临时管理。在初始化内核最终页表时alloc_bootmem_low_pages内存分配函数就用到了这个位
图。
核心数据结构:
typedef struct bootmem_data { unsigned long node_boot_start; /* 起始页框号0 */ unsigned long node_low_pfn; /* 如果物理内存大于896MB,node_low_pfn为0x37FFF。 如果物理内存小于等于896MB,node_low_pfn为物理内 存的最大页框号。*/ void *node_bootmem_map; /* 位图的起始地址 */ /* 下面三个变量的作用用于alloc_bootmem_low_pages函数 */ unsigned long last_offset; unsigned long last_pos; unsigned long last_success; } bootmem_data_t ; 创建位图的函数流程: start_kernel->setup_arch->setup_memory->init_bootmem ->init_bootmem_core linux/arch/i386/kernel/setup.c 在setup_memory()中执行 start_pfn = PFN_UP(init_pg_tables_end); /* start_pfn是指映射8MB所用页表之后第一个页框号。 PFN_UP的作用是把地址按页的大小进行对齐。也就是地址是4kb的整数倍大小。*/ find_max_pfn(); /* 找到物理内存中最大页框号。放入max_pfn中。*/ max_low_pfn=find_max_low_pfn(); /* 如果物理地址小于等于896MB,max_low_pfn=max_pfn。大于896MB时, max_low_pfn为896MB内存大小的最大页框号 */ bootmap_size = init_bootmem(start_pfn,max_low_pfn); 进入init_bootmem中 unsigned long __init init_bootmem (unsigned long start , unsigned long pages) { max_low_pfn = pages; min_low_pfn = start ; return( init_bootmem_core ( NODE_DATA (0), start , 0, pages)); } 再从init_bootmem 进入 init_bootmem_core 中,此函数创建位图 static unsigned long __init init_bootmem_core ( pg_data_t *pgdat, unsigned long mapstart, unsigned long start , unsigned long end ) { bootmem_data_t *bdata = pgdat->bdata; unsigned long mapsize = (( end - start )+7)/8; /* mapsize为要创建的位图的大小 */ pgdat->pgdat_next = pgdat_list ; pgdat_list = pgdat; mapsize = (mapsize + (sizeof(long) - 1UL)) & ~(sizeof(long) - 1UL); /* 按照4个字节大小进行对齐 */ bdata->node_bootmem_map = phys_to_virt (mapstart << PAGE_SHIFT ); /* bdata->node_bootmem_map 为位图的起始位置的线性地址 */ bdata->node_boot_start = ( start << PAGE_SHIFT ); /* 第一个页框的起始地址,就是0号页框的起始地址0x00000000 */ bdata->node_low_pfn = end ; memset (bdata->node_bootmem_map, 0xff, mapsize); /* 把位图中的每一位都置1,表示为占用状态。在接下去的函数中,会把内核可以使用的页框号对应的位置0。 */ return mapsize; } 回到setup_memory中,接着执行 register_bootmem_low_pages ( max_low_pfn ); 此函数的主要的功能是把内核可以使用的页框号(最大为max_low_pfn )在位图中对应的位置0。 由于有些页已经被内核数据占用,所以还要把这些页再置为1。就是调用 reserve_bootmem ( HIGH_MEMORY , ( PFN_PHYS (start_pfn) + bootmap_size + PAGE_SIZE -1) - ( HIGH_MEMORY )); 此函数把从1MB开始(HIGH_MEMORY定义为1024*1024)到位图结束所占用的页框号在位图中对应的位置1。 然后根据不同的硬件配置再做一些扫尾的工作。 return max_low_pfn; setup_memory函数结束。 接着linux就会调用paging_init来完成它对896MB内存的抢夺了。
相关文章推荐
- linux-3.2.36内核启动3-setup_arch中的内存初始化2(arm平台 分析建立页表)
- linux-3.2.36内核启动3-setup_arch中的内存初始化2(arm平台 分析建立页表)
- ARM Linux 内核启动总结 之 创建临时页表
- Linux内核代码之初始化内核临时页表---经典至极(转)
- 全面解析Linux 内核 3.10.x - 板级初始化 - setup_arch
- linux-3.2.36内核启动2-setup_arch中的内存初始化1(arm平台 分析高端内存和初始化memblock)
- linux临时页表初始化
- linux-3.2.36内核启动4-setup_arch中的内存初始化3(arm平台 bootmem_init源码分析)
- Linux 内核页表初始化
- linux-3.2.36内核启动4-setup_arch中的内存初始化3(arm平台 bootmem_init源码分析)
- Linux 内核临时页表的创建
- arm-linux内存管理学习笔记(2)-内核临时页表的建立
- Linux内核代码之初始化内核临时页表
- Linux0.11内核--启动代码分析setup.s 建立页目录和页表
- Linux0.11内核--启动代码分析setup.s 建立页目录和页表
- Linux内核代码之初始化内核临时页表---经典至极(FutureChen的日记)
- linux-3.2.36内核启动2-setup_arch中的内存初始化1(arm平台 分析高端内存和初始化memblock)【转】
- Linux内核代码之初始化内核临时页表---经典至极
- linux 内核 内存管理 初始化 页表
- linux-3.2.36内核启动2-setup_arch中的内存初始化1(arm平台 分析高端内存和初始化memblock)