1. 程式人生 > 其它 >pintos作業系統實驗Project1-時鐘

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時,使當前程序進入阻塞狀態,並呼叫其它程序,當睡眠時間結束時喚醒該程序。

到這裡應該思考幾個問題:

  1. 用什麼來記錄使用者呼叫時傳遞的睡眠時間?
  2. 在哪裡對睡眠時間進行什麼操作?
  3. 如何檢測睡眠時間是否結束?

經過教員講解,加之學習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就完成了,測試結果也在意料之中