2009年6月18日 星期四

OSSemPend() OSSemPost() 程式碼













OSSemPend()-1
(點擊可放大看)















OSSemPend()-2
(點擊可放大看)















OSSemPost()
(點擊可放大看)


OS學期心得

這學期給我的第一印象是

放假也放太多了吧~~~

到學期末好幾星期連續補課

幾個禮拜下來有種快掛掉的感覺

------------------------------------

uCOSII 與 linux 學習成效比較:

uCOSII 感覺比較有重點, 容易吸收

到最後 linux 老師在教得時候

有點搞不太懂重點在哪裡 想讓我們了解什麼

或許是 linux 東西太多太雜了 不好教 也不好懂

或許是 時間太短了 教得比較急促

----------------------------------

最後想抱怨期末proj...

也許是我能力欠缺

花了還蠻多時間在研究

雖然最後有做出來

可是卻遲交了

這是我第一次遲交作業 還蠻難過的

-------------------------------------

整體來看 受益頗多的

至少讓我更了解OS做作些什麼

想當初大一時 連作業系統是什麼都不知道

以前剛接觸到fedora freeBSD時

用起來都會怕怕的

現在已經可以跟用windows XP 一樣運用自如

OSSemPend()

OSEventCnt=1

task到kernel中執行完此event再回到user mode下繼續執行


前提: task 2已經進入critical section, OSEventCnt=0,

因為OSEventCnt=0, 讓task 1進入waiting狀態 並觸發sched() 把控制權交給task 2

等待task 2執行完, 呼叫sched() 讓task 1繼續執行


前提: task 2已經進入critical section 且沒有動作, OSEventCnt=0,

因為OSEventCnt=0, 所以task 1進入waiting狀態,

又因為task 2一直沒有動作, 所以最後task 1被timer叫醒

回到user mode

2009年4月18日 星期六

04/15

OS_Sched() and OSIntExit():
  1. OS_Sched(): 掌管 task 間的 scheduling
  2. OSIntExit(): 掌管 ISR 的 scheduling
下段程式碼, 若剛好進入contextswitch()怎麼辦(如何EI)?
ans:
OS_Sched(){
...
DI;
...
if(){
contextswitch();
}
...
EI;
...
}

A經context switch 到B後, 由B process做EI;

04/13

Ready list:
  1. heap:
    • ins: O(logn)
    • del: O(logn)
    • min: O(1)
  2. uC/OSII:
    • ins: O(1)
    • del: O(1)
    • min: O(1)
如果有了task的priority, 如何求出他在OSRdyTbl[]所在的位置:
若OSRdyTbl[]為n*n, n一定為2的power,
則x=priority/n, y=priority%n

2009年4月8日 星期三

04/08

INT8U os_TCBInit(){
...
/*在freelist中, 只有application存取, 可用semaphore取代, 但最好不要, 因為overhead大*/
OS_ENTER_CRITICAL();
ptcb=OSTCBFreeList;
if(){
OSTCBFreeList=ptcb->OSTCBNext;
OS_EXIT_CRITICAL();
...
...
...
/*不可用semaphore取代, 此段功能是把task放到readyQ中, 若用semaphore取代, ISR可能會去存取readyQ, 故不可取代*/
OS_ENTER_CRITICAL();
OSTCBPrioTbl[prio]=ptcb;
ptcb->OSTCBNext=OSTCBList;
ptcb->OSTCBPrev=(OS_TCB*)0;
if(OSTCBList!=(OS_TCB*)0){
OSTCBList->OSTCBPrev=ptcb;
}
OSTCBList=ptcb;
OSRdyGrp:=ptcb->OSTCBBitY;
OSRdyTbl[ptcb->OSTCBY]:=ptcb->OSTCBBitX;
OS_EXIT_CRITICAL();
...
}

ready list:
在readyQ中要做的3件事:
  1. insert
  2. delete
  3. find min. priority
在uC/OSII中, 因為insert時只限制priority=0~63的task進入readyQ, 演算法特殊, 故做這三件事都只有O(1)

由ready list再加上 OSUnMapTbl[]可迅速查出目前readyQ中priority最高的task位在哪個位置

2009年3月24日 星期二

03/25

星期一放假...因為五哥的媽媽開刀...
今日小考...
Q:
*OSTCBCur: 目前正在執行的task
*OSTCBHighRdy: priority最高的task
一般來說這兩個值會一樣, 在什麼情況下這兩個值會不同?
ans:
context switch時會不一樣
一開始OSTCBCur & OSTCBHighRdy都指向task A
因為某種原因使task B的priority變高
OSTCBHighRdy指向task B
接下來做context switch, CPU將task A 的TCB存回去, 把task B load進來
最後會讓OSTCBCur = OSTCBHighRdy

TASK CONTROL BLOCK
typedef struct os_tcb{
/*存放指向stack開頭的指標sp, stack中有存regs, pc, psw*/
OS_STK *OSTCBStkPtr;

/*OSTaskCreatEXT才有下列東西, 與此function後面跟的參數一樣*/
#if OS_TASK_CREATE_EXT_EN > 0
void *OSTCBExtPtr;
OS_STK *OSTCBStkBottom;
INT32U OSTCBStkSize;
INT16U OSTCBOpt;
INT16U OSTCBId;
#endif
}

/*把所有TCB串起來(readyQ, waitingQ...)*/

struct os_tcb *OSTCBNext;
struct os_tcb * OSTCBPrev;

/*下列五種功能只有一種用得到, 與行程間的通訊有關, 這樣寫是自己手動最佳化, 省記憶體空間*/
#if ((OS_Q_EN>0)&&(OS_MAX_QS>0))(OS_MBOX_EN>0)(OS_SEM_EN>0)(OS_MUTEX_EN>0)
OS_EUENT *OSTCBEventPtr;
#endif

#if ((OS_Q_EN>0)&&(OS_MAX_QS>0))(OS_MBOX_EN>0)
void *OSTCBMsg;
#endif

#if(...)
#if ...
#endif ...
#endif


/*決定要睡多久, 必須透過systemcall來修改(ex: OSTimeDly...)*/
INT16U OSTCBDly;
INT8U OSTCBStat;
/*task的priority*/
INT8U OSTCBPrio;

/*以下由OSTCBPrio算出來的, 在每次context switch時都會用到, 為加快CPU的速度所以先算起來放, 因為priority的更新速度並沒有比context switch快*/
INT8U OSTCBX;
INT8U OSTCBY;
INT8U OSTCBBitX;
INT8U OSTCBBitY;

#if OS_TASK_DEL_EN>0
/*若要讓該task死掉, 將下值改為1即可*/
BOOLEAN OSTCBDelReg;
#endif
}

OSTCBFreeList:
free TCB串成的list, 可以快速拿到free的TCB, 加快速度
感覺上像是linux中的slab(但平均速度快, 最佳情況比較慢)

2009年3月19日 星期四

03/18

Hooks:
OS_CTX_SW_HOOK{

}
空的, 每次context switch發生就會呼叫一次, 讓user寫入事件用

進入第三章...
critical sections:
application本身在user mode下不能直接call enable interrupt and disable interrupt, 必須透過system call, 但在kernel下可以

可以用semaphore()或enable/disable interrupt來保護
semaphore(): 用約二三十行來保護資料
若只保護1行資料, 感覺上很大費周章
DI, EI: 只用兩行
效能較高(降低overhead)
但若保護的程式碼很長, 會使DI, EI的時間變久, 會讓有些interrput都無法執行

OS_ENTER_CRITICAL(); /*在此執行OS_TIME_DELAY();*/ OS_EXIT_CRITICAL();
這樣通常會讓系統crash掉, 唯讀x86不會, 因為context switch時會讓interrput再度打開

實做critical section的三種方法:
1.OS_CRITICAL_METHOD=1
最簡單的方法, 無使用到save & restore
func1(){
DI;
func2();
.../*離開critical section*/
EI;
}
func2(){
DI;
...
EI;
/*離開critical section*/
}
這樣會出問題, 所以call function時要先注意function內有無DI, EI
2.OS_CRITICAL_METHOD=2
PSW(processor status word)用於save & restore stacks
使用stack來實做nested interrput enable/disable interrupt
3.OS_CRITICAL_METHOD=3
PSW相較於method2不局限於存在stack, 而可以存在memory中
OSTaskChangePrio()
可改變task priority=task ID, 但更改可能造成某些程式不能跑(扯到task ID)

OSTaskDel(xxx)
xxx=OS_PRIO_SELF代表刪除自己
xxx=task ID 代表刪除task IDxxx的task
(task無法用returne關掉)

OSTimeDly(), OSTimeDlyHMSM(), OSFlagPend(), OSSemPend(), OSMboxPend(), OSQPend
均會使task進入到waiting Q中
OSTimeTick()會使task回到ready Q中

全部task都進入waiting Q怎麼辦?
ans: idle task永遠在ready Q

doubley linked的好處: delete方便

*OSTCBCur;//目前正在執行的task
*OSTCBFreeList;//指向TCB開頭
*OSTCBHighRdy;//priority最高的task
*OSTCBList;//all task均可由此list找到
*OSTCBPrioTbl[];//找TCB用
OSTCBTbl[];//預先配置好的TCB
*OSTCBCur;與*OSTCBHighRdy;只有在context switch時才會不一樣

2009年3月17日 星期二

03/16

小考:
void Task(void *pdata){
INT8U x;
INT8U y;
INT8U err;

for(;;){
OSSemPend(RandomSem, 0, &err);
x=random(80);
y=random(16);
OSSemPost(RandomSem);


PC_DispChar(x, y+5, *(char*)pdata, DISP_FGND_BLACK+DISP_BGND_LIGHT_GRAY);
OSTimeDly(1);
}
}
橘色部份是讓10個task在執行時隨機印出他 們的名子
此段程式碼用Semaphore去保護
若给為用OS_ENTER_CRITICAL(); OS_EXIT_CRITICAL();去保護
也就是disable interrupt, enable interrupt去保護, 可不可以?
ans:
可以, 但同時也禁止interrupt的執行
若用Semaphore去保護, 執行到critical section, 突然有interrupt進來要修改critical section中被保護的資料, 就保護不了.
這兩種方法各有優缺點, 到底要用哪種, 取決於該段保護的資料有可能被誰存取.
在此段程式碼中, 因為只有可能被task存取, 很少有機會被interrput存取, 所以用Semaphore去保護

開始上課...
idle task是priority最低的task, 功能是一直做加法(無意義的事...)
可以用來判斷CPU的使用率, ex: 加法做20次/毫秒=>CPU使用率0%, 加法做0次/毫秒=>CPU使用率100%

TaskStart():
AckMbox=OSMboxCreate((void*)0);
TxMbox=OSMboxCreate((void*)0);
用於建立MSN的IPC(inter process communication), 因為在建立TCP時就事先allocate了, 所以速度快
PC_DOSReturn();
修改pc值, 使強制回到main function

Task1(): 統計Stack空間
Task2(): 一直印 '', '/', '-', '\'
Task3(): 一直印 '', '/', '-', '\', 且將 '?' 填入dymmy[i] (很明顯的, stack使用率高於Task2())
char dymmy[500];
INT16U i;
此兩行資料誰放在stack最上方, 所造成的CPU使用率不同. 若發現比較高, 則把此兩行對掉即可改變stack方式使CPU使用率降低
Task4(): priority=4
Task5(): priority=5(永比task4高)
兩個task互相傳MSN(task4:" #*(&%@!... ", task5: "恩"....)
task4會在OSMboxPend(AckMbox, 0, &err)等待task5的回應, 且task5的OSTimeDlyHMSM(0, 0, 1, 0)會等待1秒, 所以priority高的task5不會一直執行

linux 2.6, linux 2.4 and uC/OS-II 之stack的比較:
linux2.6:
stack大小為4k or 8k
user mode下有的stack, kernel mode下也有一模一樣的stack
interrupt service routines(kernel mode)有的stack, kernel service routine(kernel mode )也有相對應的stack
優: 各自有各自的stack比較安全, 省記憶體空間
缺: 執行上比較慢
linux 2.4:
stack大小一定為8k, 因為要預留4k給ISR使用
將對於linux2.6不同的地方在於 interrupt service routines沒有stack, 而與kernel service routines下的stack共用
優: 速度上比linux2.6還要快一點
缺: 記憶體空間比linux2.6浪費
uC/OS-II:
stack大小一定為8k
只有kernel mode, 沒有user mode
kernel mode, kernel service rouutines and interrupt service routines 都使用同一個stack
優: 執行速度上是最快的
缺: 記憶體空間使用上是最浪費的

2009年3月9日 星期一

03/09

小考:
DOS可視為MC/OSII的boot loader
IVT的功能?內容物?機制?
1.當interrupt進來時, 用於中斷CUP目前正在執行的事, 轉而執行interrupt
2.一道指令或向量
3.借由一道指令或向量跳到ISR裡去執行interrupt

PC_VectSet()
要用什麼方法保護資料取決於該筆資料可能會由誰去讀

OSTaskCreate()
1.create TCB 放到 ready Q
2.
OSTaskCreate(
TaskStart, //第一到指令所在位置(function name)
(void*)0, //參數(被TaskStart用到)
&TaskStartStk[TASK_STK_SIZE-1], //stack開頭(與CPU設計有關, 跨平台需要修改, 設計上失敗, 但速度快)
0 //設定優先權
);

OSStart()
找出CPU中priority最高的task並將CPU控制權交給它
(never return)

return 定義
指執行ret這道組合語言

OSStart之後剛開始只有兩個task, 分別為TaskStart, idle task
因為idle task的priority=63...非常低, 所以由TaskStart先開始執行

OSTimeDLYhmsm 利用類似poling的方式去檢查有無按esc此鍵
若有則用longjmp指令回到boot loader(一般都直接關機不會回boot loader)
注意: 在此絕對不是return

2009年2月24日 星期二

看板成立!!

耶~希望可以紀錄很多東西~