隊(duì)列是為了任務(wù)與任務(wù)、任務(wù)與中斷之間的通信而準(zhǔn)備的,可以在任務(wù)與任務(wù)、任務(wù)與中斷之間傳遞消息,隊(duì)列中可以存儲(chǔ)有限的、大小固定的數(shù)據(jù)項(xiàng)目。任務(wù)與任務(wù)、任務(wù)與中斷之間要交流的數(shù)據(jù)保存在隊(duì)列中,叫做隊(duì)列項(xiàng)目。隊(duì)列所能保存的最大數(shù)據(jù)項(xiàng)目數(shù)量叫做隊(duì)列的長度,創(chuàng)建隊(duì)列的時(shí)候會(huì)指定數(shù)據(jù)項(xiàng)目的大小和隊(duì)列的長度。
通常隊(duì)列采用先進(jìn)先出(FIFO)的存儲(chǔ)緩沖機(jī)制,也就是往隊(duì)列發(fā)送數(shù)據(jù)的時(shí)候(也叫入隊(duì))永遠(yuǎn)都是發(fā)送到隊(duì)列的尾部,而從隊(duì)列提取數(shù)據(jù)的時(shí)候(也叫出隊(duì))是從隊(duì)列的頭部提取的。但是也可以使用
LIFO 的存儲(chǔ)緩沖,也就是后進(jìn)先出,FreeRTOS 中的隊(duì)列也提供了 LIFO 的存儲(chǔ)緩沖機(jī)制。
數(shù)據(jù)發(fā)送到隊(duì)列中會(huì)導(dǎo)致數(shù)據(jù)拷貝,也就是將要發(fā)送的數(shù)據(jù)拷貝到隊(duì)列中,這就意味著在隊(duì)列中存儲(chǔ)的是數(shù)據(jù)的原始值,而不是原數(shù)據(jù)的引用(即只傳遞數(shù)據(jù)的指針),這個(gè)也叫做值傳遞。UCOS
的消息隊(duì)列采用的是引用傳遞,傳遞的是消息指針。采用引用傳遞的話消息內(nèi)容就必須一直保持可見性,也就是消息內(nèi)容必須有效,那么局部變量這種可能會(huì)隨時(shí)被刪掉的東西就不能用來傳遞消息,但是采用引用傳遞會(huì)節(jié)省時(shí)間?。∫?yàn)椴挥眠M(jìn)行數(shù)據(jù)拷貝。
采用值傳遞的話雖然會(huì)導(dǎo)致數(shù)據(jù)拷貝,會(huì)浪費(fèi)一點(diǎn)時(shí)間,但是一旦將消息發(fā)送到隊(duì)列中原始的數(shù)據(jù)緩沖區(qū)就可以刪除掉或者覆寫,這樣的話這些緩沖區(qū)就可以被重復(fù)的使用。FreeRTOS中使用隊(duì)列傳遞消息的話雖然使用的是數(shù)據(jù)拷貝,但是也可以使用引用來傳遞消息啊,我直接往隊(duì)列中發(fā)送指向這個(gè)消息的地址指針不就可以了!這樣當(dāng)我要發(fā)送的消息數(shù)據(jù)太大的時(shí)候就可以直接發(fā)送消息緩沖區(qū)的地址指針,比如在網(wǎng)絡(luò)應(yīng)用環(huán)境中,網(wǎng)絡(luò)的數(shù)據(jù)量往往都很大的,采用數(shù)據(jù)拷貝的話就不現(xiàn)實(shí)。
1、多任務(wù)訪問
隊(duì)列不是屬于某個(gè)特別指定的任務(wù)的,任何任務(wù)都可以向隊(duì)列中發(fā)送消息,或者從隊(duì)列中提取消息。
2、出隊(duì)阻塞
當(dāng)任務(wù)嘗試從一個(gè)隊(duì)列中讀取消息的時(shí)候可以指定一個(gè)阻塞時(shí)間,這個(gè)阻塞時(shí)間就是當(dāng)任務(wù)從隊(duì)列中讀取消息無效的時(shí)候任務(wù)阻塞的時(shí)間。出隊(duì)就是就從隊(duì)列中讀取消息,出隊(duì)阻塞是針對從隊(duì)列中讀取消息的任務(wù)而言的。
比如任務(wù) A 用于處理串口接收到的數(shù)據(jù),串口接收到數(shù)據(jù)以后就會(huì)放到隊(duì)列 Q 中,任務(wù) A 從隊(duì)列 Q 中讀取數(shù)據(jù)。但是如果此時(shí)隊(duì)列 Q
是空的,說明還沒有數(shù)據(jù),任務(wù) A 這時(shí)候來讀取的話肯定是獲取不到任何東西,那該怎么辦呢?任務(wù) A
現(xiàn)在有三種選擇,一:二話不說扭頭就走,二:要不我在等等吧,等一會(huì)看看,說不定一會(huì)就有數(shù)據(jù)了,三:死等,死也要等到你有數(shù)據(jù)!選哪一個(gè)就是由這個(gè)阻塞時(shí)間決定的,這個(gè)阻塞時(shí)間單位是時(shí)鐘節(jié)拍數(shù)。阻塞時(shí)間為
0 的話就是不阻塞,沒有數(shù)據(jù)的話就馬上返回任務(wù)繼續(xù)執(zhí)行接下來的代碼,對應(yīng)第一種選擇。如果阻塞時(shí)間為 0~
portMAX_DELAY,當(dāng)任務(wù)沒有從隊(duì)列中獲取到消息的話就進(jìn)入阻塞態(tài),阻塞時(shí)間指定了任務(wù)進(jìn)入阻塞態(tài)的時(shí)間,當(dāng)阻塞時(shí)間到了以后還沒有接收到數(shù)據(jù)的話就退出阻塞態(tài),返回任務(wù)接著運(yùn)行下面的代碼,如果在阻塞時(shí)間內(nèi)接收到了數(shù)據(jù)就立即返回,執(zhí)行任務(wù)中下面的代碼,這種情況對應(yīng)第二種選擇。當(dāng)阻塞時(shí)間設(shè)置為portMAX_DELAY
的話,任務(wù)就會(huì)一直進(jìn)入阻塞態(tài)等待,直到接收到數(shù)據(jù)為止!這個(gè)就是第三種選擇。
3、入隊(duì)阻塞
入隊(duì)說的是向隊(duì)列中發(fā)送消息,將消息加入到隊(duì)列中。和出隊(duì)阻塞一樣,當(dāng)一個(gè)任務(wù)向隊(duì)列發(fā)送消息的話也可以設(shè)置阻塞時(shí)間。比如任務(wù) B 向消息隊(duì)列 Q
發(fā)送消息,但是此時(shí)隊(duì)列 Q 是滿的,那肯定是發(fā)送失敗的。此時(shí)任務(wù) B 就會(huì)遇到和上面任務(wù) A 一樣的問題,這兩種情況的處理過程是類似的,只不過一個(gè)是向隊(duì)列 Q
發(fā)送消息,一個(gè)是從隊(duì)列 Q 讀取消息而已。
4、隊(duì)列操作過程圖示
-
嵌入式
+關(guān)注
關(guān)注
5059文章
18974瀏覽量
302065 -
數(shù)據(jù)
+關(guān)注
關(guān)注
8文章
6817瀏覽量
88743 -
FreeRTOS
+關(guān)注
關(guān)注
12文章
483瀏覽量
61918
發(fā)布評論請先 登錄
相關(guān)推薦
評論