rt-thread操作系統是一個多線程的操作系統,線程對於rt-thread來說是一個很重要的概念,因此,必須掌握它。 1 線程控制塊的數據結構 [cpp] /** * Thread structure */ struct rt_thread { /* rt object *///這裡就是rt_object的結構,其實也可以用rt_object parent來定義,估計線程在早些時候並沒有這麼做,後來也就沒改過來 char name[RT_NAME_MAX]; /**< the name of thread */ rt_uint8_t type; /**< type of object */ rt_uint8_t flags; /**< thread's flags */ #ifdef RT_USING_MODULE//模塊ID void *module_id; /**< id of application module */ #endif //內核對象鏈表 rt_list_t list; /**< the object list */ rt_list_t tlist; /**< the thread list *///線程鏈表,一般用作就緒隊列元素節點 /* stack point and entry */ void *sp; /**< stack point *///棧指針 void *entry; /**< entry *///入口函數 void *parameter; /**< parameter *///入口函數對應的參數 void *stack_addr; /**< stack address *///棧地址 rt_uint16_t stack_size; /**< stack size *///棧大小 /* error code */ rt_err_t error; /**< error code *///錯誤代碼 rt_uint8_t stat; /**< thread stat *///線程的當前狀態 /* priority */ rt_uint8_t current_priority; /**< current priority *///當前優先級 rt_uint8_t init_priority; /**< initialized priority *///初始優先級 #if RT_THREAD_PRIORITY_MAX > 32 rt_uint8_t number; rt_uint8_t high_mask; #endif rt_uint32_t number_mask; #if defined(RT_USING_EVENT)//與IPC機制事件相關的一些參數 /* thread event */ rt_uint32_t event_set; rt_uint8_t event_info; #endif rt_ubase_t init_tick; /**< thread's initialized tick *///初始tick rt_ubase_t remaining_tick; /**< remaining tick *///剩余tick struct rt_timer thread_timer; /**< built-in thread timer *///線程定時器 void (*cleanup)(struct rt_thread *tid); /**< cleanup function when thread exit *///相當於線程的析構函數,用於銷毀線程時做些後續操作 rt_uint32_t user_data; /**< private user data beyond this thread *///析構函數的輸入參數 }; typedef struct rt_thread *rt_thread_t; 2 線程創建及初始化 2.1 初始化線程 [cpp] /*@{*/ /** * This function will initialize a thread, normally it's used to initialize a * static thread object. * * @param thread the static thread object * @param name the name of thread, which shall be unique * @param entry the entry function of thread * @param parameter the parameter of thread enter function * @param stack_start the start address of thread stack * @param stack_size the size of thread stack * @param priority the priority of thread * @param tick the time slice if there are same priority thread * * @return the operation status, RT_EOK on OK, -RT_ERROR on error */ rt_err_t rt_thread_init(struct rt_thread *thread, const char *name, void (*entry)(void *parameter), void *parameter, void *stack_start, rt_uint32_t stack_size, rt_uint8_t priority, rt_uint32_t tick) { /* thread check *///參數檢查 RT_ASSERT(thread != RT_NULL); RT_ASSERT(stack_start != RT_NULL); /* init thread object */ rt_object_init((rt_object_t)thread, RT_Object_Class_Thread, name);//初始化內核對象 return _rt_thread_init(thread, name, entry, parameter, stack_start, stack_size, priority, tick); } 其中_rt_thread_init的函數如下定義: [cpp] static rt_err_t _rt_thread_init(struct rt_thread *thread, const char *name, void (*entry)(void *parameter), void *parameter, void *stack_start, rt_uint32_t stack_size, rt_uint8_t priority, rt_uint32_t tick) { /* init thread list */ rt_list_init(&(thread->tlist));//初始化線程節點 thread->entry = (void *)entry;//入口函數 thread->parameter = parameter;//入口函數的參數 /* stack init */ thread->stack_addr = stack_start;//棧地址 thread->stack_size = (rt_uint16_t)stack_size;//棧大小 /* init thread stack */ rt_memset(thread->stack_addr, '#', thread->stack_size);//將棧內的所有字節初始化為'#'號 thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter,//初始化時設置sp的內容,rt_hw_stack_init是一個與具體MCU相關的函數,這裡就不做介紹 (void *)((char *)thread->stack_addr + thread->stack_size - 4), (void *)rt_thread_exit); /* priority init */ RT_ASSERT(priority < RT_THREAD_PRIORITY_MAX); thread->init_priority = priority;//當前優先級和初始化優先級設置 thread->current_priority = priority; /* tick init */ thread->init_tick = tick;//初始化tick和剩余tick thread->remaining_tick = tick; /* error and flags */ thread->error = RT_EOK;//錯誤的狀態,線程狀態初始化時為RT_THREAD_INIT thread->stat = RT_THREAD_INIT; /* initialize cleanup function and user data */ thread->cleanup = 0;//線程析構函數及其參數 thread->user_data = 0; /* init thread timer */ rt_timer_init(&(thread->thread_timer),//初始化線程的定時器 thread->name, rt_thread_timeout, thread, 0, RT_TIMER_FLAG_ONE_SHOT); return RT_EOK; } 其中rt_thread_timeout的函數如下定義: [cpp] /** * This function is the timeout function for thread, normally which is invoked * when thread is timeout to wait some resource. * * @param parameter the parameter of thread timeout function */ void rt_thread_timeout(void *parameter) { struct rt_thread *thread; thread = (struct rt_thread *)parameter; /* thread check */ RT_ASSERT(thread != RT_NULL); RT_ASSERT(thread->stat == RT_THREAD_SUSPEND); /* set error number */ thread->error = -RT_ETIMEOUT; /* remove from suspend list *///從掛起鏈表中移除 rt_list_remove(&(thread->tlist)); /* insert to schedule ready list */ rt_schedule_insert_thread(thread);//加入調度器 /* do schedule */ rt_schedule();//重新調度 } 2.2 創建線程 [cpp] /** * This function will create a thread object and allocate thread object memory * and stack. * * @param name the name of thread, which shall be unique * @param entry the entry function of thread * @param parameter the parameter of thread enter function * @param stack_size the size of thread stack * @param priority the priority of thread * @param tick the time slice if there are same priority thread * * @return the created thread object */ rt_thread_t rt_thread_create(const char *name, void (*entry)(void *parameter), void *parameter, rt_uint32_t stack_size, rt_uint8_t priority, rt_uint32_t tick) { struct rt_thread *thread; void *stack_start; thread = (struct rt_thread *)rt_object_allocate(RT_Object_Class_Thread,//動態分配一個內核對象 name); if (thread == RT_NULL) return RT_NULL; stack_start = (void *)rt_malloc(stack_size);//動態分配一個線程棧 if (stack_start == RT_NULL) { /* allocate stack failure */ rt_object_delete((rt_object_t)thread); return RT_NULL; } _rt_thread_init(thread,//初始化線程 name, entry, parameter, stack_start, stack_size, priority, tick); return thread; } 3 線程的脫離及刪除 3.1 脫離線程 [cpp] /** * This function will detach a thread. The thread object will be removed from * thread queue and detached/deleted from system object management. * * @param thread the thread to be deleted * * @return the operation status, RT_EOK on OK, -RT_ERROR on error */ rt_err_t rt_thread_detach(rt_thread_t thread) { rt_base_t lock; /* thread check */ RT_ASSERT(thread != RT_NULL); /* remove from schedule */ rt_schedule_remove_thread(thread);//將線程從調度器中移除 /* release thread timer */ rt_timer_detach(&(thread->thread_timer));//脫離定時器 /* change stat */ thread->stat = RT_THREAD_CLOSE;//將線程的狀態設置為RT_THREAD_CLOSE /* detach object */ rt_object_detach((rt_object_t)thread);//脫離內核對象 if (thread->cleanup != RT_NULL)//如果存在線程析構函數 { /* disable interrupt */ lock = rt_hw_interrupt_disable();//關中斷 /* insert to defunct thread list *///rt_thread_defunct鏈表在系統空閒時將被空閒線程來處理 rt_list_insert_after(&rt_thread_defunct, &(thread->tlist));//將線程加入到rt_thread_defunct鏈表中 /* enable interrupt */ rt_hw_interrupt_enable(lock);//開中斷 } return RT_EOK; } 3.2 刪除線程 [cpp] /** * This function will delete a thread. The thread object will be removed from * thread queue and detached/deleted from system object management. * * @param thread the thread to be deleted * * @return the operation status, RT_EOK on OK, -RT_ERROR on error */ rt_err_t rt_thread_delete(rt_thread_t thread) { rt_base_t lock; /* thread check */ RT_ASSERT(thread != RT_NULL); /* remove from schedule */ rt_schedule_remove_thread(thread);//從調度器中移除線程 /* release thread timer */ rt_timer_detach(&(thread->thread_timer));//脫離定時器 /* change stat */ thread->stat = RT_THREAD_CLOSE;//線程狀態設置為RT_THREAD_CLOSE /* disable interrupt */ lock = rt_hw_interrupt_disable();//關中斷 /* insert to defunct thread list */ rt_list_insert_after(&rt_thread_defunct, &(thread->tlist));//將當前線程加入到空閒時才會處理的鏈表中 /* enable interrupt */ rt_hw_interrupt_enable(lock);//開中斷 return RT_EOK; } 4 啟動線程 [cpp] /** * This function will start a thread and put it to system ready queue * * @param thread the thread to be started * * @return the operation status, RT_EOK on OK, -RT_ERROR on error */ rt_err_t rt_thread_startup(rt_thread_t thread) { /* thread check *///參數檢查 RT_ASSERT(thread != RT_NULL); RT_ASSERT(thread->stat == RT_THREAD_INIT); /* set current priority to init priority */ thread->current_priority = thread->init_priority;//啟動線程時將線程當前的優先級設置為初始優先級 /* calculate priority attribute */ #if RT_THREAD_PRIORITY_MAX > 32 thread->number = thread->current_priority >> 3; /* 5bit */ thread->number_mask = 1L << thread->number; thread->high_mask = 1L << (thread->current_priority & 0x07); /* 3bit */ #else thread->number_mask = 1L << thread->current_priority; #endif RT_DEBUG_LOG(RT_DEBUG_THREAD, ("startup a thread:%s with priority:%d\n", thread->name, thread->init_priority)); /* change thread stat */ thread->stat = RT_THREAD_SUSPEND;//將線程的狀態設置為RT_THREAD_SUSPEND /* then resume it */ rt_thread_resume(thread);//還原線程 if (rt_thread_self() != RT_NULL)//如果當前的線程不為空,則執行線程調度操作 { /* do a scheduling */ rt_schedule(); } return RT_EOK; } 其中rt_thread_self函數如下定義: [cpp] /** * This function will return self thread object * * @return the self thread object */ rt_thread_t rt_thread_self(void) { return rt_current_thread; } rt_current_thread為全局變量,保存當前正在運行的線程。 rt_thread_resume函數見後第6章內容,rt_schedule函數見線程調度源碼分析相關章節. 5 線程掛起 [cpp] /** * This function will suspend the specified thread. * * @param thread the thread to be suspended * * @return the operation status, RT_EOK on OK, -RT_ERROR on error * * @note if suspend self thread, after this function call, the * rt_schedule() must be invoked. */ rt_err_t rt_thread_suspend(rt_thread_t thread) { register rt_base_t temp; /* thread check */ RT_ASSERT(thread != RT_NULL); RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend: %s\n", thread->name)); if (thread->stat != RT_THREAD_READY)//此函數只對處於就緒狀態的線程操作 { RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend: thread disorder, %d\n", thread->stat)); return -RT_ERROR; } /* disable interrupt */ temp = rt_hw_interrupt_disable();//關中斷 /* change thread stat */ thread->stat = RT_THREAD_SUSPEND;//將線程設置為掛起狀態 rt_schedule_remove_thread(thread);//將線程從調試器中移除 /* enable interrupt */ rt_hw_interrupt_enable(temp);//開中斷 return RT_EOK; } 有關rt_schedule_remove_thread函數見後續在前調度器源碼分析的文章。 6 線程還原 [cpp] /** * This function will resume a thread and put it to system ready queue. * * @param thread the thread to be resumed * * @return the operation status, RT_EOK on OK, -RT_ERROR on error */ rt_err_t rt_thread_resume(rt_thread_t thread) { register rt_base_t temp; /* thread check */ RT_ASSERT(thread != RT_NULL); RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread resume: %s\n", thread->name)); if (thread->stat != RT_THREAD_SUSPEND)//只對處於掛起的線程進行還原操作 { RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread resume: thread disorder, %d\n", thread->stat)); return -RT_ERROR; } /* disable interrupt */ temp = rt_hw_interrupt_disable();//關中斷 /* remove from suspend list */ rt_list_remove(&(thread->tlist));//從掛起隊列中移除 /* remove thread timer */ rt_list_remove(&(thread->thread_timer.list));//因線程即將運行,所以需要移除定時器,無需再定時 /* change timer state */ thread->thread_timer.parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;//將內核對象的標志設置為定時器非激活標志 /* enable interrupt */ rt_hw_interrupt_enable(temp);//開中斷 /* insert to schedule ready list */ rt_schedule_insert_thread(thread);//將線程加入調度器 return RT_EOK; } 7 線程讓出處理機 當前線程的時間片用完或者該線程自動要求讓出處理器資源時,它不再占有處理機,調度器會選擇下一個最高優先級的線程執行。這時,放棄處理器資源的線程仍然在就緒隊列中,只不過放到就緒隊列末尾去 了. [cpp] /** * This function will let current thread yield processor, and scheduler will * choose a highest thread to run. After yield processor, the current thread * is still in READY state. * * @return RT_EOK */ rt_err_t rt_thread_yield(void) { register rt_base_t level; struct rt_thread *thread; /* disable interrupt */ level = rt_hw_interrupt_disable();//關中斷 /* set to current thread */ thread = rt_current_thread;//得到當前線程 /* if the thread stat is READY and on ready queue list */ if (thread->stat == RT_THREAD_READY &&//如果當前線程處於就緒狀態且在就緒隊列 thread->tlist.next != thread->tlist.prev) { /* remove thread from thread list */ rt_list_remove(&(thread->tlist));//從就緒隊列中移除當前線程 /* put thread to end of ready queue */ rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]),//加入到就緒隊列末尾 &(thread->tlist)); /* enable interrupt */ rt_hw_interrupt_enable(level);//開中斷 rt_schedule();//重新調度線程 return RT_EOK; } /* enable interrupt */ rt_hw_interrupt_enable(level);//開中斷 return RT_EOK; } 8 線程睡眠 [cpp] /** * This function will let current thread sleep for some ticks. * * @param tick the sleep ticks * * @return RT_EOK */ rt_err_t rt_thread_sleep(rt_tick_t tick) { register rt_base_t temp; struct rt_thread *thread; /* disable interrupt */ temp = rt_hw_interrupt_disable();//關中斷 /* set to current thread */ thread = rt_current_thread;//得到當前線程 RT_ASSERT(thread != RT_NULL); /* suspend thread */ rt_thread_suspend(thread);//掛起當前線程 /* reset the timeout of thread timer and start it */ rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &tick);//設置定時器 rt_timer_start(&(thread->thread_timer));//啟動定時器 /* enable interrupt */ rt_hw_interrupt_enable(temp);//開中斷 rt_schedule();//啟動調度器 /* clear error number of this thread to RT_EOK */ if (thread->error == -RT_ETIMEOUT)//將當前線程的錯誤碼設置為超時 thread->error = RT_EOK; return RT_EOK; } [cpp] /** * This function will let current thread delay for some ticks. * * @param tick the delay ticks * * @return RT_EOK */ rt_err_t rt_thread_delay(rt_tick_t tick) { return rt_thread_sleep(tick); } 9 線程控制 [cpp] * This function will control thread behaviors according to control command. * * @param thread the specified thread to be controlled * @param cmd the control command, which includes * RT_THREAD_CTRL_CHANGE_PRIORITY for changing priority level of thread; * RT_THREAD_CTRL_STARTUP for starting a thread; * RT_THREAD_CTRL_CLOSE for delete a thread. * @param arg the argument of control command * * @return RT_EOK */ rt_err_t rt_thread_control(rt_thread_t thread, rt_uint8_t cmd, void *arg) { register rt_base_t temp; /* thread check */ RT_ASSERT(thread != RT_NULL); switch (cmd) { case RT_THREAD_CTRL_CHANGE_PRIORITY://修改優先級 /* disable interrupt */ temp = rt_hw_interrupt_disable();//關中斷 /* for ready thread, change queue */ if (thread->stat == RT_THREAD_READY)//如果線程處於就緒狀態 { /* remove thread from schedule queue first */ rt_schedule_remove_thread(thread);//移除 /* change thread priority */ thread->current_priority = *(rt_uint8_t *)arg;//設置優先級 /* recalculate priority attribute */ #if RT_THREAD_PRIORITY_MAX > 32 thread->number = thread->current_priority >> 3; /* 5bit */ thread->number_mask = 1 << thread->number; thread->high_mask = 1 << (thread->current_priority & 0x07); /* 3bit */ #else thread->number_mask = 1 << thread->current_priority; #endif /* insert thread to schedule queue again */ rt_schedule_insert_thread(thread);//加入調度器 } else { thread->current_priority = *(rt_uint8_t *)arg; /* recalculate priority attribute */ #if RT_THREAD_PRIORITY_MAX > 32 thread->number = thread->current_priority >> 3; /* 5bit */ thread->number_mask = 1 << thread->number; thread->high_mask = 1 << (thread->current_priority & 0x07); /* 3bit */ #else thread->number_mask = 1 << thread->current_priority; #endif } /* enable interrupt */ rt_hw_interrupt_enable(temp); break; case RT_THREAD_CTRL_STARTUP://啟動 return rt_thread_startup(thread); #ifdef RT_USING_HEAP case RT_THREAD_CTRL_CLOSE://關閉線程 return rt_thread_delete(thread); #endif default: break; } return RT_EOK; } 10 查找線程 [cpp] /** * This function will find the specified thread. * * @param name the name of thread finding * * @return the found thread * * @note please don't invoke this function in interrupt status. */ rt_thread_t rt_thread_find(char *name) { struct rt_object_information *information; struct rt_object *object; struct rt_list_node *node; extern struct rt_object_information rt_object_container[]; /* enter critical */ if (rt_thread_self() != RT_NULL) rt_enter_critical();//進入臨界區 /* try to find device object */ information = &rt_object_container[RT_Object_Class_Thread];//從內核對象容器中獲取內核對象鏈表 for (node = information->object_list.next; node != &(information->object_list); node = node->next) { object = rt_list_entry(node, struct rt_object, list);//得到內核對象 if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0)//比較名字 { www.2cto.com /* leave critical */ if (rt_thread_self() != RT_NULL) rt_exit_critical();//退出臨界區 return (rt_thread_t)object;//返回內核對象 } } /* leave critical */ if (rt_thread_self() != RT_NULL) rt_exit_critical();//退出臨界區 /* not found */ return RT_NULL;//返回未找到 }