2009年6月18日 星期四

心得

上老師的課也快一整學年了,上學期的OS和這學期的OSII。

老實說, 上學期結束時,我覺得我什麼東西都沒學到,
腦中只有考試前硬背的一些理論。

每次上課時,即便我很認真的抄筆記,我可能還是無法理解意義。
導致後來連筆記都不想抄了,因為抄了回家還是看不懂。

我一直很疑惑到底為什麼會這樣,
或許是我課堂上理解能力和記憶能力太差吧。

原先,我一直認為是老師的授課方式不適合我,
因為我似乎都找不太到,老師每次上課的主題,
或許是因為說話習慣吧,讓我總是找不到重點。

直到這次OSII期末考前,我開始看錄影檔,雖然我知道錄影檔有缺,
但我還是只有這樣做,想說看多少算多少。
在期中考前大概看完4.5.6.7這些章節,也做了筆記。
發現,原來我要看錄影檔才抓的到重點,
因為當我沒抄到老師講某幾句話時,可以倒轉。

當然,因為我沒看完,所以期末考,後面印象都蠻模糊的,
但是前面第一大題就比較有信心了,因為那剛好是我看過的。

原本,是不喜歡老師的授課方式的,
因為感覺沒有整體的架構,會不知道剛剛理解的東西是要做什麼的。
但我現在發現,原來我感覺不到的架構,都會在老師說的話當中,
但老師這種話可能都只會講一遍。

所以我個人覺得,錄影檔真的很重要!!!
希望老師可以讓以後的錄影檔完整一點!!!

Memory Management II

※ uCOSII
1. 記憶體管理機制比較像slab(簡化版的slab)
2. 沒有buddy system,因為uCOSII沒有MMU,沒有辦法管理MMU
所以不需要buddy system。

※
系統剛啟動時,以靜態分配的方式,將記憶體分成很多partition,
每個partition有多少塊,有多大,都是一開機完就分配好的,
因為uCOSII是real time的OS,是個embedded OS,所以可以做這個假設。

※
其記憶體分配機制很有效率,time comparsity是BigO(1),
slab幾乎是BigO(1),有時會比較大。
利用getmem指名從哪裡拿記憶體,大小不能指定。

Memory Management I

※ linux記憶體管理
1. kernel管理機制:負責配置給AP記憶體,一部分kernel主動配置,
一部份是kernel被告知有人需要多少(ex:malloc)。
使用slab和buddy system
2. user space管理機制

※ KCP:一個從頭執行到尾的動作,不管被誰驅動(一群涵式的呼叫與回傳)

※ Buddy system:最小的單位是page。

※ Slab:單位為物件,大小不定。

※
1. KCP最主要跟slab要記憶體
2. slab跟buddy system要記憶體
3. 系統裡面會有很多slab,原則上只會有一個buddy system
4. user space的管理機制不可能用slab管理記憶體,
因為硬體幫助管理記憶體最小的限制單位是page,但slab大小不定,
因此以buddy system幫助user space管理。

2009年6月16日 星期二

chapter 7

※ ISR只能做 non-blocking

※ OSSemCtreate(cnt)
1. prevent -> OSEventCnt = cnt;
一次最多有cnt個人能進去critical section
2. struct第一個欄位記錄使用函式的種類
3. OS_EventWaitListInit() 把waitingQ全部清空為0

※ OSSemDel()
1. semaphore通常拿來做IPC使用
2. opt = OS_DEL_NO_PEND
有人在semaphore的waitingQ裡面,不能刪除semaphore
3. opt = OS_DEL_ALWAYS
不管有沒有人在waiting裡面,都做刪除
4. 檢查OSEventGrp來判斷裡面有沒有人
5. 將waitingQ中所有的task搬回readyQ,
否則這些task將永遠不會執行。
6. OSEventTaskRdy()每呼叫一次,就會有一個task進入readyQ,
一直呼叫到waitingQ都變0

※ 系統裡面可以有多個semaphore,
每個semaphore都會有自己的waitingQ。
系統裡面有幾各CPU就有幾各readyQm。

※ OSSemPend() lock
1. A想進入critical section,做OSSemPend()lock,
檢查OSEventCnt是否大於0,成立-1,回傳。
2. B已經進入critical section,A想進入critical section,
做OSSemPend()lock,檢查OSEventCnt,沒有大於0,
此時A將自己從readyQ擺到waitingQ,呼叫OS_Sched()。
B離開critical section,做OSSemPost()unlock,
使用EventTaskRdy()叫醒想進入critical section的A,
此時,A與B兩個都是ready的,這時看schedule決定誰執行。
若是A的priority較高,A去看自己的status是ready的,進入critical section。
3. 和2相同,多了timeout的條件。
A可能會被kernel的timer或是B其中一個叫醒。

chapter 6(cont)

※ OS_EventWaitListInit()
將.OSEventGrp和OSEventTbl都填0

※ loop unrolling

※ OS_EnentTaskRdy() 執行XXXPost時就會呼叫這個
從waitingQ裡找出優先權最高的task,放到readyQ裡面

※
y = OSUnMapTbl[prevent->OSEnentGrp];
bity = OSMapTbl[y];
x = OSUnMapTbl[prevent->OSEventTbl[y]];
bitx = OSMapTbl[x];
prio = (INT8U)((y<<3)+x);
從waitingQ裡找出最高優先權的task,將之移出waitingQ。
演算法和原本readyQ是一樣的。
ptcb->OSTCBDly = 0
塞0進去,因為已經等到了,所以設為0,否則之後會再叫醒一次
ptcb->OSTCBStat &= ~msk
令task變為ready

※ OS_EventTaskRdy() 總結
從waitingQ裡找出最高優先權的task,從waitingQ搬到readyQ。
然後在TCB裡做必要的修改。

chapter 6

※ Event Control Block實現waitingQ

※
Semaphore
Mutual Exclusion
Message Mainbox
Message Queue
以上這幾種機制皆會使用到waitingQ

※ ECB的資料結構和readyQ差不多

※ ECB的演算法和function設計來和readyQ之間做一些互動

※
OSXxxCreate
OSXxxDel
OSXxxPend -> wait lock,等到為止
OSXxxAccept -> 等不到就走(non-blocking)
OSXxxPost -> unlock signal
OSXxxQuery -> 把整個ECB複製一份,memcpy加上critical section。

※
1. Block System call & Nonblocking System call
ex.
kmalloc
vmalloc
2. Asynchronous System call(A I/O)
用thread可達到同樣效果,但context switch的overhead太大

※ ECB
1. 只有task可以做等待的動作,ISR不能。
2. ISR可以把task從waitingQ中拉到readyQ
3. task什麼事都可以做,ISR不能做wait的動作
4. 可以多個task去wait同一個resource
5. 所有的function都沒有處理同步的問題,所以呼叫的人要自己處理

※ ECB資料結構
1. .OSEnentType ECB的種類0.1.2....
2. .OSEventGrp 實現waitingQ,剛開始都填0
3. .OSEventCnt 取決於1
4. .OSEventPtr 取決於1
5. waitingQ,剛開始都填0

※ ECB Functions
1. OS_EventWaitListInit() 給ECB初始值
2. OS_EventTaskRdy() 呼叫signal或post時會使用到,
把task從waitingQ搬到readyQ,一定是搬最高優先權的task
3. OS_EventTaskWait()
把某個task放到waitingQ裡面
4. OS_EventTO() to = timeout
設定最多等多久,時間到了就直接設為ready

chapter 5(cont)

※ OSTimeTick()
1. OSTCBList會把正在執行的task串成一列,
最後一個task一定是idle task,因為在新增刪除task時一定是從頭,
系統裡面第一個task又是idle task,造成idle task放最後一個。
2. 因此可以從頭往下找,找到idle task為止,到idle task就不執行,
因為idle task本身不會呼叫sleep,永遠都是ready。
3. (不太重要)
去判斷每個TCB裡的欄位Dly的值,數字代表要等多久。
每次執行-1,當有1變到0的時候,會把task擺到readyQ裡,
在此時,如果有人去suspend住某個task時,
他將不會變成0,至少會是1,為了避免會睡不到1個tick。
4. ptcb->OSTCBStat & OS_STAT_SUSPEND == 0x00
可能要等待多個動作(所有條件)滿足才能往下執行。

※ OSTimeDlyResume()
1. 把剩下的tick歸0
2. 把task搬到rdyQ

※ OSTimeGet() & OSTimeSet()
要包在critical section裡

※ 解決Delay a task until tx的問題 I
不可以使用第一種critical method包在critical section裡
因為要等時間中斷,但是前面卻已經把interrupt關掉,所以錯

※ 解決Delay a task until tx的問題 II
使用第二種critical method包在critical section裡,
頂多會有interrupt進來,假設ISR程式碼都很短,影響不大。
影響比較大的是high priority task,因為sched被lock住,
因此不會context switch

※ 解決Delay a task until tx的問題 III
自己寫,利用第一種critical method但是把巢狀拿掉。

※ OSTimeTick演算法的缺點
時間複雜度是系踏(n),n是系統裡面所有task的數量。

※ BSD的實作方法
用link-list將timer control block(時間控制單元)串起來,
5 1 0 3 -> 5 6 6 9
好處:每次一個時間中斷,往上呼叫的時候,只要對第一項做-1就好
壞處:新增比較麻煩,有時OSTimeDly的時間複雜度比較高
結論:還是比uCOSII好
linux演算法更複雜,介於BSD和uCOSII之間

chapter 5

※ Time Management
所以的OS都必須面臨怎麼管理時間,
包括micro kernel都要將這部分放在kernel裡面,
否則很難寫。
1. OSTimeDly()
2. OSTimeDlyHMSM() 和OSTimeDly()設計方法幾乎一樣,
多一個時間的轉換,把小時.分...轉成tick
3. OSTimeDlyResume() 有人想睡5個tick的時間,
因為有緊急事件,不能睡那麼久,用OSTimeDlyResume()叫他
4. OSTimeGet() 沒啥意義,字面上
5. OSTimeSet() 同上

※ Delay a task until tx
t=OSTimeGet()
if(tx-t>0)
OSTimeDly(tx-t)
OSTimeDly()睡多久,OSTimeGet()得到現在時間
利用這兩個函式,寫出要睡到下午5點鐘的程式。
----->會發生錯誤,t會有誤差。

※ OSTimeDly()
1. 把task從rdyQ裡移除
2. TCB裡的欄位OSTCBDly代表想要睡多久,要睡幾個tick
3. 最高優先權的task跑去睡覺,所以要呼叫OS_Sched()

※ OSTimeDlyHMSM()
1. 和OSTimeDly差不多
2. 將時分秒轉換成幾個tick(毫秒)
3. 因為integer,所以最大65535,如果大於65535就用loop解決
OSTimeDly(32768)不用65535因為怕溢位.....

※ OSTimeTick() Timer(1)
1. timer為interrupt進來,CPU去做ISR,前半段和後半段用組語寫,
前半段組語,將CPU目前的狀態全部存下來,將來就可以回復。
後半段,把記憶體的值搬到CPU。從哪邊被打斷就從哪邊重新執行。
中間用C語言寫就可以。
2. OSTimeTick()
完全使用C語言撰寫,演算法和資料結構最為重要.....,
3. 從組語裡去呼叫OSTimeTick()
5. OSTCBList將uCOSII裡所有的task串接在一起
4. OSTimeTick()裡的foreach(....)
去OSTCBList裡每個task做檢查看OSTCBDly是否>0,
如果大於0就-1,代表經過1個tick的時間,
如果等於1,將從1變0的時候,代表等的時間已經到了,即讓task變ready
5. task最多:uCOSII2.5.2->64,uCOSII2.8.x->256,linux->以k來計算
6. OSTimeTick()是function call,執行時間會很長,
就會造成I/O的performance會不好,中斷會被disable掉太久的時間。
要自己enable interrupt。
timer這個interrupt的priority非常高,較低優先的的那些task和interrupt會進不來,
為了讓這個情況不發生,所以driver最好不要這樣寫。

※ OSTimeTick() Timer(2)
1. 這種寫法比較好,但程式碼比較複雜,執行時間更長。
2. 中斷進來呼叫ISR,ISR只執行OSMBoxPost,就結束了,因此ISR長度很短。
3. OSMBoxPost送出一個message,只是把某一個或某幾個flag設為1,就執行完了。
4. interrupt進來,CPU收到並呼叫ISR,執行OSMBoxPost,往下執行,ISR結束。
接下來由task當作kernel thread接手,此時中斷被打開,優先權很高。
TickTask()
{
OSMBoxPend()
OSTimeTick()
OS_Sched() //這裡要重新排程 因為是系統裡自己寫的程式
}
OSTimeTick() Timer(1)不用自己call OS_Sched()是因為
ISR結束時會呼叫OSINTExit(),裡面就會call OS_Sched(),所以不用再去call
6. 在linux裡,ISR為top half,kernel thread為bottom half(可延遲的function)
7. 在uCOSII裡,OSTickISR()為top half,OSTimeTick()為bottom half

suspend task

※ OSTaskSuspend()
1. 把某個task從rdyQ移走,將狀態改成OS_STAT_SUSPEND
2. 若是自己把自己停掉,就要call OS_Sched()

※
一個task可能會在 OS_STAT_SUSPEND,OS_STAT_SEM,OS_STAT_FLAG
都代表task在某各waitingQ裡

※ OSTaskResume()
1. ptcb->OSTCBStat &= ~OS_STAT_SUSPEND==OS_STAT_RDY
成立的話,表示這各task可以繼續往下執行,
所有等的事件都已經滿足。
2. ptcb->OSTCBDly==0
可能再等時間的發生(timer interrupt),ptcb->OSTCBDly代表要等的tick數,
不等於0的話代表不能繼續往下執行。
3.
(ptcb->OSTCBDly==0){
OSRdyGrp = ptcb->OSTCBBitY;
OSRdyTbl[ptcb->OSTCBY] = ptcb->OSTCBBitX;
可能會造成OS_TimeDly(2)睡不到1個tick
ex.
第一個動作B睡一個tick
第二個動作A去suspend(B)
第三個動作C去resume(B)
(程式碼有少,跟課本不一樣????)

※ 把TCB抄出來,幫助除錯。
memcpy到一半時,中斷進來,可能會造成資料結構,
有部份是新的,有部份是舊的。
用critical section包住,可以保證資料是完整的。

delete task

※ delete task
● 從task目前所在的Q,將task拿出,再從link-list中拿走即刪除
● preemption kernel : A刪B不需要呼叫schedule

※ preemption point (在critical section內)
● linux :
1. interrupt可進
2. high priority可搶先low priotity
● uCOSII :
1. interrupt可進

※ 因為delete task很花時間,才加入preemption point

※ ptch->OSTCBDly = 0;
防止要刪除的task被timer放回readyQ

※ ptch->OSTCBStat = OS_STAT_RDY;
防止要刪除的task被其他task放回readyQ

※
OSLockNesting++;
OS_EXIT_CRITICAL();
OS_Dummy();
OS_ENTER_CRITICAL();
OSLockNesting--;
1. OSLockNesting++; OSLockNesting--;
只允許interrup,不允許context switch。
這裡不能改成OSSchedLock()和OSSchedUnlock(),
因為會有巢狀的問題,使得interrupt的狀態會錯誤。
2. OS_EXIT_CRITICAL(); OS_ENTER_CRITICAL();
critical method有三種,如果這裡用其他兩種寫法,
那1.的地方改成OSSchedLock()和OSSchedUnlock()是OK的。
沒有這樣做是因為,uCOSII為了要讓作業系統最能夠跨平台,
還是使用第一種critical method,因為它是最弱的一種CPU。
3. 某些CPU,disable interrupt和enable interrupt中間一定要空格幾行,
如果連在一起寫,後面那行會沒有效果,因此中間要接數個nop,
OS_Dummy()被定義成兩個nop。

※ OSTaskDelReq()
若task握有很多記憶體,直接刪除task,
如果task手中握有大量記憶體或resource,
那些資源就會空在那邊沒人用它。

※
OSTaskDelReq(將刪的TaskID);
將刪的Task中,DelReq欄位改為1(原為0)
OSTaskDel(OS_PRIO_SELF);
1. 以while確保delete成功
2. 以OSTimeDly(1)讓要delete的task能拿到CPU去delete自己。

※ uCOSII的技巧
因為uCOSII希望節省記憶體,
所以不像linux一樣花記憶體去紀錄很多和file相關的狀態。

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

※ 改變task的優先權
1. 卡位(確保沒人)
2. 跟priority有關的欄位都要修改
3. 看在哪個queue裡
(4. priority由高變低要呼叫schedule)

※ 預先計算
將會重複多次運算相同東西的(priority)運算式提到外面,
進入critical section就不用在計算,為了簡短critical section的長度。

2009年3月12日 星期四

作業一

還以為很簡單

結果弄很久

知道哪裡有問題

但不知道問題從何而來

好像三年多白唸了一樣

想了很久還是想不出來 噗

前天上課遲到

果然會使吸收變差XD

2009年3月9日 星期一

第一次

知道老師在問什麼= =

終於不是被三振了

不過上課反而沒有全神貫注一 一

下次小考大概又要被K了

2009年3月4日 星期三

今天 昨天

今天還蠻認真上課的(自以為)

不過還是很多東西不懂

該怎麼說呢

老師說了很多"大致上"

或者"有錯".....

還是沒有辦法很清楚的得到老師想傳達的訊息一 一

...

2009年3月1日 星期日

今日小考

被三振了

是因為我第0章沒去聽的緣故嗎= =

ˋˊ

2009年2月25日 星期三

那張圖

話說今天那張圖
上面DOS下面mutiprogramming那張
老師說的我大概懂@@

但是我不知道這張圖要表達啥= =

難道要表達的就是老師說的東西嗎@@?