适用系统:Rocky Linux 9/10、RHEL 9/10、AlmaLinux 9/10、CentOS Stream 9/10
一、背景知识
1.1 什么是 IOMMU?
IOMMU(Input-Output Memory Management Unit)是设备直接内存访问(DMA)的地址翻译与保护单元,Intel 平台对应 VT-d (内核日志中表现为 DMAR),AMD 平台对应 AMD-Vi。
| 场景 | 是否需要关闭 IOMMU |
|---|---|
| 普通物理机、虚拟机宿主 | ❌ 保持开启(安全性更好) |
| 旧硬件兼容性问题 | ✅ 考虑关闭 |
| 某些 PCIe 直通 / GPU 透传异常 | ✅ 临时关闭调试 |
| 性能敏感且无虚拟化需求 | ⚠️ 评估后决定 |
1.2 为什么要用 grubby 而不是改配置文件?
在 RHEL 8 之前,修改内核参数的标准做法是编辑 /etc/default/grub 后执行 grub2-mkconfig 重新生成引导配置。而在 RHEL 9/10 系列中,官方推荐直接使用 grubby:
#mermaid-svg-f8H9RBvjPfn4ykgx{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-f8H9RBvjPfn4ykgx .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-f8H9RBvjPfn4ykgx .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-f8H9RBvjPfn4ykgx .error-icon{fill:#552222;}#mermaid-svg-f8H9RBvjPfn4ykgx .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-f8H9RBvjPfn4ykgx .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-f8H9RBvjPfn4ykgx .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-f8H9RBvjPfn4ykgx .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-f8H9RBvjPfn4ykgx .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-f8H9RBvjPfn4ykgx .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-f8H9RBvjPfn4ykgx .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-f8H9RBvjPfn4ykgx .marker{fill:#333333;stroke:#333333;}#mermaid-svg-f8H9RBvjPfn4ykgx .marker.cross{stroke:#333333;}#mermaid-svg-f8H9RBvjPfn4ykgx svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-f8H9RBvjPfn4ykgx p{margin:0;}#mermaid-svg-f8H9RBvjPfn4ykgx .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-f8H9RBvjPfn4ykgx .cluster-label text{fill:#333;}#mermaid-svg-f8H9RBvjPfn4ykgx .cluster-label span{color:#333;}#mermaid-svg-f8H9RBvjPfn4ykgx .cluster-label span p{background-color:transparent;}#mermaid-svg-f8H9RBvjPfn4ykgx .label text,#mermaid-svg-f8H9RBvjPfn4ykgx span{fill:#333;color:#333;}#mermaid-svg-f8H9RBvjPfn4ykgx .node rect,#mermaid-svg-f8H9RBvjPfn4ykgx .node circle,#mermaid-svg-f8H9RBvjPfn4ykgx .node ellipse,#mermaid-svg-f8H9RBvjPfn4ykgx .node polygon,#mermaid-svg-f8H9RBvjPfn4ykgx .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-f8H9RBvjPfn4ykgx .rough-node .label text,#mermaid-svg-f8H9RBvjPfn4ykgx .node .label text,#mermaid-svg-f8H9RBvjPfn4ykgx .image-shape .label,#mermaid-svg-f8H9RBvjPfn4ykgx .icon-shape .label{text-anchor:middle;}#mermaid-svg-f8H9RBvjPfn4ykgx .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-f8H9RBvjPfn4ykgx .rough-node .label,#mermaid-svg-f8H9RBvjPfn4ykgx .node .label,#mermaid-svg-f8H9RBvjPfn4ykgx .image-shape .label,#mermaid-svg-f8H9RBvjPfn4ykgx .icon-shape .label{text-align:center;}#mermaid-svg-f8H9RBvjPfn4ykgx .node.clickable{cursor:pointer;}#mermaid-svg-f8H9RBvjPfn4ykgx .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-f8H9RBvjPfn4ykgx .arrowheadPath{fill:#333333;}#mermaid-svg-f8H9RBvjPfn4ykgx .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-f8H9RBvjPfn4ykgx .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-f8H9RBvjPfn4ykgx .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-f8H9RBvjPfn4ykgx .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-f8H9RBvjPfn4ykgx .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-f8H9RBvjPfn4ykgx .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-f8H9RBvjPfn4ykgx .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-f8H9RBvjPfn4ykgx .cluster text{fill:#333;}#mermaid-svg-f8H9RBvjPfn4ykgx .cluster span{color:#333;}#mermaid-svg-f8H9RBvjPfn4ykgx div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-f8H9RBvjPfn4ykgx .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-f8H9RBvjPfn4ykgx rect.text{fill:none;stroke-width:0;}#mermaid-svg-f8H9RBvjPfn4ykgx .icon-shape,#mermaid-svg-f8H9RBvjPfn4ykgx .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-f8H9RBvjPfn4ykgx .icon-shape p,#mermaid-svg-f8H9RBvjPfn4ykgx .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-f8H9RBvjPfn4ykgx .icon-shape .label rect,#mermaid-svg-f8H9RBvjPfn4ykgx .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-f8H9RBvjPfn4ykgx .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-f8H9RBvjPfn4ykgx .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-f8H9RBvjPfn4ykgx :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} grubby 方式(直接、安全)
grubby --update-kernel
一条命令
重启生效
传统方式(步骤多、易出错)
编辑
/etc/default/grub
grub2-mkconfig
重新生成配置
重启生效
核心优势:
- ✅ 直接修改 BTF / BLS(Boot Loader Specification)条目,无需重新生成引导配置;
- ✅ 自动适配 BIOS/Legacy 与 UEFI 的引导配置路径差异(无需记忆
grub.cfg到底在/boot/grub2/还是/boot/efi/EFI/rocky/); - ✅ 支持精确到单个内核条目 或全部内核的操作,可脚本化;
- ✅ 配合
--remove-args可干净回滚。
1.3 关键参数说明
| 参数 | 作用 | 适用平台 |
|---|---|---|
intel_iommu=off |
关闭 Intel VT-d | Intel |
amd_iommu=off |
关闭 AMD-Vi | AMD |
iommu=off |
彻底禁用 IOMMU 子系统(一刀切,影响面大) | 通用 |
iommu=pt |
直通模式:仅对直通设备启用 IOMMU(折中方案,推荐优先尝试) | 通用 |
⚠️ 建议 :生产环境优先尝试
iommu=pt(直通模式),既保留安全性又避免翻译开销;确认无需求后再考虑完全关闭。
二、操作前检查
bash
# 1. 确认系统中有多个可回退的内核条目(防止改错后无法启动)
sudo grubby --info=ALL | grep -E "^(index|title|kernel)="
# 2. 查看当前正在运行的内核及其启动参数
uname -r
cat /proc/cmdline
# 3. 确认当前 IOMMU 状态(有 DMAR / AMD-Vi 输出即为开启)
sudo dmesg | grep -i -E "iommu|DMAR|AMD-Vi"
💡 安全原则 :操作前确保系统至少保留 2 个内核条目,万一新参数导致无法启动,可在 GRUB 菜单中选择旧内核进入系统后回滚。
三、使用 grubby 关闭 IOMMU(完整流程)
3.1 流程总览
#mermaid-svg-ZC3uvFPdNN6iwtIT{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ZC3uvFPdNN6iwtIT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ZC3uvFPdNN6iwtIT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ZC3uvFPdNN6iwtIT .error-icon{fill:#552222;}#mermaid-svg-ZC3uvFPdNN6iwtIT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ZC3uvFPdNN6iwtIT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ZC3uvFPdNN6iwtIT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ZC3uvFPdNN6iwtIT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ZC3uvFPdNN6iwtIT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ZC3uvFPdNN6iwtIT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ZC3uvFPdNN6iwtIT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ZC3uvFPdNN6iwtIT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ZC3uvFPdNN6iwtIT .marker.cross{stroke:#333333;}#mermaid-svg-ZC3uvFPdNN6iwtIT svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ZC3uvFPdNN6iwtIT p{margin:0;}#mermaid-svg-ZC3uvFPdNN6iwtIT .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ZC3uvFPdNN6iwtIT .cluster-label text{fill:#333;}#mermaid-svg-ZC3uvFPdNN6iwtIT .cluster-label span{color:#333;}#mermaid-svg-ZC3uvFPdNN6iwtIT .cluster-label span p{background-color:transparent;}#mermaid-svg-ZC3uvFPdNN6iwtIT .label text,#mermaid-svg-ZC3uvFPdNN6iwtIT span{fill:#333;color:#333;}#mermaid-svg-ZC3uvFPdNN6iwtIT .node rect,#mermaid-svg-ZC3uvFPdNN6iwtIT .node circle,#mermaid-svg-ZC3uvFPdNN6iwtIT .node ellipse,#mermaid-svg-ZC3uvFPdNN6iwtIT .node polygon,#mermaid-svg-ZC3uvFPdNN6iwtIT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ZC3uvFPdNN6iwtIT .rough-node .label text,#mermaid-svg-ZC3uvFPdNN6iwtIT .node .label text,#mermaid-svg-ZC3uvFPdNN6iwtIT .image-shape .label,#mermaid-svg-ZC3uvFPdNN6iwtIT .icon-shape .label{text-anchor:middle;}#mermaid-svg-ZC3uvFPdNN6iwtIT .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ZC3uvFPdNN6iwtIT .rough-node .label,#mermaid-svg-ZC3uvFPdNN6iwtIT .node .label,#mermaid-svg-ZC3uvFPdNN6iwtIT .image-shape .label,#mermaid-svg-ZC3uvFPdNN6iwtIT .icon-shape .label{text-align:center;}#mermaid-svg-ZC3uvFPdNN6iwtIT .node.clickable{cursor:pointer;}#mermaid-svg-ZC3uvFPdNN6iwtIT .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ZC3uvFPdNN6iwtIT .arrowheadPath{fill:#333333;}#mermaid-svg-ZC3uvFPdNN6iwtIT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ZC3uvFPdNN6iwtIT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ZC3uvFPdNN6iwtIT .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZC3uvFPdNN6iwtIT .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ZC3uvFPdNN6iwtIT .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZC3uvFPdNN6iwtIT .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ZC3uvFPdNN6iwtIT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ZC3uvFPdNN6iwtIT .cluster text{fill:#333;}#mermaid-svg-ZC3uvFPdNN6iwtIT .cluster span{color:#333;}#mermaid-svg-ZC3uvFPdNN6iwtIT div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ZC3uvFPdNN6iwtIT .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ZC3uvFPdNN6iwtIT rect.text{fill:none;stroke-width:0;}#mermaid-svg-ZC3uvFPdNN6iwtIT .icon-shape,#mermaid-svg-ZC3uvFPdNN6iwtIT .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZC3uvFPdNN6iwtIT .icon-shape p,#mermaid-svg-ZC3uvFPdNN6iwtIT .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ZC3uvFPdNN6iwtIT .icon-shape .label rect,#mermaid-svg-ZC3uvFPdNN6iwtIT .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZC3uvFPdNN6iwtIT .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ZC3uvFPdNN6iwtIT .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ZC3uvFPdNN6iwtIT :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
开始
① 查看当前内核参数
cat /proc/cmdline
② 添加关闭 IOMMU 参数
grubby --update-kernel=ALL --args='...'
③ 验证参数已写入
grubby --info
④ 重启系统
reboot
⑤ 验证运行时生效
cat /proc/cmdline + dmesg
IOMMU 已关闭?
✅ 完成
检查是否漏改内核 /
GRUB 菜单选择错误
3.2 步骤详解
① 查看当前内核启动参数
bash
# 方式一:查看运行时生效的参数
cat /proc/cmdline
# 方式二:查看当前内核条目的完整配置(args 行即启动参数)
sudo grubby --info /boot/vmlinuz-$(uname -r)
# 方式三:查看所有内核条目
sudo grubby --info=ALL
② 添加关闭 IOMMU 的参数
bash
# Intel + AMD 平台参数同时写入(保留对应项即可,多余的参数无害)
sudo grubby --update-kernel=ALL --args="intel_iommu=off amd_iommu=off"
# 或者:彻底禁用 IOMMU 子系统
sudo grubby --update-kernel=ALL --args="iommu=off"
参数说明:
--update-kernel=ALL------ 修改所有已安装内核的条目,保证切换旧内核时参数依然生效;--update-kernel=DEFAULT------ 只修改默认启动的内核,适合临时调试;--update-kernel=/boot/vmlinuz-<版本>------ 精确修改指定内核。
③ 验证参数已添加(重启前)
bash
sudo grubby --info /boot/vmlinuz-$(uname -r) | grep args
输出示例(注意末尾已出现新参数):
args="ro crashkernel=1G-4G:192M,4G-64G:256M,64G-:512M resume=/dev/mapper/rl-swap rd.lvm.lv=rl/root rd.lvm.lv=rl/swap rhgb quiet intel_iommu=off amd_iommu=off"
④ 重启系统
bash
sudo reboot
⑤ 验证生效(重启后)
bash
# 确认参数已进入运行时内核命令行
cat /proc/cmdline
# 确认 IOMMU 已被禁用:无 DMAR / AMD-Vi 初始化输出即为成功
sudo dmesg | grep -i -E "iommu|DMAR|AMD-Vi"
✅ 成功标志 :dmesg 中不再出现 DMAR: Host address width ...(Intel)或 AMD-Vi: ...(AMD)初始化日志。
四、grubby 常用操作速查表
| 操作 | 命令 |
|---|---|
| 查看默认内核索引 | sudo grubby --default-index |
| 查看默认内核路径 | sudo grubby --default-kernel |
| 查看所有内核条目 | sudo grubby --info=ALL |
| 查看指定内核条目 | sudo grubby --info /boot/vmlinuz-<版本> |
| 给所有内核加参数 | sudo grubby --update-kernel=ALL --args="参数" |
| 只给默认内核加参数 | sudo grubby --update-kernel=DEFAULT --args="参数" |
| 移除参数(回滚) | sudo grubby --update-kernel=ALL --remove-args="参数" |
| 设置默认启动内核 | sudo grubby --set-default /boot/vmlinuz-<版本> |
⚠️
--remove-args必须与添加时的参数值完全一致 (包括=和值),否则无法匹配移除。
五、grubby vs 手动编辑配置对比
| 维度 | grubby | 手动编辑 /etc/default/grub + grub2-mkconfig |
|---|---|---|
| 操作步骤 | 一条命令 | 编辑文件 + 重新生成配置 + 重启 |
| UEFI/BIOS 路径差异 | 自动处理 | 需手动区分 grub.cfg 路径 |
| 粒度控制 | 可精确到单个内核 | 对所有内核统一生效 |
| 参数管理 | 分散在各内核条目中 | 集中在一处,可读性好 |
| 回滚 | --remove-args 一键回滚 |
需再次编辑并重新生成 |
| 脚本化 / 自动化 | ✅ 友好 | ❌ 繁琐 |
| 误操作风险 | 低 | 较高(配置写错可能导致无法启动) |
结论 :在 Rocky / RHEL 系列中,优先使用 grubby 修改内核参数;仅当需要统一管理大量参数或维护多发行版通用配置时,才考虑手动编辑方式。
六、故障排查(Troubleshooting)
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
| 重启后参数未生效 | 只改了默认内核,实际启动的是其他内核 | grubby --info=ALL 检查各条目,用 --update-kernel=ALL 统一修改 |
cat /proc/cmdline 有参数但 dmesg 仍有 DMAR |
参数写法错误(如 iommu=0) |
确认使用 =off 而不是 =0/=false |
--remove-args 移除失败 |
参数值与添加时不一致 | 先用 grubby --info 查看当前 args 的准确值 |
| 系统无法启动 | 参数与其他配置冲突 | 在 GRUB 菜单按 e 编辑启动项临时删除参数进入系统,再执行回滚命令 |
七、学习笔记与最佳实践
- 先小范围测试,再全量应用 :新参数先用
--update-kernel=DEFAULT验证稳定,再--update-kernel=ALL铺开; - 保留回退路径:操作前确认存在 ≥2 个内核条目;
- 优先折中方案 :IOMMU 问题优先尝试
iommu=pt,而非直接iommu=off; - grubby 修改即时写入 BLS 文件 (
/boot/loader/entries/*.conf),可查看该目录辅助排查; - 自动化场景(Ansible / Kickstart 脚本)中优先使用 grubby,保证幂等性。
八、参考链接
- RHEL 9 官方文档 --- 使用 grubby 配置内核参数
- grubby(8) man page
- Linux Kernel Parameters 文档:`Documentation/admin-guide/kernel-parameters.txt