内存管理-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) 编辑 收藏 举报