LiteOS 消息队列
參考:【野火】物聯(lián)網(wǎng)操作系統(tǒng) LiteOS 開發(fā)實戰(zhàn)指南
3 LiteOS消息隊列
3.1 消息隊列簡介
3.2 LiteOS消息隊列的特點
3.3 LiteOs消息隊列的運作機制
LiteOs消息隊列運作圖
消息隊列讀寫消息圖
3.4 LiteOs消息隊列的傳輸機制
消息隊列是一種FIFO線性表,也支持LIFO
消息數(shù)據(jù)傳輸支持值傳遞(拷貝)和引用傳遞
兩種傳遞方式比較
| 拷貝 | 數(shù)據(jù)量小的場合 | 數(shù)據(jù)重要性高 |
| 引用方式 | 數(shù)據(jù)量大的場合 | 重要性一般場合 |
3.5 消息隊列的阻塞機制
- 顧名思義,就是指讀/寫消息隊列時,能夠完整的不受其他任務(wù)干擾的完成讀/寫,即阻塞機制
3.5.1 出隊阻塞
- 讀操作,若消息隊列中沒有消息,會有三種選擇
- 該任務(wù)繼續(xù)干別的事情,不會進(jìn)入阻塞狀態(tài)
- 該任務(wù)等待消息隊列的消息,等待時間由用戶定制,等待過程即為阻塞狀態(tài),消息隊列有了對應(yīng)的消息后,該任務(wù)轉(zhuǎn)為就緒狀態(tài),然后根據(jù)該任務(wù)的優(yōu)先級讀取隊列消息,若超時,則該任務(wù)放棄等待,去干別的事情
- 該任務(wù)死等,等不到消息就不干別的事情,該任務(wù)一直進(jìn)入阻塞狀態(tài),直到完成讀取隊列的消息
3.5.2 入隊阻塞
- 寫操作,若消息隊列已經(jīng)滿了,會進(jìn)行如下處理
- 發(fā)送消息操作的時候,當(dāng)且僅當(dāng)隊列被允許入隊時,發(fā)送者才能成功發(fā)送消息
- 隊列中無可用消息空間時,系統(tǒng)會根據(jù)用戶指定的阻塞超時時間將任務(wù)阻塞,在指定的超時時間內(nèi)如果還不能完成入隊操作,發(fā)送消息的任務(wù)或者中斷服務(wù)程序會收到一個錯誤代碼LOS_ERRNO_QUEUE_ISFULL ,然后解除阻塞狀態(tài)
- 只有在任務(wù)中發(fā)送消息才允許進(jìn)行阻塞狀態(tài),在中斷中發(fā)送消息不允許帶有阻塞機制的,否則返回錯誤代碼LOS_ERRNO_QUEUE_READ_IN_INTERRUPT
- 如果有多個任務(wù)阻塞在一個消息隊列中,那么這些阻塞的任務(wù)將按照任務(wù)優(yōu)先級進(jìn)行排序,優(yōu)先級高的任務(wù)將優(yōu)先獲得隊列的訪問權(quán)
3.6 常用消息隊列的函數(shù)介紹
3.6.1 使用隊列模塊的典型流程
3.6.2 創(chuàng)建消息隊列LOS_QueueCreate()
創(chuàng)建消息隊列的內(nèi)存空間:
內(nèi)存空間=消息隊列控制塊大小+(單個消息空間大小+4字節(jié))?消息隊列長度內(nèi)存空間=消息隊列控制塊大小+(單個消息空間大小+4字節(jié))*消息隊列長度 內(nèi)存空間=消息隊列控制塊大小+(單個消息空間大小+4字節(jié))?消息隊列長度
當(dāng)消息隊列被創(chuàng)建時,系統(tǒng)會為控制塊分配對應(yīng)的內(nèi)存空間,用于保存消息隊列的(消息存儲位置,頭指針,尾指針,消息大小,以及隊列長度等)
先定義隊列ID,再調(diào)用LOS_QueueCreate() 函數(shù)創(chuàng)建,才能成功創(chuàng)建消息隊列
3.6.2 消息隊列刪除函數(shù)LOS_QueueDelete()
隊列刪除函數(shù)是直接根據(jù)隊列ID直接刪除的
UINT32 LOS_QueueDelete(UINT32 uwQueueID)隊列在使用或者阻塞中是不能被刪除的
3.6.3 消息隊列寫數(shù)據(jù)函數(shù)
任務(wù)或者中斷程序都可以給消息隊列寫入消息
當(dāng)寫入消息時,
- 如果隊列未滿,LiteOS會將消息拷貝到消息隊列的尾部,
- 若滿,會根據(jù)用戶指定的阻塞超時時間進(jìn)行阻塞,在這段時間中,如果隊列還是滿的,該任務(wù)將保持阻塞狀態(tài)以等待有空閑的消息空間,如果其他任務(wù)從其等待的隊列中讀取了數(shù)據(jù),則消息隊列空出空間,該等待的任務(wù)自動由阻塞狀態(tài)轉(zhuǎn)為就緒態(tài),并寫入消息
- 當(dāng)任務(wù)等待的時間超過指定的阻塞時間,即使隊列中還是滿的,任務(wù)也會自動從阻塞狀態(tài)變?yōu)榫途w態(tài),此時發(fā)送消息的任務(wù)/中斷程序會收到一個錯誤碼:LOS_ERRNO_QUEUE_ISFULL
不帶拷貝寫入函數(shù)LOS_QueueWrite():
UINT32 LOS_QueueWrite(UINT32 uwQueueID, // 隊列IDVOID *pBufferAddr, // 存儲寫入的數(shù)據(jù)的起始地址UINT32 uwBufferSize, // 存入緩存區(qū)的大小UINT32 uwTimeOut); // 等待時間(0~LOS_WAIT_FOREVER)寫入隊列需要注意幾點:
- 在使用寫入隊列的操作前應(yīng)先創(chuàng)建要寫入的隊列
- 在中斷上下文環(huán)境中, 必須使用非阻塞模式寫入,也就是等待時間為 0 個 tick
- 在初始化 LiteOS 之前無法調(diào)用此 API
- 將寫入由 uwBufferSize 指定大小的數(shù)據(jù),其數(shù)據(jù)存儲在 BufferAddr 指定的地址 ,那么該數(shù)據(jù)地址必須有效,否則會發(fā)生錯誤
- 寫入隊列節(jié)點中的是數(shù)據(jù)的地址
帶拷貝寫入LOS_ QueueWriteCopy()
UINT32 LOS_QueueWriteCopy(UINT32 uwQueueID, // 隊列IDVOID *pBufferAddr, // 存儲寫入的數(shù)據(jù)的起始地址UINT32 uwBufferSize, // 存入緩存區(qū)的大小UINT32 uwTimeOut); // 等待時間(0~LOS_WAIT_FOREVER)3.6.4 消息隊列讀數(shù)據(jù)函數(shù)
LOS_ QueueRead()(不帶拷貝方式讀出)
UINT32 LOS_QueueRead(UINT32 uwQueueID, // 隊列IDVOID *pBufferAddr, // 存儲寫入的數(shù)據(jù)的起始地址UINT32 uwBufferSize, // 存入緩存區(qū)的大小UINT32 uwTimeOut); // 等待時間(0~LOS_WAIT_FOREVER)注意點:
- 在使用讀取隊列的操作前應(yīng)先創(chuàng)建要寫入的隊列
- 隊列讀取采用的是先進(jìn)先出(FIFO)模式, 首先讀取首先存儲在隊列中的數(shù)據(jù)
- 必須要我們自己定義一個存儲讀取出來的數(shù)據(jù)的地方,并且把存儲數(shù)據(jù)的起始地址傳遞給 LOS_ QueueRead()函數(shù),否則,將發(fā)生地址非法的錯誤。
- 在中斷上下文環(huán)境中, 必須使用非阻塞模式寫入,也就是等待時間為 0 個 tick
- 在初始化 LiteOS 之前無法調(diào)用此 API
- pBufferAddr里存放的是隊列節(jié)點的地址
- LOS_QueueReadCopy()和 LOS_QueueWriteCopy()是一組接口,LOS_QueueRead()和 LOS_QueueWrite()是一組接口,兩組接口需要配套使用
LOS_ QueueReadCopy()(帶拷貝讀出)
UINT32 LOS_QueueReadCopy(UINT32 uwQueueID, // 隊列 IDVOID * pBufferAddr, // 存儲獲取數(shù)據(jù)的起始地址UINT32 * puwBufferSize,// 保存讀取之后數(shù)據(jù)大小的值UINT32 uwTimeOut) // 等待時間- pBufferAddr存放的是消息隊列中的數(shù)據(jù)
- 需要定義一個空間保存讀取數(shù)據(jù)的大小
總結(jié)
以上是生活随笔為你收集整理的LiteOS 消息队列的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python判断队列是否为空_pytho
- 下一篇: 百度地图线路颜色_你是铁路大亨吗?五个值