3. DPDK内存池管理
任务目标
在DPDK中创建内存池(mempool),从中分配/释放mbuf,并理解rte_mempool与rte_mbuf的结构关系。本案例使用DPDK 21.11 LTS,以最小可运行代码演示内存池的完整生命周期。
核心概念
DPDK内存池基于rte_mempool实现无锁环形缓冲区管理,每个内存池在创建时预分配固定数量的对象(mbuf)。rte_mbuf结构体位于对象起始处,其后跟随用户数据区。分配操作从pool中取出一个对象,释放操作将其归还,整个过程无系统调用。
完整代码
#include <rte_eal.h>
#include <rte_mempool.h>
#include <rte_mbuf.h>
#include <stdio.h>
#define POOL_SIZE 8192
#define CACHE_SIZE 256
#define MBUF_SIZE 2048
int main(int argc, char *argv[]) {
// 1. 初始化EAL环境
if (rte_eal_init(argc, argv) < 0) {
printf("EAL初始化失败\n");
return -1;
}
// 2. 创建内存池
struct rte_mempool *pool = rte_pktmbuf_pool_create(
"MBUF_POOL", // 池名称
POOL_SIZE, // 对象数量
CACHE_SIZE, // 每核缓存大小
0, // 私有数据大小
MBUF_SIZE, // mbuf数据区大小
SOCKET_ID_ANY // 任意NUMA节点
);
if (pool == NULL) {
printf("内存池创建失败: %s\n", rte_strerror(rte_errno));
rte_eal_cleanup();
return -1;
}
printf("内存池创建成功,对象数: %u\n", rte_mempool_avail_count(pool));
// 3. 从池中分配一个mbuf
struct rte_mbuf *mbuf = rte_pktmbuf_alloc(pool);
if (mbuf == NULL) {
printf("mbuf分配失败\n");
rte_mempool_free(pool);
rte_eal_cleanup();
return -1;
}
printf("mbuf分配成功,池中剩余: %u\n", rte_mempool_avail_count(pool));
// 4. 写入并读取数据(验证mbuf可用)
char *data = rte_pktmbuf_append(mbuf, 64);
if (data == NULL) {
printf("数据区扩展失败\n");
rte_pktmbuf_free(mbuf);
rte_mempool_free(pool);
rte_eal_cleanup();
return -1;
}
snprintf(data, 64, "DPDK mempool test");
printf("写入数据: %s\n", rte_pktmbuf_mtod(mbuf, char *));
// 5. 释放mbuf回池
rte_pktmbuf_free(mbuf);
printf("mbuf已释放,池中可用: %u\n", rte_mempool_avail_count(pool));
// 6. 清理资源
rte_mempool_free(pool);
rte_eal_cleanup();
printf("资源清理完成\n");
return 0;
}
编译与运行
# 编译(假设DPDK已安装并设置RTE_SDK/RTE_TARGET)
gcc -o mempool_demo mempool_demo.c $(pkg-config --cflags --libs libdpdk)
# 运行(需要root权限或设置hugepage)
sudo ./mempool_demo
验证方法
程序输出应依次显示:
内存池创建成功,对象数: 8192
mbuf分配成功,池中剩余: 8191
写入数据: DPDK mempool test
mbuf已释放,池中可用: 8192
资源清理完成
判定通过条件:
- 内存池创建后可用对象数为8192(初始值)
- 分配1个mbuf后可用数减为8191
- 释放后可用数恢复为8192
- 写入的数据能正确读回
结构说明
rte_pktmbuf_pool_create是rte_mempool_create的封装,自动为每个对象预留rte_mbuf头部空间。rte_pktmbuf_alloc从池中获取对象并初始化mbuf字段;rte_pktmbuf_free将mbuf归还池中。池中对象数量变化可通过rte_mempool_avail_count实时查询。
常见问题
- EAL初始化失败:确认已设置hugepage(
echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages) - 内存池创建失败:检查
rte_errno,常见原因为内存不足或hugepage不够 - 编译链接错误:确认
pkg-config --cflags --libs libdpdk输出正确