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