pintos作業系統實驗Project1-時鐘
目前在學習作業系統,在這裡用於記錄學習過程,學習過程中主要參考了laiy的文章,作為一個初學者,有些地方理解不是很透徹,就當作是筆記了。
Project1的實驗內容是重新設計timer_sleep函式,使用指定方法優化其實現方式。
pintos裡面原始的timer_sleep函式是這樣的,這裡的實現方式是使用忙等。
1 void 2 timer_sleep (int64_t ticks) 3 { 4 int64_t start = timer_ticks (); //獲取當前時鐘 5 6 ASSERT (intr_get_level () == INTR_ON); //確認當前狀態是開中斷 7 while (timer_elapsed (start) < ticks) //當呼叫之後過去的時間還沒到睡眠時間時 8 thread_yield (); //是當前程序進入就緒佇列等待,呼叫新的程序 9 }
這種方法實現起來較為簡單,但是也有明顯的缺陷,那就是在睡眠時間裡程序仍然在佔用著CPU資源。我們的任務就是要解決這個問題,方案是利用阻塞機制,當用戶程式呼叫timer_sleep時,使當前程序進入阻塞狀態,並呼叫其它程序,當睡眠時間結束時喚醒該程序。
到這裡應該思考幾個問題:
- 用什麼來記錄使用者呼叫時傳遞的睡眠時間?
- 在哪裡對睡眠時間進行什麼操作?
- 如何檢測睡眠時間是否結束?
經過教員講解,加之學習laiy的文章,基本理出一條思路:修改timer_sleep函式,使得睡眠時間大於0的時候將程序變為阻塞狀態,為了實現這一點,需要建立一個變數sleep_ticks傳遞睡眠時間,在建立程序的時候初始化為0,當呼叫timer_sleep後傳參;而後在每個時鐘中斷均需要對每個程序進行檢測sleep_ticks是否大於0,每檢測一次sleep_ticks--,直至sleep_ticks=0時喚醒該程序
下面進行具體實現:
首先線上程的結構體中加入我們需要的成員
1 int64_t sleep_ticks; /*# of timer ticks since blocked. */
在建立執行緒時初始化sleep_ticks
1 t->sleep_ticks = 0;
重寫timer_sleep函式
1 /* modified func */ 2 void 3 timer_sleep (int64_t ticks) 4 { 5 if(ticks <= 0) //如果使用者呼叫的睡眠時間<=0,則不阻塞該執行緒 6 return; 7 8 ASSERT (intr_get_level () == INTR_ON); //確認中斷是開啟的 9 enum intr_level old_level = intr_disable (); //關中斷,並儲存之前的中斷狀態,即lod_level是開中斷狀態 10 struct thread *current_thread = thread_current (); //獲取當前執行緒資訊的結構體指標 11 current_thread->sleep_ticks = ticks; //將使用者需要執行緒睡眠的時間引數傳給sleep_ticks 12 thread_block (); //將當前執行緒狀態設定為阻塞態 13 intr_set_level (old_level); //開中斷 14 }
利用每一個時鐘中斷對每個執行緒進行檢測,需要在timer_interrupt中加入函式thread_foreach()
1 thread_foreach (blocked_thread_check, NULL); //對每個執行緒都應用函式blocked_thread_check
這裡的blocked_thread_check即負責檢測每個執行緒的sleep_ticks,如果減到0則喚醒該程序,需寫入thread.c裡面
1 /* Check the blocked thread */ 2 void 3 blocked_thread_check (struct thread *t,void *aux UNUSED) 4 { 5 if (t->status == THREAD_BLOCKED && t->sleep_ticks > 0) //對於處於阻塞狀態的執行緒才會檢測其sleep_ticks 6 { 7 t->sleep_ticks--; //檢測其sleep_ticks值減1是否為0,等於0則表示 8 if (t->sleep_ticks == 0) //在這個時鐘結束時應該被unblock 9 { 10 thread_unblock(t); //喚醒該程序 11 } 12 } 13 }
blocked_thread_check需要在thread.h裡面宣告
1 /* check the block state */ 2 void blocked_thread_check (struct thread *t,void *aux UNUSED);
至此Project1就完成了,測試結果也在意料之中