DPDK启动报Cannot init memory,主因是物理内存碎片化致无法凑出连续大页,叠加NUMA分布不均与CONFIG_RTE_MAX_MEMSEG=256限制;需查/proc/meminfo中HugePages_Free与HugePages_Rsvd是否矛盾、/proc/buddyinfo高阶页是否为0,并在grub中早期预留hugepages。

DPDK程序启动时卡在 rte_eal_init() 并报 Cannot init memory,大概率不是“没大页”,而是“有大页但没法凑出连续块”——这是物理内存碎片化 + NUMA 分布 + DPDK 内存段限制三者叠加的结果。
看 HugePages_Free 和 HugePages_Rsvd 是否矛盾
先快速确认是否真有可用大页,但被预留锁死:
- 执行
cat /proc/meminfo | grep -i huge,重点看三行:HugePages_Free、HugePages_Rsvd、Hugepagesize - 如果
HugePages_Free == 0且HugePages_Rsvd > 0,说明已有进程(可能是上一个没彻底退出的 DPDK 进程)占着预留位却不释放物理页,内核无法回收——此时即使总页数足够,rte_eal_init()也会失败 - 若
HugePages_Rsvd持续不归零,检查ps aux | grep dpdk和ls -l /var/run/.rte_*,残留的 Unix socket 或共享内存文件可能让 EAL 认为旧实例还在运行
查 /proc/buddyinfo 确认物理内存是否碎片化
DPDK 需要连续物理页(尤其用 2MB 页时),而 /proc/meminfo 只告诉你“总数”,不反映连续性。真正要看的是伙伴系统:
- 执行
cat /proc/buddyinfo,找对应 zone 的高阶页数(比如 2MB 页对应 order-9,1GB 页对应 order-18) - 若高阶页列全为 0(如
node 0, zone DMA32: 0 0 0 0 0 0 0 0 0 0 0),说明物理内存已被割裂成小块,哪怕HugePages_Total=4096,也分配不出一个连续 2MB 块 - 这种现象在系统运行较久、频繁启停 DPDK 进程后极常见;重启不是必须,但
echo 1 > /proc/sys/vm/compact_memory可尝试在线整理(对生产环境需谨慎)
验证 CONFIG_RTE_MAX_MEMSEG 是否成为瓶颈
DPDK 把申请到的大页切分成最多 CONFIG_RTE_MAX_MEMSEG 个内存段(默认 256)。当物理页高度离散时,EAL 可能拆出 300+ 小段,直接触发 Current CONFIG_RTE_MAX_MEMSEG=256 is not enough 报错:
- 查看当前值:
grep CONFIG_RTE_MAX_MEMSEG $RTE_SDK/config/common_base - 临时解决:编译 DPDK 时改大该值(如设为 512),再重编应用;但治标不治本——根源仍是内存未在启动早期预留
- 根本解法:在 grub 中加
hugepages=4096 default_hugepagesz=2M,确保系统启动时就锁定连续物理页,避免被 kernel 其他模块占用
注意 NUMA 节点绑定与挂载点错位
多路服务器上,DPDK 默认只从当前 CPU 所在 NUMA node 分配大页。若你挂载了 /dev/hugepages 但没指定 node,或 numactl --membind=0 启动却只在 node 1 预留了大页,就会“看得见、拿不到”:
- 检查各 node 大页数:
ls /sys/devices/system/node/node*/hugepages/,再进对应目录看nr_hugepages - 确认挂载点是否绑定了页大小:
mount | grep hugetlbfs,若挂载时没加-o pagesize=2MB,而系统默认是 1GB 页,则 2MB 申请会失败 - 启动 DPDK 前显式绑定:
numactl --cpunodebind=0 --membind=0 ./your_app -m 2048,强制使用 node 0 的资源
最易被忽略的一点:/dev/hugepages 是个伪文件系统,挂载行为本身不消耗内存,但 nr_hugepages 写入才真正触发物理页预留——很多人只改了 sysctl 却忘了 echo 到 /proc/sys/vm/nr_hugepages,或者改了 grub 却没 reboot,结果 /proc/meminfo 里数字永远是 0。











