RT-Thread創建靜態、動態線程

RT-Thread 實時操作系統核心是一個高效的硬實時核心,它具備非常優異的實時性、穩
定性、可剪裁性,當進行最小配置時,內核體積可以到 3k ROM 佔用、 1k RAM 佔用。

 RT-Thread 中的“線程”一般由三部分組成:線程代碼(函數)、 線程控制塊、 線程堆棧。

 /* 指向線程控制塊的指針*/

複製代碼
static struct rt_thread led_thread= RT_NULL;

void
led_thread_entry(void* parameter) { rt_uint8_t count=0; rt_hw_led_init(); while (1) {   if (++count>=4) count = 0;   rt_hw_led_on(ledTable[count][0]);   rt_hw_led_off(ledTable[count][1]);   rt_hw_led_off(ledTable[count][2]);   rt_hw_led_off(ledTable[count][3]);   rt_thread_delay( RT_TICK_PER_SECOND/2 );   /* sleep 0.5 second and switch to other thread */ } }
複製代碼

上面即是一個典型的線程代碼結構—無限死循環,當然還有一種線程結構是順序執行的,比如初始化線程,它執行到 return(),就會返回,當其返回後,系統會在 idle 線程中將其刪除,從而使其退出調度隊列。一般情況下用戶線程都將是一個無限循環結構。

  線程堆棧:

static rt_uint8_t led_stack512];
線程堆棧是一段連續的內存塊,當線程切換後,爲了滿足線程切換和響應中斷時保存
cpu 寄存器中的內容及任務調用其它函數時的準備,每個線程都要配有自己的堆棧.

創建一個我們自己的線程
前面說了這麼多,我們還是來自己建立一個線程,這樣的話印象更深刻。
RT-Thread 中的線程分爲靜態線程—線程堆棧由編譯器靜態分配,使用 rt_thread_init ()
函數創建和動態線程—線程堆棧由系統動態分配,使用 rt_thread_create()函數創建。
/* 靜態線程的 線程堆棧*/

複製代碼
static rt_uint8_t led1_stack[512];
/* 靜態線程的 線程控制塊 */
static struct rt_thread led1_thread;
void demo_thread_creat(void)
{
    rt_err_t result;
    /* 動態線程的 線程控制塊指針 */
    rt_thread_t led2_thread;
    rt_hw_led_init();
    /* 創建靜態線程 : 優先級 20 ,時間片 2 個系統滴答 */
    result = rt_thread_init( &led1_thread,
                      "led1",
               static_thread_entry, 
                    RT_NULL,       (rt_uint8_t
*)&led1_stack[0],
              sizeof(led1_stack),
                       20,
                       2); if (result == RT_EOK)   {     rt_thread_startup(&led1_thread);   }   /* 創建動態線程 : 堆棧大小 512 bytes ,優先級 21 ,時間片 2 個系統滴答 */   led2_thread = rt_thread_create("led2", dynamic_thread_entry,
                    RT_NULL,                       
512,
                       21,
                       2);   if (led2_thread != RT_NULL)    rt_thread_startup(led2_thread);
}
複製代碼

靜態線程 VS 動態線程
從上例可看出,靜態、動態線程在做同樣的事情時,從效果上看,是沒有任何差別的!
那麼,我們在實際中如何抉擇?使用靜態線程時,必須先定義靜態的線程控制塊,並且定義好堆棧空間,然後調用rt_thread_init() 來完成線程的初始化工作。採用這種方式,線程控制塊和堆棧佔用的內存會放在 RW/ZI 段,這段空間在編譯時就已經確定,它不是可以動態分配的,所以不能被釋放,而只能使用 rt_thread_detach() 函數將該線程控制塊從對象管理器中脫離。使用動態定義方式 rt_thread_create() 時, RT-Thread 會動態申請線程控制塊和堆棧空間。在編譯時, 編譯器是不會感知到這段空間的,只有在程序運行時, RT-Thread 纔會從系統堆中申請分配這段內存空間,當不需要使用該線程時,調用 rt_thread_delete() 函數就會將這段申請的內存空間重新釋放到內存堆中。這兩種方式各有利弊,靜態定義方式會佔用 RW/ZI 空間,但是不需要動態分配內存,運行時效率較高,實時性較好。 動態方式不會佔用額外的 RW/ZI 空間,佔用空間小,但是
運行時需要動態分配內存,效率沒有靜態方式高。 總的來說,這兩種方式就是空間和時間效率的平衡,可以根據實際環境需求選擇採用具體的分配方式。

複製代碼
static void rt_hw_led_init(void);
static void static_thread_entry(void* parameter);
static void dynamic_thread_entry(void* parameter);

/*  變量分配4字節對齊 */
ALIGN(RT_ALIGN_SIZE)

/*  靜態線程的 線程堆棧*/
static rt_uint8_t led1_stack[512];

/* 靜態線程的 線程控制塊 */
static struct rt_thread led1_thread;


void demo_thread_creat(void)
{
    rt_err_t result;
    /* 動態線程的 線程控制塊指針 */
    rt_thread_t led2_thread;

    rt_hw_led_init();

    /* 創建靜態線程 :  */
    result = rt_thread_init(&led1_thread,
                                  "led1",
                     static_thread_entry, 
                                 RT_NULL,
             (rt_uint8_t*)&led1_stack[0], 
                      sizeof(led1_stack), 
                                      20, //優先級 20 ,
                                       2);//時間片 2個系統滴答
    if (result == RT_EOK)
    {
        rt_thread_startup(&led1_thread);
    }

    /* 創建動態線程 : 堆棧大小512 bytes ,優先級 21 ,時間片 2個系統滴答 */
    led2_thread = rt_thread_create("led2",
                     dynamic_thread_entry, 
                                  RT_NULL,
                                      512, 
                                       21, 
                                       2);

    if (led2_thread != RT_NULL)
        rt_thread_startup(led2_thread);

/*上面代碼中的 20、 8 既是線程的優先級, 5 是爲線程所分配的時間片。這裏需要注意的
是, 當一個線程的優先級獨一無二的時候,它的時間片這個參數將失去作用,我們不要認爲
上面的兩個線程運行完 5 個系統 ticks 後就會主動交出 cpu 使用權,當運行完 5 個 ticks 
後如果它不需等待任何資源,也不主動讓出 cpu 使用權的話,它還會繼續運行,時間片這個
參數只在具有相同優先級的線程之間起作用,可是即便如此,這個參數也不能設爲 0,因爲
你不知道後續是否還會創建線程。*/

}
複製代碼

由於我們的線程一般都是一個無限循環,而 RT-Thread 又是一個搶佔式的內核,所以爲了使高優先級的線程不至於獨佔 CPU,可以給其他優先級較低的線程獲得CPU使用權的機會,我們往往需要在線程中的合適位置調用系統函數 rt_thread_delay(),使當前線程的運行延時一段時間並進行一次任務調度,以讓出 CPU 的使用權。

發佈了1 篇原創文章 · 獲贊 48 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章