電電俠 ? 坐公交車、辦理業(yè)務等經(jīng)常需要排隊,計算機系統(tǒng)中也有類似的“隊列“概念嗎? ?
當然。隊列被用作進程之間的通信管道,通常是一對一的,如下圖所示。
科科君
任務 A 將信息存入隊列,任務B以先進先出的方式提取信息。隊列通常應足夠大,可以承載許多數(shù)據(jù),而不僅僅承載單個數(shù)據(jù)項。因此,它可以充當緩沖或暫存器,為管道提供靈活性。它的優(yōu)點是插入和提取功能可以異步進行(只要管道沒有填滿)。它在 RAM 中實現(xiàn)。進程之間傳遞的信息可能是數(shù)據(jù)本身,也可能是指向數(shù)據(jù)的指針。指針通常用于在 RAM 存儲受限時處理大量數(shù)據(jù)。實現(xiàn)隊列的技術有兩種:鏈表類型結構和循環(huán)緩沖區(qū)。
電電俠 ? 想了解下鏈表的特性。 ? 鏈表的一個非常有用的特性是它的大小不一定是固定的,而是可以根據(jù)需要擴大或縮小。 科科君
此外,可以構建非常大的隊列,僅受可用內存空間的限制。但是對于嵌入式系統(tǒng)來說,這些并不是特別的優(yōu)勢。首先,如果 RAM 有限,則根本不可能構造很大的隊列。其次,處理多個消息的大型FIFO隊列從數(shù)據(jù)輸入到數(shù)據(jù)輸出可能會有較長的傳輸延遲,就性能而言,對于許多實時應用可能太慢。因此,用于嵌入式的首選隊列(通道)結構是循環(huán)緩沖區(qū),如下圖所示。
電電俠 ? 循環(huán)緩存區(qū)應該如何設計? ?
循環(huán)緩沖區(qū)通常設計為使用固定數(shù)量的內存空間,用來保存一定數(shù)量的數(shù)據(jù),如上圖(a) 所示。
科科君
緩沖區(qū)大小是在創(chuàng)建時定義的(例如這里是10個數(shù)據(jù)單位),但在之后是固定的。使其循環(huán)的原因是數(shù)據(jù)單元0是數(shù)據(jù)單元9的后繼,尋址是使用模9計數(shù)器完成的(就像12小時時鐘使用模12計算一樣)。
電電俠 ? 在讀寫操作期間,數(shù)據(jù)如果在通道中移動,時間開銷增加怎么辦? ?
但是,一般來說這會帶來不可接受的時間開銷。
科科君
這里使用另一種方法,上圖(b)展示了如何使用指針來標識存儲數(shù)據(jù)的起始和結束位置(“讀取者”和“發(fā)送者”)。通過指針,不必在緩沖區(qū)中移動數(shù)據(jù)。插入的數(shù)據(jù)單元始終位于相同的內存位置,僅需改變指針的值,圖(c)和圖(d)所示。這些指針也可以用來定義隊列滿和隊列空的條件(當它們相等時)。
電電俠 ? 什么情況下任務會掛起? ?
在正常情況下,任務 A 和任務 B異步進行,根據(jù)需要從隊列中插入和刪除數(shù)據(jù)。任務掛起只在兩種情況下發(fā)生:隊列滿和隊列空。
科科君
小貼士:內存池和隊列之間有一個重要的區(qū)別———內存池讀取數(shù)據(jù)不會影響內容,但是從隊列讀取時會“消耗”數(shù)據(jù),即破壞性操作(實際上這只是概念性看法,讀指針只是移到了下一個位置)。
隊列使用的概要
下方代碼清單給出了隊列使用的概要。 科科君 01 ? ?
/* 基礎API */
/* 1. 創(chuàng)建隊列 */
FOS_CreateQueue(QLength, QItemSize);
/* 2. 從隊列獲取消息 */
FOS_GetFromQueue(QName, AddOfQData, QwaitingTime);
/* 3. 向隊列發(fā)送消息 */
FOS_SendToQueue(QName, AddOfQData, QwaitingTime);
02 ? ?
/* 創(chuàng)建一個全局的隊列聯(lián)結發(fā)送任務A和接收任務B */
/* 使用RTOS提供的數(shù)據(jù)類型 */
FOS_QName GlobalQA2B;
FOS_QLength QA2Blength = 1;
FOS_ItemSize QA2BItemSize = 4;
GlobalQA2B = FOS_CreateQueue (QA2Blength, QA2BItemSize);
03 ? ?
/* 發(fā)送到隊列-任務A */
/* 使用RTOS提供的數(shù)據(jù)類型 */
long DataForQueueA2B;
const FOS_QwaitTime NoWaiting = 0;
FOS_ QloadStatus QLoadState;
QLoadState = FOS_SendToQueue (GlobalQA2B, &DataForQueueA2B, 0);
04 ? ?
/* 從隊列獲取-任務B */
/* 使用RTOS提供的數(shù)據(jù)類型 */
long DataFromQueueA2B;
const FOS_QwaitTime NoWaiting = 0;
FOS_QreadStatus QreadState;
審核編輯:黃飛
評論