|
當(dāng)操作系統(tǒng)要建立一個進程時操作系統(tǒng)首先要對棧空間和進程控制塊進行初始化,這里的棧是為任務(wù)在內(nèi)存里開辟的一塊的模擬的堆棧區(qū)域,主要用來保存CPU的所有寄存器和任務(wù)的入口首地址,在任務(wù)切換時,保存CPU寄存器和程序入口,注意這里由于這是人造的堆棧所以你必須提供入口,這個入口就是取得函數(shù)的入口地址,這是棧,那么進程控制塊主要是保存一些與任務(wù)密切相關(guān)的數(shù)據(jù),比如本任務(wù)的堆棧在哪里,本任務(wù)的狀態(tài),本任務(wù)在就緒表中的坐標(biāo)等參數(shù),加速任務(wù)切換等,
那么堆棧是怎樣初始化的呢或者說初始化之后的結(jié)果是多少呢?結(jié)構(gòu)是什么樣的?
其實堆棧就是一個數(shù)組,這個數(shù)組創(chuàng)建的時候內(nèi)部數(shù)據(jù)全部清0,那么運行對戰(zhàn)初始化后堆棧變成了什么樣子?就那空閑任務(wù)來做例子吧
空閑任務(wù)他什么也不做,只是傻傻對一個32位的變量進行++,操作,他的優(yōu)先級最低,也就是任何一個任務(wù)就緒了就可以搶占他,他只是在
操作系統(tǒng)沒有就緒的任務(wù)時運行,但他確實是一個任務(wù),因此他擁有所有任務(wù)的特性。又因為他簡單所以比較好分析。
首先創(chuàng)建一個堆棧:
static OS_STK DT_XDATA OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE];
這就是創(chuàng)建的那個空閑任務(wù)的堆棧,創(chuàng)建空閑任務(wù)時調(diào)用OSTaskStkInit來初始化這堆棧代碼如下:
OS_STK DT_XDATA *stk;
ppdata = ppdata;
opt = opt;
stk = (OS_STK DT_XDATA *)ptos;
*stk++ = (0xFF + 1);
*stk++ = 2 + 13;
*stk++ = (INT16U)task & 0xFF;
*stk++ = (INT16U)task >> 8;
*stk++ = 0x0A;
*stk++ = 0x0B;
*stk++ = 0xD1;
*stk++ = 0xD0;
*stk++ = 0x00;
*stk++ = 0x00;
*stk++ = 0x01;
*stk++ = 0x02;
*stk++ = 0x03;
*stk++ = 0x04;
*stk++ = 0x05;
*stk++ = 0x06;
*stk++ = 0x07;
return ((void DT_XDATA *)ptos);
STK是一個指向堆棧首地址的指針,用它修改堆棧的值,最后執(zhí)行完堆棧的值如下
OSTaskIdleStk【0】=0
OSTaskIdleStk【1】=15
OSTaskIdleStk【2】=任務(wù)入口函數(shù)地址高八位
OSTaskIdleStk【3】=任務(wù)入口函數(shù)地址低八位
OSTaskIdleStk【4】=ACC=10
OSTaskIdleStk【5】=B=11
OSTaskIdleStk【6】=DPH=0XD1
OSTaskIdleStk【7】=DPL=0XD0
OSTaskIdleStk【8】=PSW=0
OSTaskIdleStk【9】=R0=0
OSTaskIdleStk【10】=R1=1
OSTaskIdleStk【11】=R2=2
OSTaskIdleStk【12】=R3=3
OSTaskIdleStk【13】=R4=4
OSTaskIdleStk【14】=R5=5
OSTaskIdleStk【15】=R6=6
OSTaskIdleStk【16】=R7=7
表示每個字節(jié)代表的存入的寄存器名字,他的堆棧是由下向上生長的!
然后函數(shù)返回一個堆棧的首地址,至此堆棧的初始化就完成了
接下來是任務(wù)控制塊(TCB)
任務(wù)控制塊到底在哪里呢?在這里看下面的定義
static OS_TCB DT_XDATA OSTCBTbl[OS_MAX_TASKS + OS_N_SYS_TASKS];
這就是書上所謂的TCB池,書總是愛故弄玄虛,你媽逼的不就是個數(shù)組嗎?瞎比比什么!記住所有的一切的操作的核心就是對這個數(shù)組的操作
他就是TCB,而且作者把他開辟為一塊靜態(tài)的內(nèi)存區(qū),不被擾動的,因為他很重要,
什么是空TCB呢?他在程序中的樣子是這樣的
OS_EXT OS_TCB DT_XDATA * DT_XDATA OSTCBFreeList;
不難看出,他就是個結(jié)構(gòu)指針,但是一個指針怎么和空表聯(lián)系起來?原來他里面的值存著尚未用的OSTCBTbl【】,也就是說,當(dāng)有任務(wù)要求占一個TCB時,首先要通過這個空表指針得到,還要看看這個表示不是用完了,獲得了這個空閑的表的地址后,還要更新OSTCBFreeList,讓他指向下一個沒有使用的空的TCB表,這也就是他的作用了
還有一個優(yōu)先級和TCB對應(yīng)的指針數(shù)組,為什么要做這個數(shù)組呢?這個數(shù)組存著什么?先看定義
OS_EXT OS_TCB DT_XDATA * DT_XDATA OSTCBPrioTbl[OS_LOWEST_PRIO + 1];
這就是那個指針數(shù)組,為什么要這個數(shù)組現(xiàn)在我還不知道,但是有一點可以看出來,他可以快速的通過任務(wù)對應(yīng)香型的TCB,也就是說
知道了任務(wù)的優(yōu)先級我就知道這任務(wù)的TCB在哪里,和目錄一樣,它里面存的全部是任務(wù)的TCB首地址,
還有一個指針這個指針叫做
OS_EXT OS_TCB DT_XDATA * DT_XDATA OSTCBList;
他是做什么的呢?他用來存一個地址,這個地址如果是第一次分配這個TCB表,那么他的值是0,第二次就是第一次的地址,依次向下,他的值
給了鏈表指針里的下一個表的指針,可見它是用來更新鏈表的!我感覺他只是個中間量而已,角色并不是很重要。
哈哈,定義不高明白,是看不進去的,因為他老是跳來跳去,而且有數(shù)組,有指針,還有指針數(shù)組,
搞明白定義家簡單了,初始化大致分為如下幾部:
取得空表,
占用空表
空表指針下移
TCB初始化,
優(yōu)先級和TCB目錄寫入
加載鏈表的下個和上個TCB塊
結(jié)束
主要還是對這四個的定義的理解,其他的都是小事,水到渠則成!
|
|