小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

RT-Thread2

 Jessica小館子 2014-03-17
[
你可以任意轉(zhuǎn)載本文,但轉(zhuǎn)載請保留本段聲明。
作者將盡量追求內(nèi)容的正確,但不對正確性作出保證。
未經(jīng)作者許可,不得用于商業(yè)目的。
作者:byeyear/告別年代
Email: byeyear@hotmail.com
]

首先糾正一下上一篇中的一個錯誤。對象類型(是否為系統(tǒng)對象)記錄在rt_thread結(jié)構(gòu)的type成員里,而不是flag成員里。

何謂線程

所謂“線程”,其實就是一段子程序。只是它和普通子程序的區(qū)別在于,這段子程序可能隨時被操作系統(tǒng)所中斷,并在將來的某個時間點恢復(fù)運行。為了達到這個目的,我們需要一些基礎(chǔ)設(shè)施。例如,我們需要在中斷一個線程的運行時保存當(dāng)前的PC寄存器,這樣我們才能在恢復(fù)其運行時知道從何處重新開始;我們還需要保存當(dāng)前CPU的所有其他寄存器,因為這些寄存器可能被其他線程所破壞。

線程的創(chuàng)建

有兩個函數(shù)可用于創(chuàng)建線程:rt_thread_initrt_thread_create。這兩者的區(qū)別在于,前者需要調(diào)用者自己分配線程對象和線程棧,而后者由操作系統(tǒng)分配線程對象和棧空間。換句話說,rt_thread_creatert_thread_init多了資源分配的操作。這里,我們先看rt_thread_init。

rt_thread_init首先對調(diào)用者提供的線程對象進行初始化:

rt_err_t rt_thread_init(...)

{

  rt_object_init((rt_object_t)thread,

                   RT_Object_Class_Thread, name);

  ...

}

rt_object_init的代碼做以下幾個工作:

1. 將對象類型設(shè)置為RT_Object_Class_Static

    這個標記表明該對象是由用戶分配而不是操作系統(tǒng)分配的。

    一般來說,硬件資源的分配遵循“誰申請,誰釋放”的原則。因此,當(dāng)線程退出運行時,操作系統(tǒng)需要判斷線程對象和線程棧占用的存儲空間是用戶分配的還是系統(tǒng)分配的。如果這些存儲空間是用戶分配的,那么操作系統(tǒng)不會對這些內(nèi)存做什么事情;但如果這些存儲空間是系統(tǒng)分配的(當(dāng)你用rt_thread_create創(chuàng)建線程時),操作系統(tǒng)就要負責(zé)釋放線程對象和線程棧所占用的存儲空間。判斷的依據(jù)就是線程對象類型。

2. 將name參數(shù)(對象名稱)復(fù)制到線程對象中

3. 將該線程對象加入線程對象鏈表,方便后面的管理。

線程對象初始化完畢后,就調(diào)用_rt_thread_init進行實際的初始化工作:

1. 首先初始化該線程的tlist成員。

    我們前面說過,tlist成員是用來將該線程掛入某個狀態(tài)隊列的。但是該線程目前還沒有初始化完成,所以目前不將其掛入任何一個隊列,僅將其prevnext字段指向自身。

2. 將entryparameter、stack_start、stack_size四個參數(shù)保存到線程對象中。

entryparameter是線程入口地址和線程參數(shù);stack_start是線程棧起始地址。在后面將線程投入運行時,這些參數(shù)都是必須的。

stack_size并不是一個線程運行所必須的參數(shù);但該變量可以幫助我們檢查線程在運行過程中是否發(fā)生了堆棧溢出。RTT將線程??臻g全部初始化為'#'。這樣,在線程運行過程中,通過檢查堆棧內(nèi)容,就可以判斷該線程實際使用的最大堆??臻g,以及線程堆??臻g是否溢出。

3. 初始化線程棧

  rt_hw_stack_init(...)

  這個函數(shù)的作用是將線程棧模擬成這個線程剛剛被切換出去的樣子。當(dāng)調(diào)度器將該線程投入運行時,它不會知道這個線程到底是真的曾經(jīng)被切換出去,還是被模擬成這個樣子。這是一個體系結(jié)構(gòu)相關(guān)的函數(shù),比較關(guān)鍵的是這一句(以arm7為例):

   *(--stk) = (unsigned long)texit; /* lr */

   texitRTT提供的系統(tǒng)函數(shù)。我們結(jié)合一個最簡單的線程作為例子來說明這一句的作用:

    void SampleThread(void *param)

    {

    }

    這個線程什么也不做,投入運行后直接退出。函數(shù)返回時將執(zhí)行bx lr指令,即將lr寄存器的內(nèi)容從堆棧中彈入pc。而lr的值就是上面那條語句中的texit入口地址。因此,該線程退出后將執(zhí)行texit()函數(shù)。texit()會做一些必要的清理工作,然后進行一次調(diào)度(因為當(dāng)前線程已經(jīng)退出運行了)。我們后面還要回到texit()函數(shù)中去。

    從這里我們看到,RTT不像uc/OS那樣要求線程一定要有一個while(1)循環(huán)。對于RTT來說,當(dāng)一個線程不再需要時,可以像函數(shù)返回一樣使用return語句令其退出運行。(插一句話,RTT關(guān)于texit的設(shè)計是激發(fā)我當(dāng)初學(xué)習(xí)RTT的主要原因之一。)

4. 將優(yōu)先級、初始tick都保存到線程對象。這里我們看到,RTTinit_tickremaining_tick都設(shè)置為相同的值。

5. 初始化thread_timer成員。thread_timer的作用我們前面已經(jīng)說過了,rt_timer_init函數(shù)我們留到定時器相關(guān)內(nèi)容中分析。


    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多