• [置顶] linux内核启动2-setup_arch中的内存初始化(目前分析高端内存)


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

            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

    # define NR_BANKS 8 三星当然是8

    #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).

        而其余的空间都是高端内存的范围,即:3512G4G,但是为了避免越界等安全问题

        的考虑,高端内存又离开了低端内存8M空间,即从3G512M+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 ", 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 ",(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 ");

                            }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 ", (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++;

            }

    ……


    未完待续,,,

  • 相关阅读:
    测试项目框架搭建
    项目实战(一)
    接口和HTTP协议(二)
    接口和http协议(一)
    什么是DFX测试
    完美解决安装在虚拟机中的CentOS7无法联网的问题
    RIP动态路由协议
    ensp实验--------RIP动态路由实验
    ensp实验--------telnet登录认证
    CSMA/CD协议
  • 原文地址:https://www.cnblogs.com/james1207/p/3343474.html
Copyright © 2020-2023  润新知