dpdk的无锁环形队列Ring

1. DPDK Ring简介

dpdk实现了一个无锁环形队列Ring,可用于在dpdk不同的应用程序之间进行通信。

Ring支持的效果:

  • 先进先出
  • 最大大小是固定的,指针存储在表中
  • 无锁实现
  • 多消费者或单消费者出队
  • 多生产者或单生产者入队
    DPDK Ring
struct rte_ring {                                                                                                                            
     /* Ring producer status. */                                                                                
     struct prod {                                                                                                
         uint32_t watermark;     /**< Maximum itemsbefore EDQUOT. */                                             
         uint32_t sp_enqueue;    /**< True, if single producer. */                                                
         uint32_t size;          /**< Size of ring.*/                                                           
         uint32_t mask;          /**< Mask (size-1)of ring. */                                                   
         volatile uint32_thead;  /**< Producer head.*/                                                           
         volatileuint32_t tail;  /**< Producer tail.*/                                                           
     } prod __rte_cache_aligned;                                                 
     /* Ring consumer status. */                                                                                
     struct cons {                                                                                                
         uint32_t sc_dequeue;    /**< True, if single consumer. */                                                
         uint32_t size;          /**< Size of thering. */                                                       
         uint32_t mask;          /**< Mask (size-1)of ring. */                                                   
         volatileuint32_t head;  /**< Consumer head.*/                                                           
         volatileuint32_t tail;  /**< Consumer tail.*/                                                                                                                                      
     } cons __rte_cache_aligned;                                                                                  
    void*ring[] __rte_cache_aligned;  
 };

2. Ring实现

2.1 单一生产者入队

首先,将ring-> prod_head和ring-> cons_tail复制到局部变量中。prod_next局部变量指向表的下一个元素,或在批量入队的情况下指向多个元素。

如果环中没有足够的空间(通过检查cons_tail可以检测到),它将返回错误。
1
第二步是修改环结构中的ring-> prod_head以指向与prod_next相同的位置。

指向添加对象的指针将复制到环(obj4)中。
2

将对象添加到环中后,将修改环结构中的ring-> prod_tail使其指向与ring-> prod_head相同的位置。入队操作完成。
3

2.2 单一消费者出队

首先,将ring-> cons_head和ring-> prod_tail复制到局部变量中。cons_next局部变量指向表的下一个元素,或在批量出队的情况下指向多个元素。

如果环中没有足够的对象(通过检查prod_tail可以检测到),它将返回错误。

1

第二步是修改ring结构中的ring-> cons_head,使其指向与cons_next相同的位置。

指向出队对象(obj1)的指针被复制到用户指定的指针中。
2
最后,将ring结构中的ring-> cons_tail修改为指向与ring-> cons_head相同的位置。出队操作完成。

3

2.3 多个生产者入队

当两个生产者同时将对象添加到环时会发生什么?

在两个CPU core上,ring-> prod_head和ring-> cons_tail都复制到局部变量中。prod_next局部变量指向表的下一个元素,或者在批量入队的情况下指向多个元素。

如果环中没有足够的空间(通过检查cons_tail可以检测到),它将返回错误。

1

第二步是修改ring结构中的ring-> prod_head以指向与prod_next相同的位置。此操作使用“比较并交换”(CAS)指令完成,该指令自动执行以下操作:

  • 如果ring-> prod_head与局部变量prod_head不同,则CAS操作失败,并且代码在第一步重新启动。
  • 否则,将ring-> prod_head设置为本地prod_next,CAS操作成功,然后继续处理。

在该图中,操作在内核1上成功完成,而第一步在内核2上重新启动。

2
成功在核心2上重试CAS操作。

核心1更新了ring(obj4)的一个元素,核心2更新了另一个(obj5)的元素。

3
每个内核现在都想更新ring-> prod_tail。仅当ring-> prod_tail等于prod_head局部变量时,内核才能更新它。这仅在内核1上成立。操作已在内核1上完成。

4
内核1更新了ring-> prod_tail之后,内核2也可以对其进行更新。该操作也在内核2上完成。

5

3. 参考

DPDK Ring Library
Linux Lockless Ring Buffer Design

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值