衡阳派盒市场营销有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

TencentOS-tiny中環形隊列的實現

strongerHuang ? 來源:Mculover666 ? 作者:Mculover666 ? 2021-10-08 16:30 ? 次閱讀

1. 什么是隊列隊列(queue)是一種只能在一端插入元素、在另一端刪除元素的數據結構,遵循「先入先出」(FIFO)的規則。

隊列中有兩個基本概念:

隊頭指針(可變):永遠指向此隊列的第一個數據元素;

隊尾指針(可變):永遠指向此隊列的最后一個數據元素;

隊列中的數據存儲方式有兩種:

① 基于靜態連續內存(數組)存儲,如圖:② 基于動態內存(鏈表節點)存儲,如圖:

?

后續都使用基于靜態內存存儲的隊列講解。

?隊列提供兩個統一的操作:

「入隊(enqueue)」

入隊將一個元素添加到隊尾,并將隊尾指針+1后移,如圖:

「出隊(dequeue)」

出隊將從隊頭中取出一個元素,并將隊頭指針+1后移,如圖:

2. 環形隊列2.1. 環形隊列的特點

普通隊列的入隊操作將隊尾指針后移+1,出隊操作將隊頭指針后移+1,操作幾次之后會發現隊頭指針和隊尾指針都跑到緩沖區的尾部去了:這就導致了前面的內存空間全被浪費,如果要重新恢復使用,則需要進行元素和指針的移動:顯然這種隊列使用方式太不方便了,所以就誕生了環形隊列:「不用搬移元素和指針,一直可以重復利用這段內存空間」。

2.2. 環形隊列的實現

TencentOS-tiny中環形隊列的實現在tos_ring_queue.h和tos_ring_queue.c中。

typedef struct k_ring_queue_st {

knl_obj_t knl_obj;

uint16_t head; //隊頭指針

uint16_t tail; //隊尾指針

size_t total; //記錄隊列中元素的個數

uint8_t *pool; //隊列底層的存儲結構(一個數組)

size_t item_size; //隊列中每個元素的大小,單位:字節

size_t item_cnt; //隊列中可以容納的元素數量

} k_ring_q_t;

環形隊列初始化,將隊頭指針和隊尾置0:

__API__ k_err_t tos_ring_q_create(k_ring_q_t *ring_q, void *pool, size_t item_cnt, size_t item_size)

{

//省略了參數合法性檢查代碼

ring_q-》head = 0u;

ring_q-》tail = 0u;

ring_q-》total = 0;

ring_q-》pool = (uint8_t *)pool;

ring_q-》item_size = item_size;

ring_q-》item_cnt = item_cnt;

return K_ERR_NONE;

}

判斷環形隊列是否為滿或者為空:

__API__ int tos_ring_q_is_empty(k_ring_q_t *ring_q)

{

TOS_CPU_CPSR_ALLOC();

int is_empty = K_FALSE;

//省略了參數合法性檢查代碼

TOS_CPU_INT_DISABLE();

is_empty = (ring_q-》total == 0 ? K_TRUE : K_FALSE);

TOS_CPU_INT_ENABLE();

return is_empty;

}

__API__ int tos_ring_q_is_full(k_ring_q_t *ring_q)

{

TOS_CPU_CPSR_ALLOC();

int is_full = K_FALSE;

//省略了參數合法性檢查代碼

TOS_CPU_INT_DISABLE();

is_full = (ring_q-》total == ring_q-》item_cnt ? K_TRUE : K_FALSE);

TOS_CPU_INT_ENABLE();

return is_full;

}

環形隊列入隊操作的API如下:

__API__ k_err_t tos_ring_q_enqueue(k_ring_q_t *ring_q, void *item, size_t item_size);

在此API中,入隊操作的實現如下:

__STATIC_INLINE__ void ring_q_item_increase(k_ring_q_t *ring_q)

{

ring_q-》tail = RING_NEXT(ring_q, ring_q-》tail);

++ring_q-》total;

}

環形隊列出隊操作的API如下:

__API__ k_err_t tos_ring_q_dequeue(k_ring_q_t *ring_q, void *item, size_t *item_size);

在此API中,出隊操作的實現如下:

__STATIC_INLINE__ void ring_q_item_decrease(k_ring_q_t *ring_q)

{

ring_q-》head = RING_NEXT(ring_q, ring_q-》head);

--ring_q-》total;

}

在入隊和出隊操作的時候都使用了 RING_NEXT 宏,用來獲取在環形隊列中的下一個位置:

#define RING_NEXT(ring_q, index) ((index + 1) % ring_q-》item_cnt)

2.3. 環形隊列使用Demo

編寫如下的測試代碼:

#include 《tos_k.h》typedef struct item_st {

int a;

int b;

int c;

} item_t;

#define RING_QUEUE_ITEM_MAX 5uint8_t ring_q_buffer[RING_QUEUE_ITEM_MAX * sizeof(item_t)];

k_ring_q_t ring_q;

void entry_task_demo(void *arg)

{

k_err_t err;

int i;

item_t item;

size_t item_size;

//創建環形隊列

tos_ring_q_create(&ring_q, ring_q_buffer, RING_QUEUE_ITEM_MAX, sizeof(item_t));

//數據入隊

for(i = 0;i 《 RING_QUEUE_ITEM_MAX; i++)

{

item.a = i;

item.b = i;

item.c = i;

err = tos_ring_q_enqueue(&ring_q, &item, sizeof(item_t));

if(err == K_ERR_NONE)

{

printf(“enqueue a item: %d %d %d

”, item.a, item.b, item.c);

}

else

{

printf(“ring queue enqueue fail,err = %d

”, err);

}

}

//隊列滿之后,繼續入隊

err = tos_ring_q_enqueue(&ring_q, &item, sizeof(item_t));

if(err == K_ERR_RING_Q_FULL)

{

printf(“ring queue is full: %s

”, tos_ring_q_is_full(&ring_q) ? “TRUE” : “FALSE”);

}

else

{

printf(“ring queue enqueue fail,err = %d

”, err);

}

//數據出隊

for(i = 0; i 《 RING_QUEUE_ITEM_MAX; ++i)

{

err = tos_ring_q_dequeue(&ring_q, &item, &item_size);

if(err == K_ERR_NONE)

{

printf(“dequeue a item(%d bytes): %d %d %d

”, item_size, item.a, item.b, item.c);

}

else

{

printf(“ring queue dequeue fail,err = %d

”, err);

}

}

//沒有數據后繼續出隊

err = tos_ring_q_dequeue(&ring_q, &item, &item_size);

if(err == K_ERR_RING_Q_EMPTY)

{

printf(“ring queue is empty: %s

”, tos_ring_q_is_empty(&ring_q) ? “TRUE” : “FALSE”);

}

else

{

printf(“ring queue dequeue fail,err = %d

”, err);

}

}

運行結果如下:

3. 優先級隊列3.1. 優先級隊列的特點

優先級隊列也是一種基于隊列的數據結構,但是它「不遵循FIFO」,而是按照每個元素的優先級進行出隊:「最高優先級的先出隊」。

3.2. 優先級隊列的實現

TencentOS-tiny中環形隊列的實現在tos_prio_queue.h和tos_prio_queue.c中。

優先級隊列在數據入隊的時候,會按照入隊元素的優先級進行一次排序,「將優先級值最小(優先級最高的元素)放在隊頭」,出隊的時候只需要取第一個元素即可。

正是因為這種特性,優先級隊列的底層存儲結構不能使用數組(排序太麻煩),而是使用了二項堆的數據結構。

?

二項堆是一種二叉樹集合的數據結構,在本文中不再深入講解,有興趣的讀者可以自己搜索閱讀。

?下面只給出優先級隊列的API,「理解其規則,會用即可」。

創建優先級隊列

__API__ k_err_t tos_prio_q_create(k_prio_q_t *prio_q, void *mgr_array, void *pool, size_t item_cnt, size_t item_size);

參數描述

prio_q優先級隊列控制塊指針

mgr_array提供一塊緩沖區用于內部管理

pool隊列的緩沖區

item_cnt隊列可容納的元素數量

item_size每個元素的大小,單位字節

其中用于內部管理的緩存區大小可以使用宏定義來計算,比如有5個元素的管理緩沖區大小:

uint8_t mgr_pool[TOS_PRIO_Q_MGR_ARRAY_SIZE(5)];

元素入隊

__API__ k_err_t tos_prio_q_enqueue(k_prio_q_t *prio_q, void *item, size_t item_size, k_prio_t prio);

其中優先級的值遵循:數值越小,優先級越高。

元素出隊

__API__ k_err_t tos_prio_q_dequeue(k_prio_q_t *prio_q, void *item, size_t *item_size, k_prio_t *prio);

其中prio需要傳入一個地址,用于記錄出隊元素的優先級。

3.3. 優先級隊列使用Demo

#include 《tos_k.h》typedef struct item_st {

int a;

int b;

int c;

} item_t;

#define PRIO_QUEUE_ITEM_MAX 5uint8_t prio_q_buffer[PRIO_QUEUE_ITEM_MAX * sizeof(item_t)];

uint8_t mgr_pool[TOS_PRIO_Q_MGR_ARRAY_SIZE(PRIO_QUEUE_ITEM_MAX)];

k_prio_q_t prio_q;

void entry_task_demo(void *arg)

{

k_err_t err;

int i;

item_t item;

size_t item_size;

k_prio_t item_prio;

//創建優先級隊列

tos_prio_q_create(&prio_q, mgr_pool, prio_q_buffer, PRIO_QUEUE_ITEM_MAX, sizeof(item_t));

//數據入隊

for(i = PRIO_QUEUE_ITEM_MAX;i 》 0; i--)

{

item.a = i;

item.b = i;

item.c = i;

err = tos_prio_q_enqueue(&prio_q, &item, sizeof(item), i);

if(err == K_ERR_NONE)

{

printf(“enqueue a item: %d %d %d

”, item.a, item.b, item.c);

}

else

{

printf(“prio queue enqueue fail,err = %d

”, err);

}

}

//隊列滿之后,繼續入隊

err = tos_prio_q_enqueue(&prio_q, &item, sizeof(item_t), i);

if(err == K_ERR_PRIO_Q_FULL)

{

printf(“prio queue is full: %s

”, tos_prio_q_is_full(&prio_q) ? “TRUE” : “FALSE”);

}

else

{

printf(“prio queue enqueue fail,err = %d

”, err);

}

//數據出隊

for(i = 0; i 《 PRIO_QUEUE_ITEM_MAX; ++i)

{

err = tos_prio_q_dequeue(&prio_q, &item, &item_size, &item_prio);

if(err == K_ERR_NONE)

{

printf(“dequeue a item[piro %d]: %d %d %d

”, item_prio, item.a, item.b, item.c);

}

else

{

printf(“prio queue dequeue fail,err = %d

”, err);

}

}

//沒有數據后繼續出隊

err = tos_prio_q_dequeue(&prio_q, &item, &item_size, &item_prio);

if(err == K_ERR_PRIO_Q_EMPTY)

{

printf(“prio queue is empty: %s

”, tos_prio_q_is_empty(&prio_q) ? “TRUE” : “FALSE”);

}

else

{

printf(“prio queue dequeue fail,err = %d

”, err);

}

}

4. 總結① 普通隊列是一種只能在一端入隊,在一端出隊的數據結構,規則:FIFO。

② 環形隊列對內存空間的利用率最高,使用最多,規則:FIFO。

③ 優先級隊列不遵循FIFO,每個元素都有自己的優先級,規則:優先級最高的元素先出隊。

責任編輯:haq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 數據
    +關注

    關注

    8

    文章

    7139

    瀏覽量

    89576
  • 存儲
    +關注

    關注

    13

    文章

    4353

    瀏覽量

    86171
  • TencentOS
    +關注

    關注

    0

    文章

    8

    瀏覽量

    7329

原文標題:TencentOS-tiny中隊列、環形隊列、優先級隊列的實現及使用

文章出處:【微信號:strongerHuang,微信公眾號:strongerHuang】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    助力AIoT應用:在米爾FPGA開發板上實現Tiny YOLO V4

    Only Look Once)是一種實時物體檢測模型,它通過一次性掃描整個圖像,實現高效的對象識別。而其簡化版 Tiny YOLO V4 更適合嵌入式設備,具有較少的層數和參數。其輕量化特性更適合在資源
    發表于 12-06 17:18

    環形器的特點和應用

    環形器是一個有單向傳輸特性的三端口器件,它表明器件從1到2,從2到3 和從3到1是導通的,反過來信號從2到1,從3到2和從1到3是隔離的。環形器是有數個端的非可逆器件。
    的頭像 發表于 11-29 16:49 ?752次閱讀
    <b class='flag-5'>環形</b>器的特點和應用

    JavaWeb消息隊列使用指南

    在現代的JavaWeb應用中,消息隊列(Message Queue)是一種常見的技術,用于異步處理任務、解耦系統組件、提高系統性能和可靠性。 1. 消息隊列的基本概念 消息隊列是一種應用程序對應
    的頭像 發表于 11-25 09:27 ?193次閱讀

    分享一個嵌入式通用FIFO環形緩沖區實現

    開源項目ringbuff ,是一款通用FIFO環形緩沖區實現的開源庫,作者MaJerle,遵循 MIT 開源許可協議。
    的頭像 發表于 10-23 16:20 ?534次閱讀
    分享一個嵌入式通用FIFO<b class='flag-5'>環形</b>緩沖區<b class='flag-5'>實現</b>庫

    嵌入式環形隊列與消息隊列實現原理

    嵌入式環形隊列,也稱為環形緩沖區或循環隊列,是一種先進先出(FIFO)的數據結構,用于在固定大小的存儲區域中高效地存儲和訪問數據。其主要特點包括固定大小的數組和兩個指針(頭指針和尾指針
    的頭像 發表于 09-02 15:29 ?658次閱讀

    環形變壓器輸出是直流還是交流

    。 關于環形變壓器輸出是直流還是交流的問題,我們需要從變壓器的工作原理和環形變壓器的特點來分析。 變壓器的工作原理 變壓器是一種利用電磁感應原理實現電能轉換的設備。它由兩個或多個線圈組成,這些線圈繞在一個或多個鐵
    的頭像 發表于 08-21 09:45 ?853次閱讀

    單片機中的幾種環形緩沖區的分析和實現

    單片機中的幾種環形緩沖區的分析和實現一、簡介環形緩沖區(RingBuffer)是一種高效的使用內存的方法,它將一段固定長度的內存看成一個環形結構,用于存儲數據,能夠避免使用動態申請內存
    的頭像 發表于 08-14 08:39 ?1067次閱讀
    單片機中的幾種<b class='flag-5'>環形</b>緩沖區的分析和<b class='flag-5'>實現</b>

    玩轉RT-Thread之消息隊列的應用

    在嵌入式系統開發中,實時處理串口和ADC數據是一項重要的任務。本文將介紹如何在RT-Thread實時操作系統中,利用消息隊列來同時處理來自串口和ADC的數據。通過這種方法,我們能夠高效地管理和處理
    的頭像 發表于 07-23 08:11 ?663次閱讀
    玩轉RT-Thread之消息<b class='flag-5'>隊列</b>的應用

    基于Tiny AI技術的玻璃敲碎聲事件離線檢測方案

    該方案基于RA系列MCU產品(RA4),在R7FA4E10D2CNE硬件上運行Aizip Tiny AI玻璃敲碎聲音事件檢測算法庫,實現了實時檢測玻璃敲碎聲,并個性化定制報警邏輯的功能。
    發表于 06-20 14:25 ?375次閱讀
    基于<b class='flag-5'>Tiny</b> AI技術的玻璃敲碎聲事件離線檢測方案

    基于Tiny AI技術的嬰兒哭聲事件離線檢測方案

    基于Tiny AI技術的嬰兒哭聲事件離線檢測模型,基于Arm Cortex/Risc V微處理器開發,芯片資源占用極少,有極高的準確率和極低的誤識別率。
    的頭像 發表于 06-17 15:25 ?843次閱讀

    TCL中環備戰收購Maxeon,助力能源綠色低碳轉型

    此項總金額高達1.975億美元的交易包括TCL中環對Maxeon的控股收購以及其納入合并報表范圍的過程。完成交易后,TCL中環對Maxeon的持股比例將大幅提升,達到至少50.1%。
    的頭像 發表于 05-31 15:33 ?1110次閱讀

    Tiny11 Builder優化客戶體驗,新增關閉遙測功能

    4 月 30 日,Tiny11 項目開發商 NTDEV 推出全新 Tiny11 Builder,其中重要更新為可關閉應用程序兼容性評估器及客戶體驗改進計劃等遙感設置。
    的頭像 發表于 04-30 11:05 ?852次閱讀

    進程間通信的消息隊列介紹

    消息隊列是一種非常常見的進程間通信方式。
    的頭像 發表于 04-08 17:27 ?346次閱讀

    MCU專屬隊列功能模塊之QueueForMcu應用

    當需要從隊列頭部獲取多個數據,但又不希望數據從隊列中刪除時,可以使用 Queue_Peek_Array 函數來實現,該函數的參數與返回值與 Queue_Pop_Array 完全相同。
    發表于 03-20 11:44 ?556次閱讀
    MCU專屬<b class='flag-5'>隊列</b>功能模塊之QueueForMcu應用

    TC399 adc能添加到同一個隊列中并得到結果嗎?加入隊列是否有任何限制?

    你好,,我正在嘗試實現 ADC。 在我的項目中,我們使用 AN0...AN60 進行不同的電壓監控。 從數據表中可以發現,這些是不同的通道和組。 在一個示例程序中,它顯示將第 0 組的 3 個通道
    發表于 03-04 06:33
    百家乐官网真钱电玩| 全讯网433234| 百家乐之三姐妹赌博机| 百家乐包赢| 百家乐长龙有几个| 百家乐巴厘岛娱乐城| 网上百家乐哪里开户| 宝博百家乐娱乐城| 试玩百家乐的玩法技巧和规则 | 立博百家乐游戏| 百家乐另类投注法| 百家乐gamble| 博彩百家乐字谜总汇二丹东| 太阳百家乐代理| 大发888娱乐场下载制度 | 爱博彩论坛| 网上百家乐官网合法吗| 菲律宾百家乐官网太阳城| 百家乐官网论坛博彩啦| 娱乐城百家乐官网送白菜| 百家乐官网怎么玩| 百家乐官网分析绿色版| 百家乐官网ho168平台| 乐享百家乐官网的玩法技巧和规则| 大众百家乐官网娱乐城| 在线百家乐3d| 百家乐桌保险| 水果机技术打法| 永胜博| 百家乐官网的路图片| 博发百家乐官网的玩法技巧和规则| 百家乐网上娱乐城| 百家乐网络游戏信誉怎么样| 棋牌英雄传| 百家乐官网代理在线游戏可信吗网上哪家平台信誉好安全 | 德州扑克 视频| 宾利百家乐官网现金网| 恒丰百家乐官网的玩法技巧和规则 | 百家乐官网玩法说| 真人百家乐游戏网| 豪门国际网上娱乐|