4. 内存管理调优:mem、memmap、crashkernel 参数详解与实战配置
内存是 Linux 系统最核心的资源之一。内核引导参数中的 mem、memmap 和 crashkernel 直接决定了操作系统可用的物理内存范围、内存区域的划分方式以及内核崩溃转储机制的预留空间。错误配置会导致系统无法识别全部内存、设备驱动 DMA 冲突,甚至无法捕获内核崩溃现场。本章从参数语义、配置语法、实战场景三个维度进行深度解析。
4.1 mem 参数:限制内核可见物理内存
mem 参数用于告诉内核只使用指定大小的物理内存,超出部分将被忽略。该参数在内存测试、隔离坏内存区域、模拟低内存环境等场景中非常实用。
4.1.1 语法与行为
| 参数格式 | 说明 | 示例 |
|---|---|---|
mem=nn[KMG] |
限制内核可见内存总量为 nn | mem=4G |
mem=nn[KMG]@ss |
从物理地址 ss 开始,使用 nn 大小内存 | mem=512M@0x10000000 |
mem= 限制内存后,内核不会访问被隐藏的物理地址空间。如果该区域被设备 DMA 或 BIOS 使用,可能导致系统不稳定或设备无法初始化。生产环境慎用。
4.1.2 实战场景:隔离坏内存区域
假设服务器物理内存 32 GB,但地址 0x20000000 ~ 0x30000000(256 MB)存在硬件故障。可通过 mem= 参数让内核跳过该区域:
# 在 GRUB 配置中添加
GRUB_CMDLINE_LINUX="mem=31.75G"
# 或更精确地指定可用区域
GRUB_CMDLINE_LINUX="mem=512M@0x0 mem=31G@0x30000000"
上述配置让内核使用 0x0 ~ 0x20000000(512 MB)和 0x30000000 ~ 结束(31 GB),跳过故障区间。
4.1.3 验证方法
# 查看内核实际识别内存
$ dmesg | grep -i "memory"
[ 0.000000] Memory: 32883020K/33554432K available
# 查看 /proc/meminfo
$ grep MemTotal /proc/meminfo
MemTotal: 32883020 kB
mem= 可以模拟低内存压力测试,验证 OOM Killer 行为和应用程序的内存容错能力。
4.2 memmap 参数:精确内存区域映射与保留
memmap 参数提供了比 mem 更精细的内存区域控制能力,允许将特定物理地址区间标记为保留、可用或特定用途。该参数在嵌入式系统、UEFI 固件兼容性修复、大页内存预分配等场景中不可或缺。
4.2.1 语法格式
| 格式 | 含义 | 典型用途 |
|---|---|---|
memmap=nn[KMG]$ss |
从 ss 开始保留 nn 大小内存(内核不可用) | 保留给固件或硬件设备 |
memmap=nn[KMG]!ss |
从 ss 开始标记 nn 大小为可用内存 | 覆盖 BIOS 错误的内存映射 |
memmap=nn[KMG]#ss |
从 ss 开始预留 nn 大小给特定驱动 | DMA 缓冲区预留 |
4.2.2 实战:修复 UEFI 内存映射冲突
某些 UEFI 固件会将 ACPI 数据区域错误地报告为可用内存,导致内核在写入时损坏 ACPI 表。使用 memmap 强制保留该区域:
# 保留 0x7FE00000 ~ 0x7FFFFFFF (2 MB) 给 ACPI
GRUB_CMDLINE_LINUX="memmap=2M$0x7FE00000"
4.2.3 实战:为大页预留连续物理内存
数据库或 HPC 应用需要 1 GB 大页时,要求物理内存连续。通过 memmap 提前预留:
# 在 4 GB 边界预留 1 GB 连续内存
GRUB_CMDLINE_LINUX="memmap=1G$0x100000000"
# 启动后验证预留区域
$ dmesg | grep "reserved"
[ 0.000000] Reserved memory: created CMA memory pool at 0x100000000, size 1024 MiB
mem= 是“限制可见总量”,memmap= 是“精确控制每个区域的属性”。前者适合快速裁剪,后者适合精细调优。
4.3 crashkernel 参数:内核崩溃转储预留
crashkernel 参数用于在系统启动时预留一段物理内存,供 kdump 机制在内核崩溃时加载捕获内核(capture kernel)并保存 vmcore 文件。没有正确配置 crashkernel,内核 panic 后将无法自动转储,导致问题排查无据可依。
4.3.1 参数格式与推荐值
| 格式 | 说明 | 推荐值(x86_64) |
|---|---|---|
crashkernel=size[KMG] |
在低端内存预留固定大小 | crashkernel=256M |
crashkernel=size[KMG]@offset |
在指定偏移地址预留 | crashkernel=256M@0x40000000 |
crashkernel=range1:size1,... |
根据总内存范围自动选择预留大小 | crashkernel=2G-4G:256M,4G-32G:512M |
crashkernel=auto |
内核自动计算预留大小 | 依赖架构和总内存 |
4.3.2 实战:为生产服务器配置 crashkernel
对于 64 GB 内存的生产数据库服务器,推荐使用范围格式:
# /etc/default/grub
GRUB_CMDLINE_LINUX="crashkernel=4G-64G:512M,64G-:1G"
# 更新 GRUB 配置
$ grub2-mkconfig -o /boot/grub2/grub.cfg
# 重启后验证预留
$ dmesg | grep -i "crash"
[ 0.000000] Reserving 512MB of memory at 256MB for crashkernel
# 查看 kdump 服务状态
$ systemctl status kdump
● kdump.service - Crash recovery kernel arming
Loaded: loaded (/usr/lib/systemd/system/kdump.service; enabled)
Active: active (exited)
4.3.3 预留大小计算原则
- 捕获内核自身内存:通常需要 64 MB ~ 256 MB,取决于内核模块数量。
- vmcore 保存缓冲区:需要容纳被捕获内核的内存映像,建议为总内存的 1/64 ~ 1/32。
- 硬件保留区域:某些设备需要 DMA 连续内存,预留时需额外考虑。
crashkernel=128M;4 GB ~ 64 GB 使用 crashkernel=256M 或 512M;超过 64 GB 使用 1G。
4.4 三个参数的协同配置与冲突避免
在实际生产环境中,mem、memmap 和 crashkernel 可能同时出现在引导参数中。错误的组合顺序或地址重叠会导致系统启动失败或功能异常。
4.4.1 参数处理顺序
内核在启动早期按以下顺序解析内存相关参数:
- 先处理
memmap=:建立初始物理内存区域属性表。 - 再处理
mem=:在区域表基础上裁剪可见内存总量。 - 最后处理
crashkernel=:在最终可用内存中预留转储空间。
4.4.2 冲突场景与解决方案
| 冲突场景 | 后果 | 解决方案 |
|---|---|---|
mem= 限制区域覆盖了 crashkernel= 预留地址 |
crashkernel 预留失败,kdump 不可用 | 先使用 memmap= 确保预留区域不被裁剪 |
memmap= 保留区域与 crashkernel= 重叠 |
内核 panic 或启动卡死 | 调整 crashkernel=@offset 避开保留区域 |
mem= 设置过小,无法容纳 crashkernel= |
系统可用内存不足,OOM 频繁 | 增大 mem= 或减小 crashkernel= |
4.4.3 生产环境推荐配置模板
# 64 GB 内存服务器,无坏内存,需要 kdump
GRUB_CMDLINE_LINUX="crashkernel=4G-64G:512M,64G-:1G"
# 32 GB 内存服务器,存在 128 MB 坏内存区域
GRUB_CMDLINE_LINUX="memmap=128M$0x20000000 crashkernel=256M"
# 16 GB 内存虚拟机,模拟 8 GB 环境并启用 kdump
GRUB_CMDLINE_LINUX="mem=8G crashkernel=128M@0x40000000"
dmesg | grep -E "memory|Memory|crash|reserved" — 查看内存识别与预留cat /proc/iomem | grep -E "Kernel|Crash|Reserved" — 查看物理地址空间分配kdumpctl status — 检查 kdump 服务是否就绪free -h — 确认系统可用内存符合预期
4.5 本章小结
- mem= 用于限制内核可见内存总量,适合内存测试和坏内存隔离,但会隐藏所有超出部分。
- memmap= 提供精细的区域属性控制,支持保留、强制可用、驱动预留三种操作,是解决固件兼容性和大页预留的首选工具。
- crashkernel= 为 kdump 预留转储空间,生产环境必须配置,推荐使用范围格式自动适配不同内存容量。
- 三个参数按
memmap → mem → crashkernel顺序处理,配置时需避免地址重叠和容量冲突。 - 每次修改引导参数后,务必通过
dmesg、/proc/iomem和kdumpctl status验证配置生效。