为什么linux内存要分DMA区域,常规区域和高端内存区域?

Linux内核划分内存区域主要是由于历史遗留问题和硬件架构的限制:

  1. DMA区域 (ZONE_DMA)

为什么存在:

· 早期ISA总线设备只能访问前16MB物理内存(24位地址总线限制)

· 某些老式DMA控制器只能访问前64KB或前16MB内存

· 确保这些老设备能够正常工作

用途:

· 分配给需要DMA操作的老式设备(声卡、网卡等)

· 防止这些设备因为无法访问内存而失败

  1. 常规区域 (ZONE_NORMAL)

为什么存在:

· 在32位系统中,内核虚拟地址空间有限(通常1GB)

· 这1GB空间需要直接映射到物理内存,称为线性映射或直接映射

· 这个直接映射区域就是ZONE_NORMAL

关键限制:

· 32位系统:内核空间1GB → 直接映射最大896MB

· 这896MB就是ZONE_NORMAL的大小

· 内核可以直接访问这个区域的物理内存,无需特殊映射

  1. 高端内存区域 (ZONE_HIGHMEM) - 32位系统的特殊产物

核心问题:

32位系统4GB虚拟地址空间分配:

复制代码
0-3GB:用户空间(每个进程独立)
3-4GB:内核空间(所有进程共享)

内核只有1GB虚拟地址空间,但物理内存可能超过1GB(如2GB、4GB)。

解决方案:

· ZONE_NORMAL(≤896MB):永久映射到内核虚拟地址空间

· ZONE_HIGHMEM(>896MB):动态映射到内核虚拟地址空间

高端内存访问机制:

c 复制代码
// 临时映射高端内存页面
void *kmap(struct page *page);
void kunmap(struct page *page);

// 原子映射(中断上下文可用)
void *kmap_atomic(struct page *page);
  1. 64位系统的变化

在64位系统中,情况完全不同:

关键优势:

· 虚拟地址空间极其巨大(x86_64:128TB内核空间)

· 内核可以将所有物理内存直接线性映射

· ZONE_HIGHMEM 不再需要(64位Linux中已移除)

现代64位系统的典型区域:

c 复制代码
// x86_64架构
ZONE_DMA      : 0-16MB     // 兼容老设备
ZONE_DMA32    : 16MB-4GB   // 32位DMA设备
ZONE_NORMAL   : 4GB-64TB   // 大部分内存都在这里
// 注意:没有ZONE_HIGHMEM!
  1. 各区域的物理位置

在32位系统(4GB物理内存)中:

复制代码
物理地址空间:
0-16MB    : ZONE_DMA      (DMA区域)
16-896MB  : ZONE_NORMAL   (常规区域)
896MB-4GB : ZONE_HIGHMEM  (高端内存)
          ↑
          └── 超过896MB的部分需要特殊映射
  1. 内存分配的优先级

内核分配内存时按顺序尝试:

  1. 先尝试在指定的ZONE分配
  2. 如果失败,按照fallback顺序尝试其他ZONE
  3. 例如:ZONE_HIGHMEM → ZONE_NORMAL → ZONE_DMA

总结表格

区域 32位系统 64位系统 主要用途

ZONE_DMA 0-16MB 0-16MB 老式DMA设备

ZONE_NORMAL 16-896MB 4GB以上 内核直接访问的内存

ZONE_HIGHMEM 896MB以上 不存在 动态映射的大内存(32位专用)

ZONE_DMA32 通常无 16MB-4GB 32位DMA设备

为什么保留这种设计?

  1. 向后兼容:支持老硬件和32位系统
  2. 性能优化:直接映射区域访问更快
  3. 资源管理:确保特殊设备有可用内存
  4. 简化移植:统一的接口,底层实现不同

关键启示:ZONE_HIGHMEM主要是32位时代的临时解决方案,64位系统已基本解决这个问题。但DMA区域仍然保留,确保老设备的兼容性。

相关推荐
进击的小头1 天前
行为型模式:策略模式的C语言实战指南
c语言·开发语言·策略模式
天马37981 天前
Canvas 倾斜矩形绘制波浪效果
开发语言·前端·javascript
Tansmjs1 天前
C++与GPU计算(CUDA)
开发语言·c++·算法
qx091 天前
esm模块与commonjs模块相互调用的方法
开发语言·前端·javascript
Suchadar1 天前
if判断语句——Python
开发语言·python
步步为营DotNet1 天前
深度剖析.NET中IHostedService:后台服务管理的关键组件
服务器·网络·.net
LUCIFER1 天前
[驱动进阶——MIPI摄像头驱动(五)]rk3588+OV13855摄像头驱动加载过程详细解析第四部分——ISP驱动
linux·驱动开发
莫问前路漫漫1 天前
WinMerge v2.16.41 中文绿色版深度解析:文件对比与合并的全能工具
java·开发语言·python·jdk·ai编程
九皇叔叔1 天前
【03】SpringBoot3 MybatisPlus BaseMapper 源码分析
java·开发语言·mybatis·mybatis plus
暮云星影1 天前
四、linux系统 应用开发:UI开发环境配置概述 (一)
linux·ui·arm