1. 程式人生 > 其它 >RTOS 的學習之建立執行緒

RTOS 的學習之建立執行緒

1、定義執行緒棧

在多執行緒系統中,每個執行緒都是獨立的,互不干擾的,所以要為每個執行緒都分配獨立的棧空間,每個棧空間通常是預先定義好的全域性陣列,也可以是動態分配的一段記憶體空間,但他們都存於RAM中。

  在多執行緒系統中,有多少個執行緒就需要定義多少個執行緒棧。

1 ALIGN(RT_ALIGN_SIZE)// (2)
2  /* 定義執行緒棧 */
3 rt_uint8_t rt_flag1_thread_stack[512];// (1)
4 rt_uint8_t rt_flag2_thread_stack[512];

執行緒棧其實就是一個預先定義好的全域性變數。在RT-Thread中,凡是涉及到資料型別的地方,RT-Thread 都會將標準的C資料型別用typedef重新取一個型別名,以“rt”字首開頭。這些經過重定義的資料型別放在rtdef.h。

ALIGN是一個帶參巨集,設定變數需要多少個位元組對齊,對在它下面的變數起作用。

RT_ALIGN_SIZE 是一個在rtconfig.h中定義的巨集,預設為4,表示4個位元組對齊。

2、定義執行緒函式

執行緒是一個獨立的函式,函式主體無限迴圈且不能返回。

3、定義執行緒控制塊

在多執行緒系統中,執行緒的執行是由系統排程的。系統為了順利的排程執行緒,為每個執行緒都額外定義了一個執行緒控制塊,這個執行緒控制塊就相當於執行緒的身份證,裡面存有執行緒的所有訊息,比如執行緒的棧指標,執行緒名稱,執行緒的形參等。有了這個執行緒控制塊之後,以後系統對執行緒的全部操作都可以通過這個執行緒控制塊來實現。定義一個執行緒控制塊需要一個新的資料型別,該資料型別在rtdef.h這個標頭檔案中宣告,使用它可以為每個執行緒都定義一個執行緒控制塊實體。

struct rt_thread// (1)
{ 
     void *sp; /* 執行緒棧指標 */
     void *entry; /* 執行緒入口地址 */
     void *parameter; /* 執行緒形參 */
     void *stack_addr; /* 執行緒起始地址 */
     rt_uint32_t stack_size; /* 執行緒棧大小,單位為位元組 */
     rt_list_t tlist; /* 執行緒連結串列節點 */
 };
 typedef struct rt_thread *rt_thread_t;

在RT-Thread中,都會給新宣告的資料結構重新定義一個指標。往後如果要定義執行緒控制塊變數就使用struct rt_thread xxx 的形式,定義執行緒控制塊指標就使用rt_thread_t xxx 的形式。

/* 定義執行緒控制塊 */
struct rt_thread rt_flag1_thread;
struct rt_thread rt_flag2_thread;

4、實現執行緒建立函式

執行緒的棧,執行緒的函式實體,執行緒的控制塊,最終需要聯絡起來才能由系統進行統一排程。那麼這個聯絡的工作就由執行緒初始化函式rt_thread_init()來實現,該函式在thread.c中定義,在rtthread.h中宣告,所有跟執行緒相關的函式都在這個檔案定義。rt_thread_init()函式的實現:

rt_err_t rt_thread_init(struct rt_thread *thread,           // (1) 
                                 void (*entry)(void *parameter), // (2)
                                 void *parameter,                       // (3)
                                 void *stack_start,                     // (4)
                                 rt_uint32_t stack_size)              // (5)
 { 
    rt_list_init(&(thread->tlist));                                  // (6)
    thread->entry = (void *)entry;                              // (7)
    thread->parameter = parameter;                          //  (8)
    thread->stack_addr = stack_start;                        // (9)
    thread->stack_size = stack_size;                         // (10)

 /* 初始化執行緒棧,並返回執行緒棧指標 */                         // (11)
     thread->sp = (void *)rt_hw_stack_init( thread->entry,
                         thread->parameter,
                         (void *)((char *)thread->stack_addr +thread->stack_size - 4) );

     return RT_EOK;                                                // (12)
 }                    

遵循RT-Thread 中的函式命名規則,以小寫的rt開頭,表示這是一個外部函式,可以由使用者呼叫,以_rt 開頭的函式表示內部函式,只能由RT-Thread內部使用。緊接著是檔名,表示該函式放在那個檔案,最後是函式功能名稱。

(1)thread 是執行緒控制塊指標。

(2)entry 是執行緒函式名,表示執行緒的入口。

(3)parameter 是執行緒形參,用於傳遞執行緒引數。

(4)stack_start 用於指向棧的起始地址。

(5)stack_size 表示執行緒棧的大小,單位為位元組。