当前位置: 首页 > news >正文

一、内核初始化中与内存管理相关的函数

目录

一、start_kernel​中内存初始化相关函数梳理:

1、start_kernel下整体梳理

1.1、早期内存基础设施初始化

1.2、内存分配器核心初始化

1.3、内存相关后期初始化

2、重要部分梳理:setup_arch

2.1、阶段1:早期环境准备与内存探测

2.2、阶段2:关键内存区域保留

2.3、阶段3:memblock内存分配器初始化

2.4、阶段4:高级内存管理

3、重要部分梳理:mm_init

二、整体架构与重要函数

1、物理内存探测

2. 内存保留与分配器准备

3. NUMA与高级配置

4. 核心分配器设置

三、流程图梳理

参考文档:


一、start_kernel​中内存初始化相关函数梳理:

整体C函数部分流程:

secondary_startup_64--> x86_64_start_kernel--> x86_64_start_reservations-> start_kernel
1、start_kernel下整体梳理
1.1、早期内存基础设施初始化
--> page_address_init          //初始化页地址映射哈希表(用于highmem,x86_64通常为空操作)
--> setup_arch(&command_line)  //架构相关内存初始化, e820/memblock初始化, 直接内存映射建立, NUMA/节点拓扑构建
--> setup_per_cpu_areas        // 为每个CPU分配专属内存区域(减少多核竞争),静态定义per-CPU变量内存分配,动态per-CPU内存池初始化
1.2、内存分配器核心初始化
--> build_all_zonelists        // 构建所有NUMA节点的zone分配顺序链表,采用本地节点优先策略 
--> page_alloc_init            // 伙伴系统(Buddy System)初始化,释放所有启动阶段预留的内存到伙伴系统,初始化每CPU页框缓存(pcp,Per-CPU Pageset)
--> mm_init                    // Linux 内核初始化过程中内存管理子系统(Memory Management)的核心入口
1.3、内存相关后期初始化
--> kmem_cache_init_late          // SLAB分配器后期优化: 合并小缓存池, 初始化调试功能(如SLUB_DEBUG)
--> setup_per_cpu_pageset         // 完善每CPU页框缓存(pcp)配置:调整高/低水位线, 激活冷热页分配策略
--> numa_policy_init              // NUMA内存策略子系统初始化: 默认策略(MPOL_DEFAULT)设置, 绑定策略(MPOL_BIND)支持
--> mem_encrypt_init              // 内存加密后期处理(AMD SEV/SME)
--> kfence_init                   // 内存错误检测工具初始化
--> kcsan_init                    // 内存竞争检测器初始化
2、重要部分梳理:setup_arch

setup_arch为体系结构相关的初始化代码。X64系统对应的setup_arch定义在arch/x86/kernel/setup.c,函数中与内存管理有关的调用:

2.1、阶段1:早期环境准备与内存探测
基础映射
--> early_ioremap_init()       // 初始化临时I/O映射框架(基于fixmap)
--> setup_olpc_ofw_pgd()       // OLPC特殊页表处理(X86特有)物理内存探测
--> e820__memory_setup         // 解析BIOS提供的E820内存映射表,建立初始物理内存布局
--> e820__reserve_setup_data   //将Boot Loader扩展的数据区标记为内核保留区域,并为其分配内存映射
--> parse_setup_data()         // 解析ACPI/DTB等Bootloader数据
--> e820__finish_early_params  //更新e820表。用户可以通过Loader传入内核CMD line来自定义内存区域映射
--> e820_add_kernel_range      // 将内核_text 到 _end区域加入到e820表
--> e820__end_of_ram_pfn       // 从e820获取最大物理页帧号
2.2、阶段2:关键内存区域保留
--> early_reserve_memory    // 在memblock生效前保留关键内存区域
--> reserve_real_mode()        // 强制保留低端1MB(实模式代码)
--> e820__reserve_setup_data() // 保留ACPI/DTB等数据区
--> e820__memblock_alloc_reserved_mpc_new() // 保留MP配置表
--> reserve_crashkernel()      // 保留kexec崩溃内核区域
2.3、阶段3:memblock内存分配器初始化
--> early_alloc_pgt_buf        // 为初始化过程中分配PGT预留堆空间
--> e820__memblock_setup       // 将e820内存分布表的数据读出,并填写到Boot分配器管理
--> init_mem_mapping           // 建立完整的直接内存映射(Direct Mapping)
--> cleanup_highmap()          // 清除临时高端映射
2.4、阶段4:高级内存管理
--> initmem_init               // 初始化NUMA(如果开启对应Kconfig的话),为memblock的现有区域分配NUMA节点ID号
--> x86_init.paging.pagetable_init   //调用 native_pagetable_init 来初始化paging
--> sync_initial_page_table    // 确保多核系统中页表的一致性,避免因 TLB 缓存不一致引发的内存访问错误
--> e820__reserve_resources    // 为e820表项分配IO resource (reserve标记的表项除外)
--> x86_init.resources.reserve_resources   //使用reserve_standard_io_resources 为下面硬件端口分配ioport resource
--> e820__setup_pci_gap        // 在0到4GB找到空闲的内存区域,用于PCI设备的IO映射

至此,setup_arch​内存初始化部分就完成了

3、重要部分梳理:mm_init
--> mm_init()--> page_ext_init_flatmem()         // 初始化page_ext元数据系统(扩展struct page功能),分配连续物理页存储元数据数组, 建立pfn到page_ext的映射关系--> init_mem_debugging_and_hardening()		 // 内存调试与安全加固--> kfence_alloc_pool()				// 分配KFENCE监控内存池,保留16MB专用内存区域--> report_meminit()				// 打印物理内存布局信息:总内存/可用内存大小,内核代码/数据区位置--> stack_depot_init()              // 初始化栈回溯存储系统,分配哈希表存储调用栈--> mem_init()						// 物理内存最终移交--> free_all_bootmem()          // 释放所有bootmem内存到伙伴系统--> page_ext_init_flatmem_late()    // 延迟page_ext初始化:激活page_owner追踪,注册内存热插拔回调--> kmem_cache_init()				// SLAB分配器初始化:创建静态缓存(kmem_cache, kmalloc_caches),替换临时分配器接口--> kmemleak_init()                 // 动态内存泄漏检测:创建扫描线程, 注册kmalloc/vmalloc钩子--> pgtable_init()					// 页表缓存初始化--> x86: 初始化pgd/pmd/pte缓存,ARM: 配置硬件页表格式--> debug_objects_mem_init()        // 调试对象内存分配:创建obj_hash缓存,初始化静态对象池--> vmalloc_init()					// 非连续内存区初始化:划分vmalloc地址空间,初始化红黑树管理结构--> pti_init() [x86]                // 页表隔离初始化,分离用户/内核页表,配置CR3切换机制
二、整体架构与重要函数

整体数据流向:BIOS E820 → memblock → 伙伴系统 → SLAB/kmalloc,其中:

  • memblock:启动期间临时管理物理内存
  • 伙伴系统:按阶管理物理页,解决外部碎片
  • SLAB:对象级缓存,解决内部碎片

其中重要的API入口:

1、物理内存探测
功能说明
​e820__memory_setup()​解析BIOS E820内存映射表,生成e820_table​(区分RAM/Reserved类型)
​e820__finish_early_params()​处理cmdline内存参数(如memmap=​),动态修改内存布局
​mtrr_bp_init()​配置MTRR(Memory Type Range Registers),标记UC/WC等特殊内存区域
2. 内存保留与分配器准备
技术细节
​early_reserve_memory()​保留内核代码/数据区、ACPI表等关键区域到memblock.reserved​
​reserve_real_mode()​强制保留低端1MB内存(实模式代码、AP启动区域)
​e820__memblock_setup()​转换E820表到memblock​分配器,建立memblock.memory​和.reserved​
​init_mem_mapping()​建立直接物理映射(__START_KERNEL_map​偏移),支持5级页表(LA57)
3. NUMA与高级配置
函数作用
​initmem_init()​解析SRAT表构建NUMA拓扑,为内存块分配节点ID(nid​)
​e820__setup_pci_gap()​在0-4GB范围寻找PCI设备MMIO空洞,避免内存冲突
​sync_initial_page_table()​同步多核TLB,确保内存映射一致性
4. 核心分配器设置
阶段操作
伙伴系统​build_all_zonelists()​构建NUMA zone分配顺序,page_alloc_init()​启用每CPU缓存
SLAB分配器​kmem_cache_init()​创建通用缓存(kmalloc-*),kmem_cache_init_late()​优化合并
非连续内存​vmalloc_init()​划分VMALLOC区域,红黑树管理虚拟地址空洞
三、流程图梳理

参考文档:

Linux内核内存管理 - 初始化C代码中的内存处理概览 | L&H SITE

【计算子系统】内存管理之一:地址映射

linux内存初始化初期内存分配器——memblock-阿里云开发者社区

(3 封私信 / 79 条消息) linux内存管理(一)内存初始化 - 知乎

http://www.dtcms.com/a/334902.html

相关文章:

  • C语言:文件操作详解
  • 微软Wasm学习-创建一个最简单的c#WebAssembly测试工程
  • 【项目实战】利用AI生成式编程生成控制镜头变倍,变焦,光圈的Shell脚本(一)
  • 如何在FastAPI中玩转APScheduler,实现动态定时任务的魔法?
  • Redis7学习--详解 主从复制
  • 利用cursor+MCP实现浏览器自动化释放双手
  • 自动驾驶中的传感器技术24.1——Camera(16)
  • 企业级Java项目金融应用领域——银行系统(补充)
  • python线程学习
  • 一文了解金融合规
  • 什么是模型预测控制?
  • 算法训练营day52 图论③ 101.孤岛的总面积、102.沉没孤岛、103.水流问题、104.建造最大岛屿
  • PTPX分析中,如何处理fsdb文件过大的问题?
  • 【C#补全计划】Lambda表达式
  • ESP32-S3_ES8311音频输出使用
  • java内存模型:
  • Ubuntu 25.04更新了哪些内容揭秘
  • PHP反序列化的CTF题目环境和做题复现第1集
  • lesson40:PyMySQL完全指南:从基础到高级的Python MySQL交互
  • 【大语言模型 00】导读
  • 【Docker】Ubuntu上安装Docker(网络版)
  • 双指针和codetop复习
  • Hexo 双分支部署指南:从原理到 Netlify 实战
  • 【遥感图像技术系列】遥感图像风格迁移的研究进展一览
  • SymPy 矩阵到 NumPy 数组的全面转换指南
  • Redis 04 Reactor
  • eChart饼环pie中间显示总数_2个以上0值不挤掉
  • 【集合框架List进阶】
  • 【UHD】vivado 2021.1 编译
  • 选择式与生成式超启发算法总结