内存模块从无到可以给别的模块使用,需要经历哪些阶段

Linux 内核中的**内存管理模块(Memory Management, MM)**从初始化到可供其他模块使用,需要经历一系列严格的阶段,涵盖硬件初始化、数据结构构建、接口暴露等过程。以下是关键阶段的详细说明:


关键函数调用链(示例)

start_kernel()
  → setup_arch()          # 架构相关内存初始化
  → mm_init()            # 核心内存管理初始化
    → mem_init()         # 释放memblock到伙伴系统
    → kmem_cache_init()  # SLAB初始化
    → vmalloc_init()     # 虚拟内存区域初始化
  → rest_init()          # 启动kswapd线程

1. 硬件相关初始化(Architecture-Specific Setup)

阶段目标:检测物理内存布局,建立最基本的页表映射。
  • 执行时机:内核启动早期(start_kernel() 之前,由汇编代码处理)。
  • 关键步骤
    1. 探测物理内存
      • BIOS/UEFI 或设备树(DT)传递内存信息(如 mem= 内核参数)。
      • 记录内存区域(memblocke820 映射,位于 arch/x86/kernel/e820.c)。
    2. 初始化页表
      • 建立临时内核页表(arch/x86/mm/init_64.cstartup_64())。
      • 启用分页机制(cr3 寄存器加载)。
    3. 保留关键内存区域
      • 保留内核代码、数据段、启动参数等(memblock_reserve())。
边界
  • 依赖体系结构代码(如 arch/x86, arch/arm64)。
  • 不依赖其他内核模块(此时调度器、驱动等尚未初始化)。

2. 通用内存管理子系统初始化(start_kernel() 阶段)

阶段目标:构建核心内存管理数据结构,替换临时分配器。
  • 执行时机start_kernel()mm_init()
  • 关键步骤
    1. 初始化 memblock 分配器
      • 临时管理物理内存(mm/memblock.c),后续被伙伴系统取代。
    2. 建立伙伴系统(Buddy System)
      • 解析 memblock 内存区域,初始化 struct zonemm/page_alloc.cfree_area_init())。
      • 划分物理页帧(struct page 数组),管理空闲列表。
    3. 初始化 SLAB/SLUB 分配器
      • 为内核对象(如 task_struct)创建缓存(mm/slub.ckmem_cache_init())。
    4. 设置内存回收机制
      • 启动 kswapd 内核线程(mm/vmscan.c)。
    5. 初始化虚拟内存(VM)
      • 建立 vmalloc 区域(mm/vmalloc.cvmalloc_init())。
边界
  • 依赖体系结构代码提供的物理内存信息。
  • 不依赖动态模块(此时模块子系统未初始化)。

3. 动态内存接口暴露(API Ready)

阶段目标:提供其他模块可调用的内存分配接口。
  • 执行时机mm_init() 完成后,其他子系统开始初始化。
  • 关键接口
    1. 物理页分配
      • alloc_pages() / __get_free_pages()include/linux/gfp.h)。
    2. SLAB 分配器
      • kmalloc() / kfree()include/linux/slab.h)。
    3. 虚拟内存映射
      • vmalloc() / vfree()mm/vmalloc.c)。
    4. DMA 内存接口
      • dma_alloc_coherent()include/linux/dma-mapping.h)。
    5. 用户空间内存交互
      • copy_to_user() / get_user_pages()mm/memory.c)。
边界
  • 通过 EXPORT_SYMBOL() 导出符号供其他模块使用。
  • 依赖核心模块(如 spinlock 用于保护内存结构)。

4. 与其他模块的协作(Integration)

阶段目标:响应其他模块的内存需求。
  • 示例场景
    1. 进程管理模块
      • 创建进程时调用 mm_init() 初始化 mm_structkernel/fork.c)。
    2. 文件系统模块
      • 文件映射(mmap())触发 filemap_fault() 加载页面缓存。
    3. 设备驱动模块
      • 驱动通过 kmalloc() 分配内存,或 ioremap() 映射设备内存。
    4. 网络模块
      • SKB 缓冲区分配(alloc_skb() 内部调用 kmalloc())。
边界
  • 严格通过头文件中的 API 交互,避免直接访问内部数据结构。

5. 动态内存扩展(可选)

阶段目标:支持内存热插拔、CMA(连续内存分配器)等高级功能。
  • 执行时机:运行时动态加载。
  • 关键步骤
    1. 内存热插拔
      • 通过 add_memory() / remove_memory() 动态增删内存(drivers/base/memory.c)。
    2. CMA 初始化
      • 为设备预留连续内存(mm/cma.ccma_init_reserved_areas())。
边界
  • 依赖设备驱动模块(如 NUMA 架构)。

总结:从无到有的阶段

阶段关键操作依赖关系
硬件初始化探测内存、建立页表仅依赖体系结构代码
核心内存子系统初始化伙伴系统、SLAB、VM初始化依赖硬件初始化完成
接口暴露导出 kmallocalloc_pages 等符号依赖核心内存子系统
模块协作为进程、文件系统、驱动提供内存服务所有基础接口已就绪
动态扩展内存热插拔、CMA可选,依赖具体需求

内存模块的初始化是内核启动的关键路径之一,必须按严格顺序执行,确保其他模块在需要内存时,底层机制已完全就绪。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值