嵌入式OS入门笔记-以RTX为案例:三.初探进程
生活随笔
收集整理的這篇文章主要介紹了
嵌入式OS入门笔记-以RTX为案例:三.初探进程
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
嵌入式OS入門筆記-以RTX為案例:三.初探進(jìn)程
1.理論
? ? 進(jìn)程,英文稱呼很多Process, Task 等等,一般通用操作系統(tǒng)稱Process的比較多,各種稱呼涵義稍微有不一樣。一般而言,進(jìn)程是對(duì)一個(gè)運(yùn)行單元的抽象,主要包括內(nèi)存(code,data,heap和stack),CPU狀態(tài)(PC,SP和寄存器值等)與其他OS管理相關(guān)的內(nèi)容。進(jìn)程是一個(gè)運(yùn)行中的程序。在RTX中,一個(gè)task就是一個(gè)進(jìn)程。
一般我們有一個(gè)進(jìn)程控制塊(Process control block,PCB),用于記錄進(jìn)程的相關(guān)信息。在RTX上,這個(gè)控制塊叫做task control block(TCB),是一個(gè)結(jié)構(gòu)體,其中的成員記錄了關(guān)于該task的信息,其定義在rt_TypeDef.h中:
typedef struct OS_TCB { /* General part: identical for all implementations. */ U8 cb_type; /* Control Block Type */ U8 state; /* Task state */ U8 prio; /* Execution priority */ U8 task_id; /* Task ID value for optimized TCB access */ struct OS_TCB *p_lnk; /* Link pointer for ready/sem. wait list */ struct OS_TCB *p_rlnk; /* Link pointer for sem./mbx lst backwards */ struct OS_TCB *p_dlnk; /* Link pointer for delay list */ struct OS_TCB *p_blnk; /* Link pointer for delay list backwards */ U16 delta_time; /* Time until time out */ U16 interval_time; /* Time interval for periodic waits */ U16 events; /* Event flags */ U16 waits; /* Wait flags */ void **msg; /* Direct message passing when task waits */ struct OS_MUCB *p_mlnk; /* Link pointer for mutex owner list */ U8 prio_base; /* Base priority */ U8 ret_val; /* Return value upon completion of a wait */ /* Hardware dependant part: specific for CM processor */ U8 ret_upd; /* Updated return value */ U16 priv_stack; /* Private stack size, 0= system assigned */ U32 tsk_stack; /* Current task Stack pointer (R13) */ U32 *stack; /* Pointer to Task Stack memory block */ /* Task entry point used for uVision debugger */ FUNCP ptask; /* Task entry address */ } *P_TCB;
一個(gè)進(jìn)程會(huì)有它自己的周期,會(huì)處在不同的進(jìn)程狀態(tài)(state,見上面的state成員),不同的狀態(tài)有不同的意味,不同的狀態(tài)間可以相互轉(zhuǎn)換。在RTX中,task的狀態(tài)是在rt_Task.h中定義的,一共有10種:
/* Values for 'state' */ #define INACTIVE 0 #define READY 1 #define RUNNING 2 #define WAIT_DLY 3 #define WAIT_ITV 4 #define WAIT_OR 5 #define WAIT_AND 6 #define WAIT_SEM 7 #define WAIT_MBX 8 #define WAIT_MUT 9 簡單說來,可以分為4大類,inactive(進(jìn)程被清理),ready(就緒),running(執(zhí)行)和waiting(等待)。狀態(tài)3至9都可以歸為等待狀態(tài),區(qū)別在于他們等待的東西不同,從等待狀態(tài)觸發(fā)到就緒狀態(tài)的條件不同。
進(jìn)程的創(chuàng)建和消滅都是主要都牽涉到內(nèi)存分配,排程器的安排,TCB的處理等等,需要具體的OS具體的分析,我們這里貼一下RTX進(jìn)程創(chuàng)建的源代碼: OS_TID rt_tsk_create (FUNCP task, U32 prio_stksz, void *stk, void *argv) { /* Start a new task declared with "task". */ P_TCB task_context; U32 i; /* Priority 0 is reserved for idle task! */ if ((prio_stksz & 0xFF) == 0) { prio_stksz += 1; } task_context = rt_alloc_box (mp_tcb); if (task_context == NULL) { return (0); } /* If "size != 0" use a private user provided stack. */ task_context->stack = stk; task_context->priv_stack = prio_stksz >> 8; /* Pass parameter 'argv' to 'rt_init_context' */ task_context->msg = argv; /* For 'size == 0' system allocates the user stack from the memory pool. */ rt_init_context (task_context, prio_stksz & 0xFF, task); /* Find a free entry in 'os_active_TCB' table. */ i = rt_get_TID (); os_active_TCB[i-1] = task_context; task_context->task_id = i; DBG_TASK_NOTIFY(task_context, __TRUE); rt_dispatch (task_context); os_tsk.run->ret_val = i; return ((OS_TID)i); } 基本就是填TCB,分配內(nèi)存空間,確定優(yōu)先級(jí)和排程相關(guān)設(shè)置,這里就不深入分析。消滅進(jìn)程的源代碼也是類似的。
2.進(jìn)程相關(guān)的基本操作
進(jìn)程在RTX里的基本形式是:
__task void task(void){ for(;;){ //... } } 進(jìn)程相關(guān)操作就是RTX提供的圍繞這樣一個(gè)task的一些基本操作,例如創(chuàng)建,消滅等等。
從應(yīng)用角度來說,了解以下進(jìn)程基本操作就足夠了:
最主要的是這個(gè):
os_tsk_create(task_name,priority);
把函數(shù)名填入,和進(jìn)程的優(yōu)先度,優(yōu)先度后面的筆記會(huì)介紹。
如果留心看源代碼,其實(shí)源代碼的create操作要求一共4個(gè)參數(shù)(FUNCP task, U32 prio_stksz, void *stk, void *argv)。我們最基本的這個(gè)創(chuàng)建函數(shù)并沒有接受后兩個(gè)參數(shù)。如果實(shí)在有需要,有以下另外三個(gè)相關(guān)的操作:
os_tsk_create_ex(task_name,priority,para);
這個(gè)是用于傳遞一個(gè)初始參數(shù)para給相關(guān)進(jìn)程的。例如你有一個(gè)LED_On的進(jìn)程,而你有4個(gè)LED,你只有在創(chuàng)建進(jìn)程時(shí)才能決定,你點(diǎn)亮的是哪個(gè)LED,那么就可以用這個(gè)操作,通過傳遞參數(shù)來決定具體要亮哪個(gè)LED。
os_tsk_create_user(task_name,priority,&stack,sizeof(stack));
這個(gè)是用來給進(jìn)程創(chuàng)建自定義stack的。需要傳遞stack的地址和大小。
os_tsk_create_user_ex(task_name,priority,&stack,sizeof(stack),para);
這個(gè)明顯就是上面兩個(gè)的結(jié)合。
以上這些創(chuàng)建操作,返回類型都是OS_TID,進(jìn)程ID,實(shí)際值從0到255。 所以可以先聲明一個(gè)該類型的值,然后創(chuàng)建進(jìn)程時(shí)讓其返回該值。
2.消滅
os_tsk_delete(taskID);
填入你要消滅的進(jìn)程的進(jìn)程ID,TID。
如果要消滅進(jìn)程本身,用:
os_tsk_delete_self();
注意,RTX的消滅進(jìn)程并不清理互斥鎖或者信號(hào)燈的占有的。所以在消滅一個(gè)進(jìn)程前,確定進(jìn)程釋放了所有資源。內(nèi)存資源會(huì)被這兩個(gè)操作釋放,所以不用擔(dān)心。
3.雜項(xiàng)
如果想要知道當(dāng)前進(jìn)程的ID,使用以下操作:
os_get_TID();
還有一個(gè)非常重要的:
os_sys_init(first_task);
這個(gè)操作初始化整個(gè)RTX,如果不在main中執(zhí)行這一操作,一切都是空談。該操作會(huì)創(chuàng)建第一個(gè)進(jìn)程,也就是first_task。
一般而言,進(jìn)程可以創(chuàng)造別的進(jìn)程,也可以消滅別的進(jìn)程。但進(jìn)程只能夠消滅本身,而不能創(chuàng)造本身。所以就需要有一個(gè)操作去創(chuàng)建第一個(gè)進(jìn)程,然后別的進(jìn)程可由這個(gè)第一個(gè)進(jìn)程去創(chuàng)造。
3.一個(gè)完整的例子
一下是一個(gè)從初始化,到創(chuàng)建第一個(gè)進(jìn)程,到第一個(gè)進(jìn)程創(chuàng)建別的進(jìn)程,最后消滅自己的一個(gè)例子: OS_TID taskID1; OS_TID taskID2; __task void init (void) { //Necessary Initialization //... //Create a task taskID1 = os_tsk_create(task1, 0); taskID2 = os_tsk_create(task2, 0); os_tsk_delete_self (); // Delete the init(self) task } int main(void) { //Necessary Initialization //... os_sys_init(init); }
這個(gè)簡單的例子足夠應(yīng)付最基本使用RTX的需求了。
關(guān)于RTX的排程,優(yōu)先度,內(nèi)存分配和一些OS原語,在后面的筆記會(huì)記錄。
文章轉(zhuǎn)載自:http://blog.csdn.net/raym0ndkwan/article/details/32859989
總結(jié)
以上是生活随笔為你收集整理的嵌入式OS入门笔记-以RTX为案例:三.初探进程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中国版Kindle Paperwhite
- 下一篇: linux下shell编程课程设计,Li