linux物理内存管理区初始化

 

Linux物理内存管理区在start_kernel函数中进行初始化,此时启动分配器已经建立,所以可以从bootmem中分配需要的内存。

一、全局变量初始化

max_pfn:最大物理页面帧号

start_kernel()->setup_arch()->e820_end_of_ram_pfn()找出最大可用内存页面帧号。

void __init setup_arch(char **cmdline_p)
{
	……
/*
	 * partially used pages are not usable - thus
	 * we are rounding upwards:
	 */
	/*遍历e820.map,找到系统中得最大内存数,
	这个内存数需小于4G*/
	max_pfn = e820_end_of_ram_pfn();
	……
}
unsigned long __init e820_end_of_ram_pfn(void)
{
	/*MAX_ARCH_PFN为4G空间*/
	return e820_end_pfn(MAX_ARCH_PFN, E820_RAM);
}
/*
 * Find the highest page frame number we have available
 */
static unsigned long __init e820_end_pfn(unsigned long limit_pfn, unsigned type)
{
	int i;
	unsigned long last_pfn = 0;
	unsigned long max_arch_pfn = MAX_ARCH_PFN;/*4G地址空间对应的页面数*/

	/*对e820中所有的内存块,其中e820为从bios中探测到的页面数存放处*/
	for (i = 0; i < e820.nr_map; i++) {
		struct e820entry *ei = &e820.map[i];/*第i个物理页面块*/
		unsigned long start_pfn;
		unsigned long end_pfn;

		if (ei->type != type)/*与找的类型不匹配*/
			continue;
		/*起始地址对应的页面帧号*/
		start_pfn = ei->addr >> PAGE_SHIFT;
       	/*结束物理地址对应的页面帧号*/
		end_pfn = (ei->addr + ei->size) >> PAGE_SHIFT;

		if (start_pfn >= limit_pfn)
			continue;
		if (end_pfn > limit_pfn) {
			last_pfn = limit_pfn;/*找到的结束页面帧号大于限制大小时*/
			break;
		}
		if (end_pfn > last_pfn)
			last_pfn = end_pfn;/*保存更新last_pfn*/
	}

	if (last_pfn > max_arch_pfn)/*大于4G空间时*/
		last_pfn = max_arch_pfn;
	/*打印输出信息*/
	printk(KERN_INFO "last_pfn = %#lx max_arch_pfn = %#lx\n",
			 last_pfn, max_arch_pfn);
	/*返回最后一个页面帧号*/
	return last_pfn;
}

max_low_pfn:低端内存最大页面数

start_kernel()->setup_arch()->find_low_pfn_range()

/*
 * Determine low and high memory ranges:
 */
/*找到低端内存的做大内存页面数,初始化两个变量*/
void __init find_low_pfn_range(void)
{
	/* it could update max_pfn */
	/*当内存的大小本来就小于低端内存的做大页框数时;
	直接没有高端地址映射*/
	if (max_pfn <= MAXMEM_PFN)
		lowmem_pfn_init();
	else/*这是一般PC机的运行流程,存在高端映射*/
		highmem_pfn_init();
}

我们直接看具有高端地址空间的部分。

/*
 * We have more RAM than fits into lowmem - we try to put it into
 * highmem, also taking the highmem=x boot parameter into account:
 */
 /*高端地址空间的页面数可以在启动中进行配置;
 如果不配置,在这里进行设置大小*/
void __init highmem_pfn_init(void)
{
	/*MAXMEM_PFN为最大物理地址-(4M+4M+8K+128M);
	所以低端内存的大小其实比我们说的896M低一些*/
	max_low_pfn = MAXMEM_PFN;

	if (highmem_pages == -1)/*高端内存页面数如果在开机没有设置*/
		highmem_pages = max_pfn - MAXMEM_PFN;/*总页面数减去低端页面数*/
	/*如果highmem_pages变量在启动项设置了,那么在这里就要进行这样的判断,因为可能出现不一致的情况*/
	if (highmem_pages + MAXMEM_PFN < max_pfn)
		max_pfn = MAXMEM_PFN + highmem_pages;

	if (highmem_pages + MAXMEM_PFN > max_pfn) {
		printk(KERN_WARNING MSG_HIGHMEM_TOO_SMALL,
			pages_to_mb(max_pfn - MAXMEM_PFN),
			pages_to_mb(highmem_pages));
		highmem_pages = 0;
	}
#ifndef CONFIG_HIGHMEM
	/* Maximum memory usable is what is directly addressable */
	printk(KERN_WARNING "Warning only %ldMB will be used.\n", MAXMEM>>20);
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值