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