DPDK17.02内存池管理2 – rte_mempool_ops
内存池通过DPDK中注册的一系列处理函数进行管理操作。
1、数据结构
共涉及到两个数据结构。
1.1 struct rte_mempool_ops
该数据结构定义了对 mempool 进行操作的各个函数接口
1 2 3 4 5 6 7 8 | struct rte_mempool_ops { char name[RTE_MEMPOOL_OPS_NAMESIZE]; /**< mempool 操作的名称 */ rte_mempool_alloc_t alloc; /**< 分配私有数据 */ rte_mempool_free_t free; /**< 释放外部内存池 */ rte_mempool_enqueue_t enqueue; /**< 入队一个对象 */ rte_mempool_dequeue_t dequeue; /**< 出队一个对象 */ rte_mempool_get_count get_count; /**< 获取有效的对象数 */ } __rte_cache_aligned; |
1.2 struct rte_mempool_ops_table
该数据结构使用一个数组保存已注册的 ops 结构。
每个进程都有其自己的结构用来保存这些 ops 结构,因此 mempool 可以在主进程和次进程之间共享。
1 2 3 4 5 6 | struct rte_mempool_ops_table { rte_spinlock_t sl; /**< 添加或删除 ops 的锁 */ uint32_t num_ops; /**< 表中使用的 ops 结构的数量 */ /* 保存所有的 struct rte_mempool_ops 数据结构 */ struct rte_mempool_ops ops[RTE_MEMPOOL_MAX_OPS_IDX]; /* 最多16个 */ } __rte_cache_aligned; |
2、注册新的 struct rte_mempool_ops
DPDK 使用 rte_mempool_register_ops() 函数对新的 ops 结构进行注册。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | int rte_mempool_register_ops(const struct rte_mempool_ops *h) { struct rte_mempool_ops *ops; int16_t ops_index; rte_spinlock_lock(&rte_mempool_ops_table.sl); if (rte_mempool_ops_table.num_ops >= RTE_MEMPOOL_MAX_OPS_IDX) { /* 如果数组已经满了 */ rte_spinlock_unlock(&rte_mempool_ops_table.sl); RTE_LOG(ERR, MEMPOOL, "Maximum number of mempool ops structs exceeded\n"); return -ENOSPC; } if (h->alloc == NULL || h->enqueue == NULL || h->dequeue == NULL || h->get_count == NULL) { /* 这四个回调函数必须指定 */ rte_spinlock_unlock(&rte_mempool_ops_table.sl); RTE_LOG(ERR, MEMPOOL, "Missing callback while registering mempool ops\n"); return -EINVAL; } if (strlen(h->name) >= sizeof(ops->name) - 1) { /* ops 使用的名字太长 */ rte_spinlock_unlock(&rte_mempool_ops_table.sl); RTE_LOG(DEBUG, EAL, "%s(): mempool_ops <%s>: name too long\n", __func__, h->name); rte_errno = EEXIST; return -EEXIST; } /* 初始化 */ ops_index = rte_mempool_ops_table.num_ops++; ops = &rte_mempool_ops_table.ops[ops_index]; snprintf(ops->name, sizeof(ops->name), "%s", h->name); ops->alloc = h->alloc; ops->free = h->free; ops->enqueue = h->enqueue; ops->dequeue = h->dequeue; ops->get_count = h->get_count; rte_spinlock_unlock(&rte_mempool_ops_table.sl); return ops_index; /* 返回当前 ops 的索引 */ } |
3、MEMPOOL_REGISTER_OPS 宏
DPDK中使用该宏来注册 mempool 处理函数。
1 2 3 4 5 6 | #define MEMPOOL_REGISTER_OPS(ops) \ void mp_hdlr_init_##ops(void); \ void __attribute__((constructor, used)) mp_hdlr_init_##ops(void)\ { \ rte_mempool_register_ops(&ops); \ } |
需要注意的是,如果注册失败,这里不会有任何提示。
4、rte_mempool_set_ops_byname() 函数
该函数为指定的 mp 指定对应的 ops。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | int rte_mempool_set_ops_byname(struct rte_mempool *mp, const char *name, void *pool_config) { struct rte_mempool_ops *ops = NULL; unsigned i; if (mp->flags & MEMPOOL_F_POOL_CREATED) /* 太晚了,mempool 已经被填充了 */ return -EEXIST; /* 根据指定的 ops 的名字,查找对应的 ops 结构 */ for (i = 0; i < rte_mempool_ops_table.num_ops; i++) { if (!strcmp(name, rte_mempool_ops_table.ops[i].name)) { ops = &rte_mempool_ops_table.ops[i]; break; } } if (ops == NULL) return -EINVAL; mp->ops_index = i; mp->pool_config = pool_config; return 0; } |
5、mempool 处理函数
DPDK 中默认使用了 4 组处理函数,分别对应多生产者多消费者,单生产者单消费者,多生产者单消费者,单生产者多消费者。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | static const struct rte_mempool_ops ops_mp_mc = { .name = "ring_mp_mc", /* 多生产者多消费者 */ .alloc = common_ring_alloc, .free = common_ring_free, .enqueue = common_ring_mp_enqueue, .dequeue = common_ring_mc_dequeue, .get_count = common_ring_get_count, }; static const struct rte_mempool_ops ops_sp_sc = { .name = "ring_sp_sc", /* 单生产者单消费者 */ .alloc = common_ring_alloc, .free = common_ring_free, .enqueue = common_ring_sp_enqueue, .dequeue = common_ring_sc_dequeue, .get_count = common_ring_get_count, }; static const struct rte_mempool_ops ops_mp_sc = { .name = "ring_mp_sc", /* 多生产者单消费者 */ .alloc = common_ring_alloc, .free = common_ring_free, .enqueue = common_ring_mp_enqueue, .dequeue = common_ring_sc_dequeue, .get_count = common_ring_get_count, }; static const struct rte_mempool_ops ops_sp_mc = { .name = "ring_sp_mc", /* 单生产者多消费者 */ .alloc = common_ring_alloc, .free = common_ring_free, .enqueue = common_ring_sp_enqueue, .dequeue = common_ring_mc_dequeue, .get_count = common_ring_get_count, }; /* 注册以上 4 组 mempool 处理函数 */ MEMPOOL_REGISTER_OPS(ops_mp_mc); MEMPOOL_REGISTER_OPS(ops_sp_sc); MEMPOOL_REGISTER_OPS(ops_mp_sc); MEMPOOL_REGISTER_OPS(ops_sp_mc); |
————————————————————
原创文章,转载请注明: 转载自孙希栋的博客