99精品伊人亚洲|最近国产中文炮友|九草在线视频支援|AV网站大全最新|美女黄片免费观看|国产精品资源视频|精彩无码视频一区|91大神在线后入|伊人终合在线播放|久草综合久久中文

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

裸機(jī)中環(huán)形隊(duì)列與RTOS中消息隊(duì)列有何區(qū)別呢?

lilihe92 ? 來源:strongerHuang ? 2024-01-26 09:38 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

正文

環(huán)形隊(duì)列”和“消息隊(duì)列”在嵌入式領(lǐng)域有應(yīng)用非常廣泛,相信有經(jīng)驗(yàn)的嵌入式軟件工程師對(duì)它們都不陌生。 但經(jīng)常看到一些初學(xué)者問一些相關(guān)的問題,今天就來分享一下關(guān)于“環(huán)形隊(duì)列”和“消息隊(duì)列”的內(nèi)容。

1

環(huán)形隊(duì)列

環(huán)形隊(duì)列是在實(shí)際編程極為有用的數(shù)據(jù)結(jié)構(gòu),它是一個(gè)首尾相連的FIFO的數(shù)據(jù)結(jié)構(gòu),采用數(shù)組的線性空間,數(shù)據(jù)組織簡(jiǎn)單,能很快知道隊(duì)列是否滿為空,能以很快速度的來存取數(shù)據(jù)。

環(huán)形隊(duì)列通常用于通信領(lǐng)域,比如UART、USBCAN、網(wǎng)絡(luò)等。

1.環(huán)形隊(duì)列實(shí)現(xiàn)原理

內(nèi)存上沒有環(huán)形的結(jié)構(gòu),因此環(huán)形隊(duì)列實(shí)上是數(shù)組的線性空間來實(shí)現(xiàn)。當(dāng)數(shù)據(jù)到了尾部它將轉(zhuǎn)回到0位置來處理。 因此環(huán)列隊(duì)列的邏輯:將數(shù)組元素q[0]與q[MAXN-1]連接,形成一個(gè)存放隊(duì)列的環(huán)形空間。

為了方便讀寫,還要用數(shù)組下標(biāo)來指明隊(duì)列的讀寫位置。head/tail.其中head指向可以讀的位置,tail指向可以寫的位置。

6fd07c00-bb88-11ee-8b88-92fbcf53809c.jpg

環(huán)形隊(duì)列的關(guān)鍵是判斷隊(duì)列為空,還是為滿。當(dāng)tail追上head時(shí),隊(duì)列為滿時(shí);當(dāng)head追上tail時(shí),隊(duì)列為空。但如何知道誰追上誰,還需要一些輔助的手段來判斷. 如何判斷環(huán)形隊(duì)列為空,為滿有兩種判斷方法:

a.附加一個(gè)標(biāo)志位tag

當(dāng)head趕上tail,隊(duì)列空,則令tag=0

當(dāng)tail趕上head,隊(duì)列滿,則令tag=1

b.限制tail趕上head,即隊(duì)尾結(jié)點(diǎn)與隊(duì)首結(jié)點(diǎn)之間至少留有一個(gè)元素的空間。

隊(duì)列空: head==tail

隊(duì)列滿: (tail+1)% MAXN ==head

2.附加標(biāo)志實(shí)現(xiàn)原理 a.采用第一個(gè)環(huán)形隊(duì)列有如下結(jié)構(gòu):

typedef struct ringq{
   int head; /* 頭部,出隊(duì)列方向*/
   int tail; /* 尾部,入隊(duì)列方向*/ 
   int tag ;
   int size ; /* 隊(duì)列總尺寸 */
   int space[RINGQ_MAX]; /* 隊(duì)列空間 */
}RINGQ;

初始化狀態(tài):

q->head = q->tail = q->tag = 0;

隊(duì)列為空:

( q->head == q->tail) && (q->tag == 0)

隊(duì)列為滿 :

 ((q->head == q->tail) && (q->tag == 1))

入隊(duì)操作,如隊(duì)列不滿,則寫入:

q->tail =  (q->tail + 1) % q->size ;

出隊(duì)操作,如果隊(duì)列不空,則從head處讀出。

下一個(gè)可讀的位置在:

q->head =  (q->head + 1) % q->size
b.完整代碼 頭文件ringq.h:
#ifndef __RINGQ_H__
#define __RINGQ_H__


#ifdef __cplusplus
extern "C" {
#endif 


#define QUEUE_MAX 20


typedef struct ringq{
   int head; /* 頭部,出隊(duì)列方向*/
   int tail; /* 尾部,入隊(duì)列方向*/ 
   int tag ; /* 為空還是為滿的標(biāo)志位*/
    int size ; /* 隊(duì)列總尺寸 */
   int space[QUEUE_MAX]; /* 隊(duì)列空間 */
}RINGQ;


/* 
  第一種設(shè)計(jì)方法:
     當(dāng)head == tail 時(shí),tag = 0 為空,等于 = 1 為滿。
*/


extern int ringq_init(RINGQ * p_queue);


extern int ringq_free(RINGQ * p_queue);




/* 加入數(shù)據(jù)到隊(duì)列 */
extern int ringq_push(RINGQ * p_queue,int data);


/* 從隊(duì)列取數(shù)據(jù) */
extern int ringq_poll(RINGQ * p_queue,int *p_data);




#define ringq_is_empty(q) ( (q->head == q->tail) && (q->tag == 0))


#define ringq_is_full(q) ( (q->head == q->tail) && (q->tag == 1))


#define print_ringq(q) printf("ring head %d,tail %d,tag %d
", q->head,q->tail,q->tag);
#ifdef __cplusplus
}
#endif 


#endif /* __RINGQ_H__ */
源代碼 ringq.c:
#include 
#include "ringq.h"


int ringq_init(RINGQ * p_queue)
{
   p_queue->size = QUEUE_MAX ;


   p_queue->head = 0;
   p_queue->tail = 0;


   p_queue->tag = 0;


   return 0;
}


int ringq_free(RINGQ * p_queue)
{
  return 0;
}




int ringq_push(RINGQ * p_queue,int data)
{
  print_ringq(p_queue);


  if(ringq_is_full(p_queue))
   {


     printf("ringq is full
");
     return -1;
   }


   p_queue->space[p_queue->tail] = data;


   p_queue->tail = (p_queue->tail + 1) % p_queue->size ;


   /* 這個(gè)時(shí)候一定隊(duì)列滿了*/
   if(p_queue->tail == p_queue->head)
    {
       p_queue->tag = 1;
    }


    return p_queue->tag ;  
}


int ringq_poll(RINGQ * p_queue,int * p_data)
{
   print_ringq(p_queue);
  if(ringq_is_empty(p_queue))
   {


      printf("ringq is empty
");
     return -1;
   }


   *p_data = p_queue->space[p_queue->head];


   p_queue->head = (p_queue->head + 1) % p_queue->size ;


    /* 這個(gè)時(shí)候一定隊(duì)列空了*/
   if(p_queue->tail == p_queue->head)
    {
       p_queue->tag = 0;
    }    
    return p_queue->tag ;
}
看到源代碼,相信大家就明白其中原理了。其實(shí)還有不采用tag,或者其他一些標(biāo)志的方法,這里就不進(jìn)一步展開講述了,感興趣的讀者可以自行研究一下。

2

消息隊(duì)列

RTOS中基本都有消息隊(duì)列這個(gè)組件,也是使用最常見的組件之一。

1.消息隊(duì)列的基本概念

消息隊(duì)列是一種常用于任務(wù)間通信的數(shù)據(jù)結(jié)構(gòu),隊(duì)列可以在任務(wù)與任務(wù)間、中斷和任務(wù)間傳遞信息,實(shí)現(xiàn)了任務(wù)接收來自其他任務(wù)或中斷的不固定長(zhǎng)度的消息。

通過消息隊(duì)列服務(wù),任務(wù)或中斷服務(wù)程序可以將一條或多條消息放入消息隊(duì)列中。同樣,一個(gè)或多個(gè)任務(wù)可以從消息隊(duì)列中獲得消息。 使用消息隊(duì)列數(shù)據(jù)結(jié)構(gòu)可以實(shí)現(xiàn)任務(wù)異步通信工作。

2.消息隊(duì)列的特性

RTOS

消息隊(duì)列,常見特性:

消息支持先進(jìn)先出方式排隊(duì),支持異步讀寫工作方式。

讀寫隊(duì)列均支持超時(shí)機(jī)制。

消息支持后進(jìn)先出方式排隊(duì),往隊(duì)首發(fā)送消息(LIFO)。

可以允許不同長(zhǎng)度(不超過隊(duì)列節(jié)點(diǎn)最大值)的任意類型消息。

一個(gè)任務(wù)能夠從任意一個(gè)消息隊(duì)列接收和發(fā)送消息。

多個(gè)任務(wù)能夠從同一個(gè)消息隊(duì)列接收和發(fā)送消息。

當(dāng)隊(duì)列使用結(jié)束后,可以通過刪除隊(duì)列函數(shù)進(jìn)行刪除。

3.消息隊(duì)列的原理

這里以 FreeRTOS 為例進(jìn)行說明。FreeRTOS 的消息隊(duì)列控制塊由多個(gè)元素組成,當(dāng)消息隊(duì)列被創(chuàng)建時(shí),系統(tǒng)會(huì)為控制塊分配對(duì)應(yīng)的內(nèi)存空間,用于保存消息隊(duì)列的一些信息如消息的存儲(chǔ)位置,頭指針 pcHead、尾指針 pcTail、消息大小 uxItemSize 以及隊(duì)列長(zhǎng)度 uxLength 等。

6fd3e9bc-bb88-11ee-8b88-92fbcf53809c.png

比如創(chuàng)建消息隊(duì)列:

xQueue = xQueueCreate(QUEUE_LEN, QUEUE_SIZE);
任務(wù)或者中斷服務(wù)程序都可以給消息隊(duì)列發(fā)送消息,當(dāng)發(fā)送消息時(shí),如果隊(duì)列未滿或者允許覆蓋入隊(duì),F(xiàn)reeRTOS 會(huì)將消息拷貝到消息隊(duì)列隊(duì)尾,否則,會(huì)根據(jù)用戶指定的阻塞超時(shí)時(shí)間進(jìn)行阻塞,在這段時(shí)間中,如果隊(duì)列一直不允許入隊(duì),該任務(wù)將保持阻塞狀態(tài)以等待隊(duì)列允許入隊(duì)。

當(dāng)其它任務(wù)從其等待的隊(duì)列中讀取入了數(shù)據(jù)(隊(duì)列未滿),該任務(wù)將自動(dòng)由阻塞態(tài)轉(zhuǎn)移為就緒態(tài)。

當(dāng)?shù)却臅r(shí)間超過了指定的阻塞時(shí)間,即使隊(duì)列中還不允許入隊(duì),任務(wù)也會(huì)自動(dòng)從阻塞態(tài)轉(zhuǎn)移為就緒態(tài),此時(shí)發(fā)送消息的任務(wù)或者中斷程序會(huì)收到一個(gè)錯(cuò)誤碼 errQUEUE_FULL。

發(fā)送緊急消息的過程與發(fā)送消息幾乎一樣,唯一的不同是,當(dāng)發(fā)送緊急消息時(shí), 發(fā)送的位置是消息隊(duì)列隊(duì)頭而非隊(duì)尾,這樣,接收者就能夠優(yōu)先接收到緊急消息,從而及時(shí)進(jìn)行消息處理。

當(dāng)某個(gè)任務(wù)試圖讀一個(gè)隊(duì)列時(shí),其可以指定一個(gè)阻塞超時(shí)時(shí)間。

在這段時(shí)間中,如果隊(duì)列為空,該任務(wù)將保持阻塞狀態(tài)以等待隊(duì)列數(shù)據(jù)有效。當(dāng)其它任務(wù)或中斷服務(wù)程序往其等待的隊(duì)列中寫入了數(shù)據(jù),該任務(wù)將自動(dòng)由阻塞態(tài)轉(zhuǎn)移為就緒態(tài)。

當(dāng)?shù)却臅r(shí)間超過了指定的阻塞時(shí)間,即使隊(duì)列中尚無有效數(shù)據(jù),任務(wù)也會(huì)自動(dòng)從阻塞態(tài)轉(zhuǎn)移為就緒態(tài)。

當(dāng)消息隊(duì)列不再被使用時(shí),應(yīng)該刪除它以釋放系統(tǒng)資源,一旦操作完成, 消息隊(duì)列將被永久性的刪除。

消息隊(duì)列的運(yùn)作過程具體見下圖:

6fe6df7c-bb88-11ee-8b88-92fbcf53809c.png

4.消息隊(duì)列的阻塞機(jī)制

出隊(duì)阻塞:當(dāng)且僅當(dāng)消息隊(duì)列有數(shù)據(jù)的時(shí)候,任務(wù)才能讀取到數(shù)據(jù),可以指定等待數(shù)據(jù)的阻塞時(shí)間。

入隊(duì)阻塞:當(dāng)且僅當(dāng)隊(duì)列允許入隊(duì)的時(shí)候,發(fā)送者才能成功發(fā)送消息;隊(duì)列中無可用消息空間時(shí),說明消息隊(duì)列已滿,此時(shí),系統(tǒng)會(huì)根據(jù)用戶指定的阻塞超時(shí)時(shí)間將任務(wù)阻塞。 假如有多個(gè)任務(wù)阻塞在一個(gè)消息隊(duì)列中,那么這些阻塞的任務(wù)將按照任務(wù)優(yōu)先級(jí)進(jìn)行排序,優(yōu)先級(jí)高的任務(wù)將優(yōu)先獲得隊(duì)列的訪問權(quán)。

3

環(huán)形隊(duì)列與消息隊(duì)列的異同

通過以上分析,你會(huì)發(fā)現(xiàn)“環(huán)形隊(duì)列”和“消息隊(duì)列”之間有很多共同點(diǎn):

1.他們都是一種數(shù)據(jù)結(jié)構(gòu),結(jié)構(gòu)中都包含頭、尾、標(biāo)志等信息;

2.它們都是分配一塊連續(xù)的內(nèi)存空間,且都可以分配多個(gè)隊(duì)列。

3.應(yīng)用場(chǎng)景類似,有大量吞吐數(shù)據(jù)的情況下,比如通信領(lǐng)域。

... 當(dāng)然,他們也有一些不同點(diǎn):

1.“環(huán)形隊(duì)列”可以獨(dú)立使用,也可以結(jié)合操作系統(tǒng)使用。而消息隊(duì)列依賴RTOS(有些RTOS的參數(shù)信息)。

2.“環(huán)形隊(duì)列”占用資源更小,更適合于資源較小的系統(tǒng)中。

3.“消息隊(duì)列”結(jié)合RTOS應(yīng)用更加靈活,比如延時(shí)、中斷傳輸數(shù)據(jù)等。

... 最后,這兩種隊(duì)列應(yīng)用都比較廣,建議抽空都研究一下。





審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 嵌入式
    +關(guān)注

    關(guān)注

    5152

    文章

    19677

    瀏覽量

    317755
  • RTOS
    +關(guān)注

    關(guān)注

    24

    文章

    851

    瀏覽量

    121203
  • FIFO存儲(chǔ)
    +關(guān)注

    關(guān)注

    0

    文章

    103

    瀏覽量

    6192
  • UART接口
    +關(guān)注

    關(guān)注

    0

    文章

    124

    瀏覽量

    15882
  • 裸機(jī)
    +關(guān)注

    關(guān)注

    0

    文章

    40

    瀏覽量

    6701

原文標(biāo)題:裸機(jī)中環(huán)形隊(duì)列與RTOS中消息隊(duì)列

文章出處:【微信號(hào):最后一個(gè)bug,微信公眾號(hào):最后一個(gè)bug】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    基于STM32的串口環(huán)形隊(duì)列IAP調(diào)試

    基于STM32的串口環(huán)形隊(duì)列IAP調(diào)試心得
    的頭像 發(fā)表于 09-18 15:33 ?2049次閱讀
    基于STM32的串口<b class='flag-5'>環(huán)形</b><b class='flag-5'>隊(duì)列</b>IAP調(diào)試

    環(huán)形隊(duì)列在串口數(shù)據(jù)接收的使用

    前言??書接上回,前文主要介紹了環(huán)形隊(duì)列的實(shí)現(xiàn)原理以及C語言實(shí)現(xiàn)及測(cè)試過程,本文將回歸到嵌入式平臺(tái)的應(yīng)用,話不多說,淦,上干貨!實(shí)驗(yàn)?zāi)康腍AL庫下串口的配置及使用環(huán)形
    發(fā)表于 12-06 06:27

    FreeRtos消息隊(duì)列API的調(diào)用該怎樣去實(shí)現(xiàn)

    消息隊(duì)列是什么?消息隊(duì)列有作用?FreeRtos消息隊(duì)列API的調(diào)用該怎樣去實(shí)現(xiàn)
    發(fā)表于 01-20 07:04

    FreeRTOS消息隊(duì)列有作用

    。多任務(wù)訪問??隊(duì)列不是屬于某個(gè)特別指定的任務(wù)的,任何任務(wù)都可以向隊(duì)列中發(fā)送消息,或者從隊(duì)列中提取消息。原始值傳遞??隊(duì)列的消息內(nèi)容不是引
    發(fā)表于 01-27 06:53

    實(shí)現(xiàn)隊(duì)列環(huán)形緩沖的方法

    串口隊(duì)列環(huán)形緩沖區(qū)隊(duì)列串口環(huán)形緩沖的好處代碼實(shí)現(xiàn)隊(duì)列??要實(shí)現(xiàn)隊(duì)列
    發(fā)表于 02-21 07:11

    環(huán)形隊(duì)列的相關(guān)資料分享

    前言??當(dāng)代碼,不再是簡(jiǎn)單的完成需求,對(duì)代碼進(jìn)行堆砌,而是開始思考如何寫出優(yōu)美代碼的時(shí)候,我們的代碼水平必然會(huì)不斷提升,今天,咱們來學(xué)習(xí)環(huán)形隊(duì)列結(jié)構(gòu)。環(huán)形隊(duì)列的基本概念??相信對(duì)數(shù)據(jù)結(jié)
    發(fā)表于 02-23 06:10

    如何去實(shí)現(xiàn)一種隊(duì)列程序的設(shè)計(jì)

    隊(duì)列的原理是什么?隊(duì)列有作用?如何去實(shí)現(xiàn)一種隊(duì)列程序的設(shè)計(jì)?
    發(fā)表于 02-25 07:50

    環(huán)形隊(duì)列的操作如何去實(shí)現(xiàn)

    環(huán)形隊(duì)列結(jié)構(gòu)的定義是什么?環(huán)形隊(duì)列的操作如何去實(shí)現(xiàn)?
    發(fā)表于 02-25 06:35

    深度解析數(shù)據(jù)結(jié)構(gòu)與算法篇之隊(duì)列環(huán)形隊(duì)列的實(shí)現(xiàn)

    01 — 隊(duì)列簡(jiǎn)介 隊(duì)列是種先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu),有個(gè)元素進(jìn)入隊(duì)列稱為入對(duì)(enqueue),刪除元素稱為出隊(duì)(dequeue),隊(duì)列有對(duì)頭(head)和對(duì)尾(tail),當(dāng)有元素進(jìn)入
    的頭像 發(fā)表于 06-18 10:07 ?2209次閱讀

    TencentOS-tiny中環(huán)形隊(duì)列的實(shí)現(xiàn)

    ; 隊(duì)尾指針(可變):永遠(yuǎn)指向此隊(duì)列的最后一個(gè)數(shù)據(jù)元素; 隊(duì)列的數(shù)據(jù)存儲(chǔ)方式有兩種: ① 基于靜態(tài)連續(xù)內(nèi)存(數(shù)組)存儲(chǔ),如圖:② 基于動(dòng)態(tài)內(nèi)存(鏈表節(jié)點(diǎn))存儲(chǔ),如圖: ? 后續(xù)都使用基于靜態(tài)內(nèi)存存儲(chǔ)的
    的頭像 發(fā)表于 10-08 16:30 ?1613次閱讀

    嵌入式環(huán)形隊(duì)列和消息隊(duì)列的實(shí)現(xiàn)

    嵌入式環(huán)形隊(duì)列和消息隊(duì)列是實(shí)現(xiàn)數(shù)據(jù)緩存和通信的常見數(shù)據(jù)結(jié)構(gòu),廣泛應(yīng)用于嵌入式系統(tǒng)的通信協(xié)議和領(lǐng)域。
    的頭像 發(fā)表于 04-14 11:52 ?2077次閱讀

    嵌入式環(huán)形隊(duì)列和消息隊(duì)列是如何去實(shí)現(xiàn)的?

    嵌入式環(huán)形隊(duì)列和消息隊(duì)列是實(shí)現(xiàn)數(shù)據(jù)緩存和通信的常見數(shù)據(jù)結(jié)構(gòu),廣泛應(yīng)用于嵌入式系統(tǒng)的通信協(xié)議和領(lǐng)域。
    發(fā)表于 05-20 14:55 ?1408次閱讀

    RTOS消息隊(duì)列的應(yīng)用

    基于RTOS的應(yīng)用,通常使用隊(duì)列機(jī)制實(shí)現(xiàn)任務(wù)間的數(shù)據(jù)交互,一個(gè)應(yīng)用程序可以有任意數(shù)量的消息隊(duì)列,每個(gè)消息隊(duì)列都有自己的用途。
    發(fā)表于 05-29 10:49 ?845次閱讀
    <b class='flag-5'>RTOS</b>消息<b class='flag-5'>隊(duì)列</b>的應(yīng)用

    單片機(jī)裸機(jī)實(shí)現(xiàn)隊(duì)列功能的方案

    單片機(jī)裸機(jī)實(shí)現(xiàn)隊(duì)列功能的方案
    的頭像 發(fā)表于 10-17 14:34 ?847次閱讀

    嵌入式環(huán)形隊(duì)列與消息隊(duì)列的實(shí)現(xiàn)原理

    嵌入式環(huán)形隊(duì)列,也稱為環(huán)形緩沖區(qū)或循環(huán)隊(duì)列,是一種先進(jìn)先出(FIFO)的數(shù)據(jù)結(jié)構(gòu),用于在固定大小的存儲(chǔ)區(qū)域中高效地存儲(chǔ)和訪問數(shù)據(jù)。其主要特點(diǎn)包括固定大小的數(shù)組和兩個(gè)指針(頭指針和尾指針
    的頭像 發(fā)表于 09-02 15:29 ?1266次閱讀