女人被狂躁到高潮视频免费无遮挡,内射人妻骚骚骚,免费人成小说在线观看网站,九九影院午夜理论片少妇,免费av永久免费网址

當前位置:首頁 > > 嵌入式IoT

rt-thread的線程調度與管理


  • ?1.調度是什么?

  • ?2.調度怎么實現?

  • ?3.什么時候系統(tǒng)做調度?

    • ?3.1 任務主動block

    • ?3.2 被更高優(yōu)先級的任務喚醒

    • ?3.3 yield放棄cpu使用

    • ?3.4 中斷中執(zhí)行調度

  • ?4.調度做了哪些事情?

  • ?5.總結


要想使用好rtos,做出更加穩(wěn)定可靠的產品,必須非常清楚底層的調度原理。由于RTOS的可控性,所以只有了解了其核心部分的設計思路,才能用起來得心應手,游刃有余。本文主要是聽完熊大對rt-thread調度講解之后,自己做了一些反思總結,打算分享一下rt-thread線程的調度與管理相關的比較核心和重要的部分的筆記。

1.調度是什么?

調度一般就是合理的安排,協調資源,統(tǒng)一指揮去完成一件事,而在操作系統(tǒng)中,線程調度就是有多個就緒優(yōu)先級的任務,找到最高優(yōu)先級任務,交給CPU去運行。


rt-thread調度器就是起到判決線程當前的優(yōu)先級,然后去執(zhí)行當前最高優(yōu)先級的就緒的線程。

調度又可以細分為兩種??纱驍嗾{度:關鍵防止優(yōu)先級倒置 ;不可打斷調度:先來先服務,不可中斷。

2.調度怎么實現?

在創(chuàng)建任務的時候,指定了任務的優(yōu)先級,一般來說,每個任務都有自己特定的優(yōu)先級。所以內核線程對象中有不同的優(yōu)先級的任務列表。

如果最大指定為32個優(yōu)先級,那么可以用u32,每一個bit表示一個優(yōu)先級就緒的狀態(tài)。使用位圖的優(yōu)點就是速度快,而且內存占用小。

一般來說,調度去找到最高優(yōu)先級的任務時,就需要去做判斷。如何去找到最高優(yōu)先級的任務。一般來說,有兩種辦法:

  • 軟件計算
  • 硬件計算

這兩種的差別僅僅在于計算效率的問題,本質目的并無差別。

而尋找最高優(yōu)先級的事情也是有兩種實現的策略:

1.遍歷就緒的隊列,找到最小的就緒的隊列,尋找的時間不確定,時間復雜度O(n)。

2.采用空間換時間的辦法,事先做好一個bitmap

例如系統(tǒng)中最大有8個優(yōu)先級,那么bitmap如下:

const rt_uint8_t __lowest_bit_bitmap[] =
{
 /* 00 */ 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
 /* 10 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
 /* 20 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
 /* 30 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
 /* 40 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
 /* 50 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
 /* 60 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
 /* 70 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
 /* 80 */ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
 /* 90 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
 /* A0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
 /* B0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
 /* C0 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
 /* D0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
 /* E0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
 /* F0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
};

一般每一位代表一個就緒的狀態(tài),所以__rt_ffs程序的設計如下

int __rt_ffs(int value)
{ if (value == 0) return 0; if (value & 0xff) return __lowest_bit_bitmap[value & 0xff] + 1; if (value & 0xff00) return __lowest_bit_bitmap[(value & 0xff00) >> 8] + 9; if (value & 0xff0000) return __lowest_bit_bitmap[(value & 0xff0000) >> 16] + 17; return __lowest_bit_bitmap[(value & 0xff000000) >> 24] + 25;
}

如果當前系統(tǒng)的線程狀態(tài)為0b0110 0000,那么轉換成十六進制就是0x60,根據表中的狀態(tài)此時的最高優(yōu)先級是5+1=6。所以可以得出系統(tǒng)的優(yōu)先級,此時計算的復雜度為O(1)。

雖然rtt是支持同等優(yōu)先級的,但是在具體的業(yè)務邏輯的設計中,在使用RTOS常用的設計方法中,一般都是要求程序的運行邏輯是可預測的,就是在程序執(zhí)行的過程中,可以預測到程序下一步的動作。所以rtos中同等優(yōu)先級,按照時間片輪訓的這種方式設計業(yè)務邏輯的情況并不多。使用相同優(yōu)先級會增加系統(tǒng)的業(yè)務邏輯的復雜性。

3.什么時候系統(tǒng)做調度?

RTT是搶占式的系統(tǒng)調用,所以系統(tǒng)什么時候去做的調度非常的關鍵。系統(tǒng)調度分為主動調度和被動兩種。

3.1 任務主動block

當A線程在正常運行時,主動放棄CPU的使用權,比如去執(zhí)行rt_thread_delay或者去等待一個IPC的事件到來時,都會釋放CPU進行調度,此時去系統(tǒng)中尋找已經就緒的最高優(yōu)先級的線程進行調度。

這種方式應用的場景比較豐富,比如當前線程沒有獲取到資源時,需讓出CPU的使用權,或者事情做完了,主動讓出CPU的使用權,這就是系統(tǒng)做調度的時機。

A線程的優(yōu)先級要高于B線程的優(yōu)先級,所以在A放棄CPU使用權后,已經就緒的最高優(yōu)先級線程B就開始執(zhí)行了。

3.2 被更高優(yōu)先級的任務喚醒

這種方式就是當比當前運行線程的優(yōu)先級高的線程處于就緒態(tài)時,會調度到比當前線程更高的優(yōu)先級線程中去。

按照理解A線程是正在運行的線程,此時更高任務優(yōu)先級的線程C就緒處于就緒狀態(tài)了,所以系統(tǒng)的tick函數中判斷已經有比線程A更高優(yōu)先級的線程處于就緒狀態(tài),于是執(zhí)行了rt_schedule()函數執(zhí)行了系統(tǒng)調度。當前A線程運行狀態(tài)壓棧,更高優(yōu)先級的C線程的狀態(tài)出棧,開始運行C線程。

3.3 yield放棄cpu使用

首先理解一下什么是yield,解釋成讓出,放棄比較合理。該出讓只針對于同等優(yōu)先級的線程。


這種情況只適用于A線程的優(yōu)先級等于B線程的優(yōu)先級的情況。因為RTT支持同等優(yōu)先級的方式創(chuàng)建線程,相同的優(yōu)先級的切換是靠時間片輪詢來進行的。所以,當A線程正常運行的時候,如果執(zhí)行了yield函數,那么只相當于將A線程的時間片消耗完,此時同等優(yōu)先級的D線程開始運行。

由于在RTOS中,需要的是完成任務的確定性與可靠性,同等優(yōu)先級的情況比較有限,所以這一塊應用的不多。

3.4 中斷中執(zhí)行調度

以上的三種屬于主動進行調度的過程,其系統(tǒng)的執(zhí)行流程都是可以預測的,但是中斷去執(zhí)行調度卻是比較特殊。是被動調度。

這種方式是在中斷中執(zhí)行調度的,當A線程正常運行時,此時來了一個中斷,由于中斷的優(yōu)先級是高于線程的。所以,中斷處理事情,如果在中斷中執(zhí)行了調度函數,那么在中斷退出后,將直接切換到當前系統(tǒng)中更高優(yōu)先級的線程去運行。如果如果當前系統(tǒng)的最高優(yōu)先級還是A,那么中斷退出后,執(zhí)行的最高優(yōu)先級線程依然是A。若存在線程E線程優(yōu)先級高于A并且處于就緒狀態(tài),此時,中斷退出后,切換到E線程去執(zhí)行。

4.調度做了哪些事情?

系統(tǒng)進行調度的時候做了哪些事情?

第一步:查找當前系統(tǒng)中當前以及就緒的最高優(yōu)先級的線程,若有高于當前運行系統(tǒng)運行的線程棧則執(zhí)行線程切換

第二步:關閉中斷,將系統(tǒng)當前運行的寄存器壓入??臻g

第三步:   找到需要運行的線程的PC指針,并找到棧起始處彈出棧中的寄存器狀態(tài)

第四部:打開中斷,執(zhí)行異常ret,讓系統(tǒng)恢復執(zhí)行

此時,就切換到已經就緒的更高優(yōu)先級的線程去運行了。

5.總結

rt-thread線程的調度原理和過程上述文章已經寫的比較詳細了,主要需要注意的是調度器的原理以及調度的時機的問題。往往在利用rt-thread做具體的項目的時候,需要非常清楚的理解調度過程,通過閱讀代碼,就能預測程序下一步的執(zhí)行動作。真正的做到手中有糧,心中不慌。


本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯系該專欄作者,如若文章內容侵犯您的權益,請及時聯系本站刪除。
關閉