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

DMA 概念与讲解

在这里插入图片描述

文章目录

  • 一、Linux 物理内存区
      • **1. 硬件兼容性与性能优化**
        • **ZONE_DMA(直接内存访问区)**
        • **ZONE_NORMAL(普通内存区)**
        • **ZONE_HIGHMEM(高端内存区)**
      • **2. 地址空间管理需求**
        • **直接映射区(Direct Mapping)**
        • **动态映射区(High Memory)**
      • **3. 内存分配策略**
        • **连续物理内存分配(`kmalloc`)**
        • **非连续内存分配(`vmalloc`)**
        • **Slab 分配器与对象缓存**
      • **4. 跨架构差异**
      • **5. 核心原则总结**
      • **6. 现代系统的演变**
      • **示例代码:查看内存区域信息**
      • **总结**
  • 参考


一、Linux 物理内存区

Linux 内核将物理内存划分为 ZONE_DMAZONE_NORMALZONE_HIGHMEM 的原则,主要基于以下核心因素:


1. 硬件兼容性与性能优化

ZONE_DMA(直接内存访问区)
  • 目的:支持老旧 DMA 控制器(Direct Memory Access)的硬件设备。
  • 硬件限制
    许多早期 DMA 控制器(如 ISA 总线设备)仅能访问物理地址的低范围(通常为 0x00000000 ~ 0x00FFFFFF,即 16MB 或更低)。
    若设备 DMA 操作超出此范围,可能导致地址溢出或数据损坏。
  • 内核策略
    将物理内存的低地址段(如 0x00000000 ~ 896MB)保留为 ZONE_DMA,确保 DMA 设备可直接访问。
ZONE_NORMAL(普通内存区)
  • 目的:存放内核核心数据和频繁访问的内存。
  • CPU 架构优化
    现代 CPU 的 MMU(内存管理单元)和缓存机制对低端内存的访问效率更高。
    内核代码、页表、全局数据结构(如 task_struct)需稳定且连续的物理内存,因此优先分配 ZONE_NORMAL。
ZONE_HIGHMEM(高端内存区)
  • 目的:解决 32 位系统的物理内存寻址限制。
  • 32 位系统限制
    32 位系统的虚拟地址空间为 4GB,内核直接映射的物理内存范围通常为 0x00000000 ~ 0x7FFFFFFF(即 896MB)。
    超出部分(>896MB)无法直接映射到内核虚拟地址空间,需通过动态映射(如 vmallockmap)访问,这部分称为 ZONE_HIGHMEM。
  • 64 位系统差异
    64 位系统的虚拟地址空间极大(如 128TB),可直接映射全部物理内存,因此 无需 ZONE_HIGHMEM

2. 地址空间管理需求

直接映射区(Direct Mapping)
  • ZONE_DMA + ZONE_NORMAL
    内核启动时,物理内存的低地址段(如 0x00000000 ~ high_memory)被直接映射到内核虚拟地址空间(PAGE_OFFSET 起始)。
    此区域访问高效,无需复杂的地址转换。
动态映射区(High Memory)
  • ZONE_HIGHMEM(仅 32 位):
    物理内存超过直接映射范围的部分(high_memory ~),需通过临时映射(如 kmap_atomic)或页表切换访问。
    此区域访问效率较低,但扩展了可用内存上限。

3. 内存分配策略

连续物理内存分配(kmalloc
  • ZONE_DMA & ZONE_NORMAL
    kmalloc() 分配的物理内存默认来自 ZONE_DMA 或 ZONE_NORMAL,保证连续性和低延迟,适用于 DMA、内核数据结构等场景。
非连续内存分配(vmalloc
  • ZONE_HIGHMEM(32 位):
    vmalloc() 分配的虚拟内存可能映射到 ZONE_HIGHMEM,但物理页不要求连续,适用于大块内存或无需 DMA 的场景。
Slab 分配器与对象缓存
  • 缓存亲和性
    频繁访问的小对象(如 struct page)优先从 ZONE_NORMAL 分配,减少缓存失效。

4. 跨架构差异

系统架构ZONE_DMAZONE_NORMALZONE_HIGHMEM
32 位低端内存(如 0~16MB)中段内存(16MB~896MB)高端内存(>896MB)
64 位通常空闲或极小覆盖几乎全部物理内存不存在

5. 核心原则总结

Linux 内核划分内存区域的三大原则:

  1. 硬件兼容性
    适配 DMA 设备等硬件的地址限制。
  2. 性能优化
    优先保障内核高频访问区域的连续性和低延迟。
  3. 地址空间高效利用
    在 32 位系统中通过 ZONE_HIGHMEM 扩展可用内存,64 位系统则简化管理。

6. 现代系统的演变

  • 64 位系统
    因虚拟地址空间极大(如 48/57 位物理寻址),通常仅保留 ZONE_DMA 和 ZONE_NORMAL,ZONE_HIGHMEM 被淘汰。
  • 大内存优化
    对 NUMA(非统一内存访问)系统,Linux 进一步细分 ZONE_NORMAL 为多个内存节点(Node),优化局部性。

示例代码:查看内存区域信息

#include <linux/mm.h>
#include <linux/printk.h>

void print_memory_zones(void) {
    struct zone *zone;
    for_each_zone(zone) {
        pr_info("Zone: %s, Start: %lu KB, End: %lu KB
",
                zone->name,
                zone->zone_start_pfn << (PAGE_SHIFT - 10),
                (zone->zone_start_pfn + zone->spanned_pages) << (PAGE_SHIFT - 10));
    }
}

总结

Linux 内核通过划分 ZONE_DMAZONE_NORMALZONE_HIGHMEM,实现了对硬件兼容性、性能及内存利用率的平衡。这种设计在 32 位系统中尤为重要,而在 64 位系统中则大幅简化,体现了操作系统对底层硬件的深刻理解和抽象能力。

参考

PCIe MMIO、DMA、TLP
【PCIe】PCIe配置空间与CPU访问机制


   
 

Ctrl + Alt + V

相关文章:

  • LeetCode 热题 100_完全平方数(84_279_中等_C++)(动态规划(完全背包))
  • 随机产生4位随机码(java)
  • 设计模式之享元模式
  • 图解AUTOSAR_SWS_FlexRayDriver
  • 使用分布式锁和乐观锁解决超卖问题
  • 闪蒸高密度聚乙烯无纺布市场报告:探索高性能材料的新机遇
  • 搜广推面经六十八
  • yum拒绝连接
  • 【区块链+ 人才服务】蓝鲸智课——区块链课程与实训平台 | FISCO BCOS 应用案例
  • GS069W电动工具直流调速电路:高效调速方案解析
  • 【多线程-第四天-自己模拟SDWebImage的下载图片功能-取消操作 Objective-C语言】
  • Quartz 分布式集群 数据持久化任务调度系统
  • 【VScode】C/C++使用教程
  • C++11实现一个自旋锁
  • Flutter:Flutter SDK版本控制,fvm安装使用
  • 寄存器相关及清零、置1、取反等位移操作
  • 进程的创建态、运行状态和阻塞状态
  • FreeRTOS与RT-Thread深度对比:从入门到精通的全面解析
  • Redlinux(2025.3.29)
  • 地图与图层操作
  • 如何与别的网站做友情链接/2023能用的磁力搜索引擎
  • 网站项目建设主要内容/手机网址大全123客户端下载
  • 外贸都用什么网站/广告公司取名字参考大全
  • 杭州下沙做网站的论坛/产品推广策划
  • 专门做面条菜谱的网站/怎么样做seo
  • 自动生成网站地图怎么做/百度搜索排行榜前十名