3. Linux 大页配置方法

大页(HugePages)是 DPDK 性能的基石。Linux 内核提供了三种配置大页的方式:临时配置(运行时调整)、永久配置(重启后生效)和启动时配置(内核引导参数)。三种方式适用于不同的运维场景,理解其差异是避免生产环境配置丢失的关键。

3.1 三种配置方式对比

配置方式 生效时机 持久性 适用场景
临时配置(/proc/sys/vm/nr_hugepages) 立即生效 重启后丢失 快速验证、开发调试、临时调优
永久配置(/etc/sysctl.conf) 重启后生效 / sysctl -p 立即加载 持久化 生产环境标准部署
启动时配置(hugepagesz= 内核参数) 系统引导时分配 持久化(需修改引导加载器) 需要 1G 巨页、早期内存预留、避免碎片化
最佳实践:生产环境推荐“启动时配置 + 永久配置”组合:启动时预留 1G 大页给 DPDK 数据面,永久配置保留 2MB 大页给控制面或辅助进程。

3.2 临时配置:/proc/sys/vm/nr_hugepages

通过写入 /proc 文件系统,可以立即调整大页数量,无需重启。这是开发阶段最常用的方法。

配置步骤

  1. 查看当前大页状态
# 查看系统大页信息
cat /proc/meminfo | grep -i huge
# 输出示例:
# AnonHugePages:         0 kB
# ShmemHugePages:        0 kB
# HugePages_Total:       0
# HugePages_Free:        0
# HugePages_Rsvd:        0
# HugePages_Surp:        0
# Hugepagesize:       2048 kB
  1. 分配 2MB 大页(以 1024 个为例)
# 分配 1024 个 2MB 大页,共 2GB
echo 1024 > /proc/sys/vm/nr_hugepages

# 验证分配结果
cat /proc/meminfo | grep HugePages_Total
# 期望输出:HugePages_Total:    1024
  1. 分配特定 NUMA 节点的大页
# 在 NUMA node0 上分配 512 个 2MB 大页
echo 512 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages

# 在 NUMA node1 上分配 512 个 2MB 大页
echo 512 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages
注意:临时配置在系统重启后失效。如果内存碎片严重,echo 操作可能分配少于请求的数量,务必检查 HugePages_Total 确认实际分配值。

3.3 永久配置:/etc/sysctl.conf

将大页参数写入 /etc/sysctl.conf 或 /etc/sysctl.d/ 下的独立配置文件,实现重启后自动生效。

配置步骤

  1. 编辑 sysctl 配置文件
# 使用 root 权限编辑
vim /etc/sysctl.conf

# 添加以下行(分配 2048 个 2MB 大页,共 4GB)
vm.nr_hugepages = 2048

# 可选:设置大页池最小值,防止被回收
vm.nr_hugepages_mempolicy = 2048
  1. 立即加载配置(无需重启)
# 使配置立即生效
sysctl -p

# 验证
sysctl vm.nr_hugepages
# 输出:vm.nr_hugepages = 2048
  1. NUMA 感知的永久配置(推荐)
# 在 /etc/sysctl.d/99-hugepages.conf 中配置
# node0 分配 1024 个 2MB 大页
vm.nr_hugepages = 2048
# 注意:sysctl 不支持直接设置 per-node 参数,
# 需要在启动脚本中通过 echo 写入 /sys/devices/system/node/ 下的接口
生产建议:在 /etc/sysctl.d/ 下创建独立配置文件(如 99-dpdk-hugepages.conf),便于管理和回滚。配置格式为 vm.nr_hugepages = 数量。

3.4 启动时配置:hugepagesz= 内核参数

通过内核引导参数在系统启动早期预留大页,支持 1GB 巨页,避免运行时分配失败。需要修改 GRUB 配置。

配置步骤

  1. 编辑 GRUB 配置
# 编辑 /etc/default/grub
vim /etc/default/grub

# 找到 GRUB_CMDLINE_LINUX 行,添加大页参数
# 示例:预留 4 个 1GB 大页,8 个 2MB 大页
GRUB_CMDLINE_LINUX="... default_hugepagesz=1G hugepagesz=1G hugepages=4 hugepagesz=2M hugepages=8"
  1. 更新 GRUB 引导器
# 对于 BIOS 系统
grub2-mkconfig -o /boot/grub2/grub.cfg

# 对于 UEFI 系统
grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg

# 重启系统
reboot
  1. 验证启动时分配
# 重启后检查大页状态
cat /proc/meminfo | grep -E "HugePages_Total|Hugepagesize"
# 期望输出:
# HugePages_Total:      12   (4个1G + 8个2M)
# Hugepagesize:    1048576 kB  (默认显示最后配置的页面大小)

# 查看 1G 大页的 NUMA 分布
cat /sys/devices/system/node/node*/hugepages/hugepages-1048576kB/nr_hugepages
关键约束:
  • default_hugepagesz 必须与第一个 hugepagesz= 一致。
  • 1GB 大页只能在启动时预留,不支持运行时 echo 分配。
  • 不同架构支持的页面大小不同:x86_64 支持 2MB 和 1GB;ARM64 支持 64KB、2MB 和 1GB。

3.5 大页配置流程总览

大页配置方式决策流程 确定大页需求 需要 1G 巨页? 启动时配置 hugepagesz=1G 生产环境? 永久配置 /etc/sysctl.conf 临时配置 /proc/sys/vm/nr_hugepages 挂载 hugetlbfs + 配置 DPDK 生产组合:启动时 1G + 永久 2MB 开发调试:临时配置快速验证

3.6 配置验证与常见问题

验证清单

检查项 命令 预期结果
大页总数 cat /proc/meminfo | grep HugePages_Total 等于配置值
空闲大页 cat /proc/meminfo | grep HugePages_Free 大于等于 DPDK 需求
NUMA 分布 cat /sys/devices/system/node/node*/hugepages/hugepages-2048kB/nr_hugepages 各节点数量符合预期
大页挂载 mount | grep hugetlbfs 显示挂载点和页面大小
DPDK 检测 dpdk-hugepages.py -s 显示可用大页数量和大小

常见问题与解决

  • 分配数量不足:检查 dmesg | grep huge 查看内核是否因内存碎片拒绝分配。尝试启动时预留或减少其他内存占用。
  • NUMA 节点分配不均:使用 numactl --hardware 查看节点内存大小,按比例分配。DPDK 的 --socket-mem 参数需与 NUMA 大页分布匹配。
  • 1G 大页未生效:确认 CPU 支持 1G 页面(cat /proc/cpuinfo | grep pdpe1gb),且内核编译开启 CONFIG_HUGETLB_PAGE 和 CONFIG_HUGETLBFS。
  • 重启后配置丢失:检查 /etc/sysctl.conf 语法错误,或 GRUB 配置未正确更新。运行 sysctl -p 测试加载。
快速诊断脚本:
#!/bin/bash
# 大页健康检查
echo "=== HugePages Info ==="
grep -E "HugePages_Total|HugePages_Free|Hugepagesize" /proc/meminfo
echo ""
echo "=== NUMA Distribution ==="
for node in /sys/devices/system/node/node*/hugepages/hugepages-2048kB; do
  echo "$(basename $(dirname $(dirname $node))): $(cat $node/nr_hugepages)"
done
echo ""
echo "=== Mount Points ==="
mount | grep hugetlbfs

3.7 配置策略总结

选择配置方式的核心原则:1G 大页必须启动时预留,2MB 大页生产环境用永久配置,开发调试用临时配置。无论哪种方式,配置后务必通过 /proc/meminfo 和 NUMA 节点接口双重验证,确保 DPDK 运行时有足够的大页资源可用。