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实时查询。

rte_mempool 对象0: rte_mbuf头部 + 数据区 对象1: rte_mbuf头部 + 数据区 对象2: rte_mbuf头部 + 数据区 ... 共8192个对象 rte_pktmbuf_alloc rte_pktmbuf_free rte_mbuf结构 头部: 元数据(池指针、长度等) 数据区: 实际存储内容 私有数据(本例为0)

常见问题

  • EAL初始化失败:确认已设置hugepage(echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages)
  • 内存池创建失败:检查rte_errno,常见原因为内存不足或hugepage不够
  • 编译链接错误:确认pkg-config --cflags --libs libdpdk输出正确