【RTOS训练营】队列的读写、休眠和唤醒、常规应用、使用和晚课提问
一:隊列的讀寫
對于隊列,我們只要理解它就是一個環形緩沖區,然后還可以去休眠、喚醒,就可以了。
1.寫數據的時候,如果沒有空間自己就休眠
2.讀數據的時候,如果沒有數據自己就休眠
3.寫數據成功之后,如果有其他任務在等待數據,就把它喚醒
4.讀數據成功之后,如果有其他任務在等待空間,就把它喚醒
比環形緩沖區多了:休眠和喚醒的操作。
我們再來回顧一下怎么去創建一個隊列:
這里,故意把這個程度改為4,來看看會發生什么事。
我們要關注的是這個圖片里面黃色的那兩個變量;
一個是寫位置:pcWriteTo,另一個是讀位置:pcReadFrom。
怎么寫數據呢?假設初始情況和寫了一個數據后,分別如下:
1.寫到哪里去?pcWriteTo
2.寫完之后,pcWriteTo指向下一個位置
那怎么讀數據?假設初始情況和寫了一個數據后,分別如下:
1.pcReadFrom先調整為指向下一個位置
2.再從pcReadFrom讀出一個元素
讀出數據之后,數據還保存在隊列里, 但是指針位置變了,所以之前的那些數據并不會再次讀出來,也就相當于之前的數據被廢棄了。
讀和寫的時候,都是使用memcpy,那么復制多長的數據呢?
創建隊列的時候就指定有每一個元素有多長。
二:隊列的休眠和喚醒
下面我們來看看休眠和喚醒的操作。
寫隊列、讀隊列的操作是很類似的。
休眠的時間可以設置成:0、portMAX_DELAY、某個值
0的話就表示不休眠:成就成,不成就拉倒。
通過返回值來判斷是否成功:
上一次課我們講了寫隊列的操作,今天我們來講讀隊列。
其實大家英文好的話,看這個代碼,它的注釋都很完善:
他會判斷一下時間到了沒有。
時間沒到,并且隊列是空的,那顯然得不到數據,那就休息一下。
怎么休息呢?
1.當前任務,要把自己放到隊列的某個鏈表去
2.當前任務,把自己從ready list放到delay list
假設想去讀數據,但是沒有數據,則會被放到隊列的xTasksWaitingToReceive上。
為什么要把當前任務放到隊列的xTasksWaitingToReceive鏈表?
這里是登記一下,等待的數據來了可以喚醒這個任務。
這里會涉及三個鏈表:
1.我在等待數據,那別人怎么知道你在等待數據?就需要把自己放到隊列的xTasksWaitingToReceive鏈表
2.我要休眠,怎么休眠?把自己從ready list放到delay list
再強調一下,超時時間,不影響排隊的位置:
三:隊列的常規應用
隊列的常規應用:
1.寫到隊列的尾部
2.從隊列的頭部讀到數據
就是先寫到隊列的數據,會被先讀出來,FIFO,先進先出,這是常規用法。
我們還可以覆蓋地寫:
1.隊列長度是1,也就是里面只會有一個元素
2.寫了第1個數據之后,還可以繼續寫第2個數據、第3個數據
本來,如果隊列已經滿了,是無法再寫入新的數據的,但是可以用另外一個函數:
這函數就是覆蓋的寫:要注意,你能使用這個函數,前提是隊列的長度只有1。
既然是覆蓋的寫:那就是原來里面的數據會被覆蓋。
從上面圖可以看出來,一般的隊列操作時,隊列沒有滿才可以寫數據。
但是如果使用了xQueueOverwrite,即使隊列滿了也可以寫數據。
我們看到了覆蓋:寫的時候比較特殊,
還有一個操作:讀的時候比較特殊。
讀的時候,本來應該是這樣的,先移動讀位置,讀到數據:
對于xQueuePeek,他是這樣的:
這兩個特殊的寫操作、讀操作,組合起來就可以得到一個“郵箱”。
我覺得這個郵箱取名并不好,也許是因為“櫥窗”會更好。
他的適用場景是這樣:
A、B、C、D 4個學習委員,去買報紙。
只要有一個人能夠買到報紙,全班所有的同學都可以寫“實事作文”。
ABCD這些任務,就可以調用:xQueueOverwrite。
其他同學,就可以調用:xQueuePeek。
在這個場景里面, A買到了報紙,其他同學都可以看到這個報紙,B買到了報紙,其他同學都可以看到這個報紙。
我們根本不在乎是誰買到了報紙,誰買到都可以,這個報紙是共享的,誰都可以看到。
四:隊列的使用
我們來看看隊列在什么情況下使用。
這就是隊列的使用場景,左邊生產數據,右邊消費數據。
在我們的項目里,就可以使用隊列,
我們用環形緩沖區的地方,就可以改成使用隊列。
我們在使用這些函數時,要注意使用的位置。
這些函數有兩個版本:
1.在任務里面使用
2.在中斷函數里面使用(有FromISR后綴)
五:晚課學員提問
1. 問: 老師,多個隊列休眠,放入xTaskWaitingToReceive隊列里面時候,在隊列里面的排序是在哪里?
答: 在隊列里面如果有多個任務都在等待數據,誰排在最前面?
1.誰先來排隊,誰就排在前面
2.誰的優先級更高,他就可以插隊
列表項,里面有一個xItemValue,會先根據這個詞在鏈表里面找到一個位置,再把它插到鏈表里去。
總之在鏈表里面會根據優先級來排放那些任務,如果優先級相同,就會放到同優先級的任務的后面。
舉個例子:
在上面的圖里,有7個任務在等待數據。
這時候,有一個優先級為3的任務也來等待數據,它在哪里排隊?
那如果再有一個優先級為2的任務來等待數據,他插在哪里?
使用這種方法,就可以保證:
1.優先級高的任務,排前面
2.優先級相同的任務,按照函數調用時間來排
2. 問: freeRTOS 如果在同一優先級的任務,是不是有沒搶斷了?只能鏈表時間片來輪詢?
答: 沒錯,同優先級的任務,只能輪詢。
3. 問: 各種不同的輸入,輸入的數據大小不一樣,怎么應對這種情況呢?
答: 我們創建隊列的時候就指定了元素的大小,我們去讀寫隊列時,都是使用memcpy。
所以,假設數據源有A和B。
A本來只需要寫一個字節, B需要寫100個字節。
你偏要使用同一個隊列來處理A和B提供的數據,那就只能犧牲一些效率,浪費一些空間。
對于A,即使只需要寫一個字節,也需要那么memcpy 100個字節
4. 問: 老師,任務的優先級怎么配置比較合適,比如有三個task,task1,task2,task3。task1負責采集數據發送給task2處理,task2處理完數據后發給task3進行對外發送。頻率都是100HZ。
答: 他們有依賴關系,也就是說有前后關系,所以優先級不重要。
如果:task2出來的過程總,允許task1采集數據,那么,task1的優先級更高。
在實際的開發過程中:task1 > task2 > task3
task1優先級最高,確保了數據不會丟失,
task2 > task3 : task2處理完之后,task3才能處理
5. 問: xQueueReceive的最開頭,有個判斷時間到沒到,這個是怎么判斷的,從哪里算是start的時間?
答: 不是在開頭判斷時間,隊列中沒有數據才判斷時間。
6. 問:
答:
中斷函數要考慮一點:要盡快執行。
我們假設在中斷里面寫隊列:
1.寫入了數據
2.導致一個優先級非常高的任務從阻塞變為了就緒
3.會馬上調度嗎?
4.不會,我的中斷都還沒執行完呢
5.怎么做?記錄下來:
6.等中斷處理完了,才去觸發調度
為什么要這么做呢?
我們反過來假設:在中斷里面,沒處理完中斷就要去調度、切換任務。
1.如果這個中斷函數里面有兩個循環,第1個循環會去切換任務A,第2個循環要去切換任務B
2.應該把它匯聚起來,只去執行一次切換:只在最后時刻切換任務B
你切換任務A,中斷高于任務,沒有用,還不如等到中斷處理完的時候,再去挑出優先級最高的任務B,這樣只需要切換一次。
7. 問: 老師,3個任務的優先級那個,可不可以這樣思考:如果讀任務的優先級高,那么隊列中就只能寫入一個數據了,所以一般都要寫任務優先級高,這樣隊列才有可能寫滿。
答: 還是要具體分析。
1.不想讓數據丟失,寫任務優先級就要高
2.數據丟失沒關系,一旦得到數據,就要全力處理:這個時候寫任務的優先級可以調低
對于第2種情況,其實挺普遍的。
我們在屏幕上按下某個按鈕之后,他就卡死了,實際上是在進行數據的處理。
在處理數據的過程中,你再去點擊屏幕也沒有任何作用,處理完數據之后,你之前點擊屏幕那些動作也沒有任何作用。
8. 問: 中斷可以不能被任務打斷,是不是可以因為中斷沒有TCB(調度器只認識TCB),無法保存現場和恢復現場?但是中斷可以被中斷打斷,是因為中斷可以使用主堆棧保存現場和恢復現場(不同中斷服務函數之間使用的主堆棧是連續的)?老師可以這樣理解嗎?
答: 中斷可以被打斷,中斷不可以阻塞。
不是這個原因,這是由硬件決定的。
任務運行的時候,一旦發生了中斷, CPU就一定會去執行中斷
在執行中斷的過程中,有什么理由暫停中斷的處理、去執行任務呢?
9. 問: 中斷里調度會發生什么?
答:
中斷里調度,只會去設置pxCurrentTCB,并不會運行任務。
我們反過來假設:在中斷里面,沒處理完中斷就要去調度、切換任務。
如果這個中斷函數里面有3個循環,
第1個循環會去切換任務A,pxCurrentTCB = task A
第2個循環要去切換任務B, pxCurrentTCB = task B
第3個循環要去切換任務C, pxCurrentTCB = task C
前面兩個循環毫無意義,你去設置pxCurrentTCB也沒有用,中斷沒執行完都不會去執行任務。
所以,在中斷里調用xQueueSendToBackFromISR時,只會設置一個變量,表示說“需要調度”
等中斷處理完,再設置pxCurrentTCB等于最高優先級的任務。
總結
以上是生活随笔為你收集整理的【RTOS训练营】队列的读写、休眠和唤醒、常规应用、使用和晚课提问的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机相关双人相声,适合学生表演的双人相
- 下一篇: 人人皆可做的抖音108个赚钱项目:抖音美