上一篇微博留下了这几个函数,现在我们来分析它们

        sanity_check_meminfo();

        arm_memblock_init(&meminfo, mdesc);

        paging_init(mdesc);

        request_standard_resources(mdesc);

在上一微博有展现根据启动参数初始化meminfo,记录了物理内存的开始和大小

sanity_check_meminfo();

有mmu的情况下这个函数才有意义,初始化高端内存,首先内核要选上这个

KernelFeatures下的

[*]High Memory Support

arch/arm/include/asm/setup.h

#ifdef CONFIG_ARCH_EP93XX

# define NR_BANKS 16

#else

#endif

struct membank {

phys_addr_t start;

unsigned longsize;

unsigned inthighmem;

};如果是高端内存highmem为1

struct meminfo {

int nr_banks;

struct membankbank[NR_BANKS];

};

extern struct meminfo meminfo;

我们现在的函数就是初始化meminfo这个全局变量

高端内存

linux内核的地址空间是3G~4G。假如说机器的内存为512M,那么内存的物

理地址范围是:0~512,而映射到内核空间的范围是3G~3G+512M(可以叫low memory).

+512G~4G,但是为了避免越界等安全问题

的考虑,高端内存又离开了低端内存8M空间,即从3G+512M+8M空间开始。linux内核又规定,高端内存至少为128M,即加入物理内存为1G,那么高端内存就是从896M~4G,即其最大地址:0xC0000000+896M,实际:0xC0000000+x(内存size)

简单举个例子,假设你有2G内存,而内核只有1G不能全部做线性映射,内核就会把前896M用于RAM线性映射,后128M可以通过更改映射关系访问剩下的内存。有三种方法:永久内核映射,临时映射,非连续内存分配(这些以后写关于内存管理的文章时再分析)。

没有全部贴

void __init sanity_check_meminfo(void)

{

int i, j, highmem= 0;

//wxl add

printk(KERN_NOTICE"vmalloc_min = %lx\n", vmalloc_min);

打印结果

vmalloc_min = ee000000

vmalloc_min = (void *)(VMALLOC_END - SZ_128M);

arch/arm/mach-s3c2410/include/mach/vmalloc.h
#define VMALLOC_END 0xF6000000UL

0xF6000000-0x8000000=0xEE000000

3808M

for (i = 0, j = 0;i < meminfo.nr_banks; i++) {

structmembank *bank = &meminfo.bank[j];

*bank =meminfo.bank[i];

#ifdef CONFIG_HIGHMEM

_va()是物理地址转换虚拟地址

#define __virt_to_phys(x)      ((x) - PAGE_OFFSET + PHYS_OFFSET)

#define __phys_to_virt(x)      ((x) - PHYS_OFFSET + PAGE_OFFSET)

#define __va(x)                ((void *)__phys_to_virt((unsigned long)(x)))

下面的条件告诉了我们高端地址范围,大于等于vmalloc_min的好理解,小于PAGE_OFFSET大概就是高端内存没有一次全部映射到内核空间,所以有低于PAGE_OFFSET的高端内存

if(__va(bank->start) >= vmalloc_min ||

__va(bank->start) < (void *) PAGE_OFFSET)

highmem = 1;

//wxl add

printk(KERN_NOTICE "start:bank->start = %lx bank->size = %lx __va = %lx highmem = %d\n",(unsigned long)bank->start, (unsigned long)bank->size, (unsignedlong)__va(bank->start), highmem);

打印结果

start: bank->start = 30000000 bank->size = 4000000 __va =c0000000 highmem = 0

bank->start bank->size就是上一篇微博提到的

bank->highmem = highmem;

/*

* Splitthose memory banks which are partially overlapping

* thevmalloc area greatly simplifying things later.

*/

 假设__va(bank->start) < vmalloc_min;它的大小可能会超过低端内存,也就是起始地址在低端,结束地址超过低端范围,那么就要把它分开,你可以简单看看代码

if(__va(bank->start) < vmalloc_min &&

bank->size > vmalloc_min - __va(bank->start)) {

if(meminfo.nr_banks >= NR_BANKS) {

printk(KERN_CRIT "NR_BANKS too low, "

"ignoringhigh memory\n");

}else {

memmove(bank + 1, bank,

(meminfo.nr_banks - i) * sizeof(*bank));

meminfo.nr_banks++;

i++;

bank[1].size -= vmalloc_min - __va(bank->start);

bank[1].start = __pa(vmalloc_min - 1) + 1;

bank[1].highmem = highmem = 1;

j++;

}

bank->size = vmalloc_min - __va(bank->start);

}

//wxl add

printk(KERN_NOTICE "end: bank->start = %lx bank->size =%lx\n", (unsigned long)bank->start, (unsigned long)bank->size);

打印结果

end: bank->start = 30000000 bank->size = 4000000

#else

……

#endif

重设低端内存限制

if(!bank->highmem && bank->start + bank->size > lowmem_limit)

lowmem_limit =bank->start + bank->size;

j++;

}

……

未完待续,,,

[置顶] linux内核启动2-setup_arch中的内存初始化(目前分析高端内存)的更多相关文章

  1. [置顶] linux内核启动1-启动参数(启动参数的获取和处理,分析setup_arch)

    最近公司要求调试一个内核,启动时有问题,所以就花了一点时间看看内核启动. 看的过程中总结了一点东西,希望可以帮助大家调试内核. 当我开始看的时候,第一件事是从网上搜集资料,不看不知道,一看吓一跳!牛人 ...

  2. linux内存(二)高端内存

    来此网址 https://ilinuxkernel.com/?p=1013 Linux内核地址映射模型x86 CPU采用了段页式地址映射模型.进程代码中的地址为逻辑地址,经过段页式地址映射后,才真正访 ...

  3. linux-3.2.36内核启动2-setup_arch中的内存初始化1(arm平台 分析高端内存和初始化memblock)【转】

    转自:http://blog.csdn.net/tommy_wxie/article/details/17093307 上一篇微博留下了这几个函数,现在我们来分析它们         sanity_c ...

  4. Linux内核启动分析

    张超<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 我的代码可见https://www.shiyanlo ...

  5. Linux用户空间与内核空间(理解高端内存)

    Linux 操作系统和驱动程序运行在内核空间,应用程序运行在用户空间,两者不能简单地使用指针传递数据,因为Linux使用的虚拟内存机制,用户空间的数据可能被换出,当内核空间使用用户空间指针时,对应的数 ...

  6. linux 用户空间与内核空间——高端内存详解

    摘要:Linux 操作系统和驱动程序运行在内核空间,应用程序运行在用户空间,两者不能简单地使用指针传递数据,因为Linux使用的虚拟内存机制,用户空间的数据可能被换出,当内核空间使用用户空间指针时,对 ...

  7. Linux用户空间与内核空间(理解高端内存)【转】

    转自:http://www.cnblogs.com/wuchanming/p/4360277.html Linux 操作系统和驱动程序运行在内核空间,应用程序运行在用户空间,两者不能简单地使用指针传递 ...

  8. 高端内存映射之kmap持久内核映射--Linux内存管理(二十)

    1 高端内存与内核映射 尽管vmalloc函数族可用于从高端内存域向内核映射页帧(这些在内核空间中通常是无法直接看到的), 但这并不是这些函数的实际用途. 重要的是强调以下事实 : 内核提供了其他函数 ...

  9. Linux内核高端内存 转

        Linux内核地址映射模型x86 CPU采用了段页式地址映射模型.进程代码中的地址为逻辑地址,经过段页式地址映射后,才真正访问物理内存. 段页式机制如下图.   Linux内核地址空间划分 通 ...

随机推荐

  1. python 函数初识和文件操作

    文件操作  打开文件:文件句柄 = open('文件路径', '模式')  打开文件的模式 w #以写的方式打开 (不可读,不存在则创建,存在则删除内容) a #以追加的模式打开(可读, 不存在则创建 ...

  2. PHP负载均衡

    待更新 版权声明:本文为博主原创文章,未经博主允许不得转载.

  3. 在MessageBox的Show方法中如何无限使用参数值?

    今天发现在show方法中不能使用花括号的方式使用多个可变参数,经过查询得出结果.在show方法中是不存在花括号的方式使用参数的.在Console.WriteLine中是存在的,如下: 那么在show方 ...

  4. a标签的简单用法

    1.href="#"的作用:页面中有滚动,可以直接回到顶部. <a href="#">回到最顶端</a> 2.href="ur ...

  5. SQL语句操作文件

    -----先开启命令exec sp_configure 'show advanced options', 1; reconfigure; exec sp_configure 'xp_cmdshell' ...

  6. 文件上传利器SWFUpload使用指南

    这里就不再介绍什么是SWFUpload啦,简单为大家写一个简单关于SWFUpload的Demo. 1.把SWFUpload 相关的文件引用进来 2.创建upload.aspx页面(页面名称可自定义), ...

  7. ios 添加通用断点定位到异常点

    今天下午项目突然异常崩溃,因为代码没有多少结构改动,恢复旧版本还是不行,判定为网络获取信息异常,无奈从网络获取的信息太多,搞了很久后发现有个通用异常断点很好用,新手就是新手,浪费时间了.

  8. java中关于static的小知识

    static能够修饰属性和方法.凡是static修饰的方法和属性都是和类的关系较大,都在加载的时候要特殊处理(包括属性和类的优先加载).下面比较下static修饰属性和方法时的区别: 一.修饰属性的时 ...

  9. mysql 表操作

    创建表 简单的方式 CREATE TABLE person ( number INT(11), name VARCHAR(255), birthday DATE ); 或者是 CREATE TABLE ...

  10. ES6-个人学习笔记二--解构赋值

    第二期,解构赋值如果能够熟练应用确实是个十分方便的功能,但是过分的依赖和嵌套只会让代码理解和维护起来十分困难,是个体现高逼格的表达式呢~ 1,解构赋值的基础 //定义:es6运行按照一定模式,从数组或 ...