内存管理-25-内存初始化

基于msm-5.4

一、C代码部分

1. 调用路径

_head //head.S 
    stext //head.S
        __primary_switch //head.S
            __primary_switched //head.S
                kaslr_early_init //kaslr.c 最先调用,可配置会否生效与不生效,默认生效
                    early_fixmap_init
                start_kernel
                    setup_arch //setup.c 主要路径
                        early_fixmap_init
                        early_ioremap_init
                        setup_machine_fdt
                            early_init_dt_scan(params) //fdt.c
                                early_init_dt_scan_nodes //fdt.c
                                    early_init_dt_scan_memory //fdt.c 解析memory内存节点,填充memory内存区
                        arm64_memblock_init
                            early_init_fdt_scan_reserved_mem //fdt.c 解析reserved内存,填充reserved内存区
                            memblock_reserve(__pa_symbol(_text), _end - _text); //reserve整个内核镜像
                        paging_init
                            cpu_replace_ttbr1(lm_alias(swapper_pg_dir)); //从此PGD页表从init_pg_dir变为swapper_pg_dir
                            init_mm.pgd = swapper_pg_dir; //从此init进程页表从init_pg_dir变为swapper_pg_dir
                            memblock_free(__pa_symbol(init_pg_dir), __pa_symbol(init_pg_end) - __pa_symbol(init_pg_dir)); //init页表取消reserve
                        bootmem_init
                            memblocks_present //sparse.c
                            sparse_init //sparse.c
                            zone_sizes_init //init.c
                            memblock_dump_all //memblock.h dump所有memory区域和reserved区域
                        early_ioremap_reset //标记内存已经初始化好了
                    build_all_zonelists //page_alloc.c
                    page_alloc_init //page_alloc.c
                    parse_early_param //解析模块参数,调用参数回调
                    mm_init //main.c
                        mem_init //init.c
                memblock_free_all //memblock.c 将所有物理页释放到伙伴系统
                mem_init_print_info //page_alloc.c 打印 Memory: 13676936K/14227228K available ...内存信息 kmem_cache_init //slab.c kmemleak_init //kmemleak.c pgtable_init //mm.h vmalloc_init //vmalloc.c sched_init //调度初始化 kmem_cache_init_late console_init //这里串口才初始化,但是在这之前的打印也能打印出来 setup_per_cpu_pageset vfs_caches_init pagecache_init arch_call_rest_init //main.c rest_init kernel_thread(kernel_init, NULL, CLONE_FS) //创建init线程 kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES) //创建内核kthreadd线程 complete(&kthreadd_done) //通知内核 kthreadd 线程启动完成 cpu_startup_entry(CPUHP_ONLINE) while (1) //swapper线程在这里不会退出 do_idle()

init线程执行流程:

kernel_init
    kernel_init_freeable //main.c
        wait_for_completion(&kthreadd_done) //等待内核 kthreadd 线程启动完成
        do_pre_smp_initcalls //调用 __initcall_start -- __initcall0_start 之间的函数,默认没有
        page_alloc_init_late
        page_ext_init
        do_basic_setup //main.c
          do_initcalls //main.c 执行initcall回调
                init_per_zone_wmark_min //page_alloc.c initcall-2 水位初始化
                populate_rootfs //vmlinux.lds.h中检索rootfs, 在initcall的5-6之间
                    free_initrd_mem(initrd_start, initrd_end) //释放initrd预留的内存
    free_initmem //init.c 释放__init修饰的代码段
    run_init_process(execute_command) //运行用户空间init进程

 

2. 说明

arm64_memblock_init() 中确定了逻辑物理内存起始地址 memstart_addr; 确定了page数组与逻辑物理内存首地址之间的偏移 vmemmap; 确定了内核线性映射区虚拟地址空间与物理地址空间之间的偏移 physvirt_offset;

 

二、各阶段内存分配方式

1. 起初在汇编中通过vmlinux.lds.S预留内存空间,然后手动自己创建页表。
2. 通过memblock分配内存,手动创建页表。
3. 通过memblock分配内存,利用fixmap映射创建页表。//此时early_ioremap()可以使用了
4. paging_init()调用创建线性映射后,所有物理内存都映射了,还是通过memblock分配内存,但不需要再手动创建映射了。
-------
5. 伙伴系统初始化后u,就可以通过伙伴系统的接口 alloc_pages() 分配内存了。
6. slab初始话后就可以通过 malloc/free分配释放内存了?

 

posted on 2024-08-03 10:30  Hello-World3  阅读(21)  评论(0编辑  收藏  举报

导航