並發無鎖隊列學習之二【單生產者單消費者】


1、前言

  

  最近工作比較忙,加班較多,每天晚上回到家10點多了。我不知道自己還能堅持多久,既然選擇了就要做到最好。寫博客的少了。總覺得少了點什么,需要繼續學習。今天繼續上個開篇寫,介紹單生產者單消費者模型的隊列。根據寫入隊列的內容是定長還是變長,分為單生產者單消費者定長隊列和單生產者單消費者變長隊列兩種。單生產者單消費者模型的隊列操作過程是不需要進行加鎖的。生產者通過寫索引控制入隊操作,消費者通過讀索引控制出隊列操作。二者相互之間對索引是獨享,不存在競爭關系。如下圖所示:

2、單生產者單消費者定長隊列

  這種隊列要求每次入隊和出隊的內容是定長的,即生產者寫入隊列和消費者讀取隊列的內容大小事相同的。linux內核中的kfifo就是這種隊列,提供了讀和寫兩個索引。單生產者單消費者隊列數據結構定義如下所示:

typedef struct { uint32_t r_index; /*讀指針*/ uint32_t w_index; /*寫指針*/ uint32_t size; /*緩沖區大小*/ char *buff[0]; /*緩沖區起始地址*/ }ring_buff_st;

為了方便計算位置,設置隊列的大小為2的次冪。這樣可以將之前的取余操作轉換為位操作,即r_index = r_index % size 與 r_index = r_index & (size -1)等價。位操作非常快,充分利用了二進制的特征。
(1)隊列初始狀態,讀寫索引相等,此時隊列為空。

  

(2)寫入隊列

寫操作即進行入隊操作,入隊有三種場景,

2.1 寫索引大於等於讀索引

2.2寫索引小於讀索引

2.3.寫索引后不夠寫入一個

(3)讀取隊列

讀隊列分為三種場景

3.1寫索引大於等於讀索引

3.2寫索引小於讀索引

3.3.讀索引后面不夠一個

3、單生產者單消費者變長隊列

  有些時候生產者每次寫入的數據長度是不確定的,導致寫入隊列的數據時變長的。這樣為了充分利用隊列,需要增加一個結束索引,保證隊列末尾至少能夠寫入一個數據。變長隊列數據結構定義如下:

typedef struct { uint32_t r_index; /*讀指針*/ uint32_t w_index; /*寫指針*/ uint32_t e_index; /*隊列結束指針*/ uint32_t size; /*緩沖區大小*/ char *buff[0]; /*緩沖區起始地址*/ }ring_buff_st;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM