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

【操作系统】内存管理知识点深度解析

文章目录

  • 一、虚拟内存的必要性(为什么要有虚拟内存?)
    • 地址空间扩展
    • 内存保护与隔离
    • 提高内存利用率
  • 二、malloc 内存分配机制(malloc 是如何分配内存的?)
    • 用户空间内存分配
      • 堆管理:
      • 分配策略:
    • 内核空间内存分配
      • 伙伴系统(Buddy System):
      • Slab 分配器:
  • 三、内存满的处理机制(4.3 内存满了,会发生什么?)
    • 页面置换与交换(Swapping)
    • 性能影响
  • 四、大内存申请的处理(4.4 在 4GB 物理内存的机器上,申请 8G 内存会怎样?)
    • 虚拟内存分配可行性
    • 物理内存不足的处理
  • 五、缓存优化策略(4.5 如何避免预读失效和缓存污染?)
    • 预读失效(Prefetching Failure)
      • 原因:
      • 优化:
    • 缓存污染(Cache Pollution)
      • 原因:
    • 优化:
  • 六、Linux 虚拟内存管理(4.6 深入理解 Linux 虚拟内存管理)
    • 地址映射机制
    • 内存回收与压缩
  • 七、Linux 物理内存管理(4.7 深入理解 Linux 物理内存管理)
    • 伙伴系统(Buddy System)
      • 内存划分:
      • 内存 Zones:
    • Slab 分配器
      • 对象缓存:
        • Per-CPU 缓存:为每个 CPU 分配独立 Slab 缓存,减少锁竞争(如percpu_alloc)。
  • 总结

一、虚拟内存的必要性(为什么要有虚拟内存?)

地址空间扩展

物理内存容量有限(如早期 32 位系统物理内存≤4GB),虚拟内存通过分页 / 分段机制将虚拟地址(如 64 位系统支持 128TB 虚拟地址空间)映射到物理内存,使程序可使用远超物理内存的地址空间(如进程独立虚拟地址空间)。
示例:64 位 Linux 进程虚拟地址空间分为用户空间(0-0x7FFFFFFFFFFF)和内核空间(0x800000000000 以上),每个进程 “认为” 拥有独立内存,实际由 MMU 动态映射。

内存保护与隔离

虚拟内存通过页表权限位(读 / 写 / 执行)实现进程间内存隔离(如用户态进程无法访问内核内存),防止非法访问。
内核态(Ring 0)与用户态(Ring 3):操作系统内核运行于高特权级,通过虚拟内存保护其内存不被用户程序篡改。

提高内存利用率

按需加载(Demand Paging):程序启动时仅加载必要代码(如 main 函数),其余部分(如库函数)在首次访问时通过缺页中断加载,减少内存浪费。
页面置换(Page Replacement):通过 LRU 等算法将不活跃页面换出到磁盘(交换空间),实现物理内存的动态复用,支持多进程并发执行。

二、malloc 内存分配机制(malloc 是如何分配内存的?)

用户空间内存分配

堆管理:

malloc基于 C 标准库的堆分配器(如 glibc 的 ptmalloc),通过brk(扩展堆顶)或mmap(映射匿名内存)系统调用从内核申请内存。

分配策略:

小内存(≤128KB):使用brk扩展堆,采用空闲链表(如双向链表管理空闲块),分配算法包括首次适应(First Fit)、最佳适应(Best Fit),存在内部碎片(空闲块小于分配需求时无法利用)。
大内存(>128KB):直接通过mmap映射匿名内存,分配粒度为页(如 4KB),减少碎片但增加系统调用开销。

内核空间内存分配

伙伴系统(Buddy System):

管理物理页框(4KB/8KB 等),将内存划分为 2^n 大小的块,通过合并 / 分裂空闲块分配内存,解决外部碎片(空闲块不连续导致无法分配大内存)。

Slab 分配器:

针对内核对象(如进程描述符、文件结构体),预先分配内存池(Slab),通过对象缓存减少伙伴系统的分裂 / 合并开销,提升分配效率(如 Linux 内核的kmalloc基于 Slab)。

三、内存满的处理机制(4.3 内存满了,会发生什么?)

页面置换与交换(Swapping)

当物理内存不足时,Linux 内核通过kswapd 进程扫描不活跃页面(通过page_reclaim机制),将其换出到交换分区(/swap)。若交换空间也满,触发OOM Killer(内存不足杀手),选择 “badness” 评分高的进程(如占用内存多、优先级低)终止,释放内存。

性能影响

颠簸(Thrashing):频繁缺页(如进程访问内存远超过物理内存 + 交换空间)导致 CPU 忙于页面置换,系统吞吐量骤降。可通过增加物理内存或优化进程内存使用(如减少内存泄漏)缓解。

四、大内存申请的处理(4.4 在 4GB 物理内存的机器上,申请 8G 内存会怎样?)

虚拟内存分配可行性

64 位系统中,虚拟内存分配(如malloc(810241024*1024))首先检查虚拟地址空间是否足够(64 位系统支持远超 8GB),分配虚拟地址范围(VMA,虚拟内存区域),此时物理内存尚未分配(仅记录 VMA 属性,如可读 / 可写)。

物理内存不足的处理

当程序访问未映射的虚拟内存时,触发缺页中断(Page Fault):
若物理内存有空闲页框,直接分配并映射(minor fault)。
若物理内存不足,通过页面置换(major fault)换出不活跃页面,分配物理页框。
若交换空间不足且无法置换(如所有页面均活跃),触发 OOM Killer。

五、缓存优化策略(4.5 如何避免预读失效和缓存污染?)

预读失效(Prefetching Failure)

原因:

预读算法(如 Linux 的readahead)基于局部性原理加载数据,但实际未被访问,导致缓存(如 CPU L1/L2 缓存、磁盘缓存)空间浪费。

优化:

自适应预读:根据历史访问模式动态调整预读窗口(如 SSD 的 NVMe 协议支持自适应预读)。
应用层优化:减少不必要的预读(如数据库查询避免全表扫描),利用空间局部性(连续访问内存)。

缓存污染(Cache Pollution)

原因:

无关数据(如大数组遍历)占据缓存,替换掉高频访问数据,降低缓存命中率。

优化:

缓存隔离:使用posix_memalign分配对齐内存,避免跨缓存行访问;内核通过SLAB_CACHE_DMA等标志隔离 DMA 内存与普通内存。
内存访问模式优化:采用时间局部性(重复访问同一内存区域),如循环内访问数组元素,提升缓存利用率。

六、Linux 虚拟内存管理(4.6 深入理解 Linux 虚拟内存管理)

地址映射机制

多级页表(x86_64 为 4 级页表:PGD→PUD→PMD→PTE):每个进程维护页表,MMU 通过 TLB(快表)缓存近期页表项,加速地址转换(TLB 命中率通常 > 95%)。
虚拟内存区域(VMA):描述进程虚拟内存的区间(如代码段、数据段、堆、栈、共享库),通过mm_struct和vm_area_struct管理,支持内存共享(如fork的写时复制,COW)。

内存回收与压缩

kswapd:周期性扫描内存,回收不活跃页(page_reclaim),支持内存压缩(Memory Compaction)(将分散的空闲页合并为连续块,缓解外部碎片)。
透明大页(THP,Transparent Huge Page):将 2MB/1GB 大页用于匿名内存(如堆),减少页表项数量,提升 TLB 命中率(适用于内存访问密集型应用,如数据库)。

七、Linux 物理内存管理(4.7 深入理解 Linux 物理内存管理)

伙伴系统(Buddy System)

内存划分:

将物理内存按 2^n 字节(n=0 到 11,对应 4KB 到 8MB)划分为块,通过free_area数组管理空闲块,分配时从最小适配块分裂,释放时合并相邻块。

内存 Zones:

DMA Zone(0-16MB):支持 DMA 设备直接访问(如老式 PCI 设备)。
Normal Zone(16MB - 高端内存):普通物理内存。
HighMem Zone(32 位系统高端内存,64 位系统已淘汰):通过临时映射(kmap)访问。

Slab 分配器

对象缓存:

为内核对象(如task_struct)创建 Slab(包含多个对象实例),通过kmem_cache管理,减少伙伴系统的碎片化,提升分配速度(如kmalloc默认使用 Slab)。

Per-CPU 缓存:为每个 CPU 分配独立 Slab 缓存,减少锁竞争(如percpu_alloc)。

总结

内存管理是操作系统的核心模块,通过虚拟内存扩展地址空间、通过伙伴系统 / Slab 管理物理内存、通过页面置换和缓存优化提升性能。理解malloc的底层机制、Linux 的内存映射与回收策略,是优化程序内存使用(如避免内存泄漏、提升缓存命中率)的关键。随着硬件发展(如 NVM 内存、CXL 技术),内存管理将向更高效的分层架构演进,需持续关注硬件 - 软件协同优化。

http://www.xdnf.cn/news/699031.html

相关文章:

  • 直播框架:基础知识点
  • 【基础题库回复四则】2022-1-26
  • git提交更改
  • 三强联合!Attention+LSTM,结合特征融合,起手二区!
  • 从“被动养老”到“主动健康管理”:平台如何重构代际关系?
  • Linux上给SD卡创建分区
  • 光谱相机在生态修复监测中的应用
  • LeetCode 463. 岛屿的周长 java题解
  • 软件测试之黑盒测试与白盒测试详解
  • python 小工具,获取 github 仓库信息
  • ORDER BY子句在一个 SQL 查询中只能出现一次
  • 全球轨道铺设设备市场发展现状与未来趋势分析
  • HDFS:解锁大数据存储的奥秘
  • 54、C# 委托 (Delegate)
  • Maven 项目中集成数据库文档生成工具
  • leetcode hot100刷题日记——23.数组中的第K个最大元素
  • 磁光电流互感器行业2025数据分析报告
  • UE5 编辑器工具蓝图
  • 2025年AEJ SCI2区,动态反向排序教与学优化算法DSTLBO+光伏系统参数辨识,深度解析+性能实测
  • java课堂笔记10
  • ubuntu创建指定版本python虚拟环境
  • emu8086 v4.08安装教程
  • Python基础语法(下)
  • 打破认知壁垒重构科技驱动美好生活 大模型义务传播计划
  • 数据科学入门
  • CS144 - Lecture 1 记录
  • js中common.js和ECMAScript.js区别
  • 智慧交通新纪元:AI赋能下的交通治理革命与技术演进路径
  • 学习路之Nginx--不同域名的反向代理
  • 有道翻译js分析