dpdk学习之多进程simple_mp源代码分析

1.实现思路分析

dpdk提供了进程间共享的方法,需要以下几步来完成。
1.rte_ring需要与rte_mempool配合使用,通过rte_mempool来共享内存。

// flags:标识是单消费者/生产者或者多消费者/生产者struct rte_ring *ring = rte_ring_create("message_ring",
        ring_size, rte_socket_id(), flags);
struct rte_mempool *message_pool = rte_mempool_create(
        "message_pool", pool_size,
        string_size, pool_cache, 0,
        NULL, NULL, NULL, NULL,
        rte_socket_id(), flags);

2.首先primary进程创建ring和mempool,secondary进程在primary进程启动后,通过rte_ring_lookup和rte_mempool_lookup来获取ring和mempool的地址。

struct rte_ring *ring = rte_ring_lookup("message_ring");
struct rte_mempool *message_pool = rte_mempool_lookup(
        "message_pool");

3.使用时,rte_mempool_get从mempool中获取一个对象,然后使用rte_ring_enqueue入队列,另一个进程通过rte_ring_dequeue来出队列,使用完成后需要rte_mempool_put将对象放回mempool。

2.一步步进行代码分析

main函数,将在primary进程创建两个ring队列
- 发送队列 PRI_2_SEC
- 接受队列 SEC_2_PRI

对于secondary进程,查找发送和接受队列,顺序跟primary相反:
- 发送队列 SEC_2_PRI
- 接受队列 PRI_2_SEC

这里写图片描述

当在primary进程执行send hello1时,使用的是dpdk自带的cmdline库

struct cmdline *cl = cmdline_stdin_new(simple_mp_ctx, "\nsimple_mp > ");
    if (cl == NULL)
        rte_exit(EXIT_FAILURE, "Cannot create cmdline instance\n");
    cmdline_interact(cl);
    cmdline_stdin_exit(cl);

定位到simple_mp_ctx结构体中

cmdline_parse_ctx_t simple_mp_ctx[] = {
        (cmdline_parse_inst_t *)&cmd_send,
        (cmdline_parse_inst_t *)&cmd_quit,
        (cmdline_parse_inst_t *)&cmd_help,
    NULL,
};

cmd_send对应”send”命令的结构体指针
cmd_quit对应”quit”命令的结构体指针
cmd_help对应”help”命令的结构体指针
点击进入cmd_send

cmdline_parse_inst_t cmd_send = {
    .f = cmd_send_parsed,  /* function to call */
    .data = NULL,      /* 2nd arg of func */
    .help_str = "send a string to another process",
    .tokens = {        /* token list, NULL terminated */
            (void *)&cmd_send_action,
            (void *)&cmd_send_message,
            NULL,
    },
};

一切都清楚了,当在控制台输出send xxx命令时,会调用cmd_send_parsed函数进行逻辑处理

static void cmd_send_parsed(void *parsed_result,
        __attribute__((unused)) struct cmdline *cl,
        __attribute__((unused)) void *data)
{
    void *msg = NULL;
    struct cmd_send_result *res = parsed_result;
    //从内存池中获取一个对象
    if (rte_mempool_get(message_pool, &msg) < 0)
        rte_panic("Failed to get message buffer\n");
    snprintf((char *)msg, string_size, "%s", res->message);
    //ring入队操作
    if (rte_ring_enqueue(send_ring, msg) < 0) {
        printf("Failed to send message - message discarded\n");

        //将对象归还给内存池
        rte_mempool_put(message_pool, msg);
    }
}

对于primary进程,

/* call lcore_recv() on every slave lcore */
    RTE_LCORE_FOREACH_SLAVE(lcore_id) {
        rte_eal_remote_launch(lcore_recv, NULL, lcore_id);
    }

在每个slave核心上执行lcore_recv函数调用。lcore_recv函数代码如下:

static int
lcore_recv(__attribute__((unused)) void *arg)
{
    unsigned lcore_id = rte_lcore_id();

    printf("Starting core %u\n", lcore_id);
    while (!quit){
        void *msg;
        //ring 出队操作
        if (rte_ring_dequeue(recv_ring, &msg) < 0){
            usleep(5);
            continue;
        }
        printf("core %u: Received '%s'\n", lcore_id, (char *)msg);
        //将之前从内存池中获取的对象归还到内存池
        rte_mempool_put(message_pool, msg);
    }

    return 0;
}

3.

至此,我们总结下,进程之间通过ring来共享数据内容,数据内容是存储在从内存池申请的对象上的。
流程如下:
从内存池申请对象->入队ring->将对象归还给内存池

参考资料:

dpdk的使用说明,请参考
http://blog.csdn.net/njnu_mjn/article/details/52474300

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值