Linux核心學習筆記三——進程調度

來源:互聯網
上載者:User

進程調度:

       在可運行態進程之間分配有限處理器時間資源的核心子系統。

一 調度策略

1 進程類型

       I/O消耗型進程:大部分時間用來提交I/O請求或是等待I/O請求,經常處於可運行狀態,但已耗用時間短,等待請求過程時處於阻塞狀態。如互動式程式。

       處理器消耗型進程:時間大都用在執行代碼上,除非被搶佔否則一直不停的運行。

       綜合型:既是I/O消耗型又是處理器消耗型。

       調度策略要在:進程響應迅速(回應時間短)和最大系統利用率(高輸送量)之間尋找平衡。

2 調度概念

       優先順序:基於進程價值和對處理器時間需求進行進程分級的調度。

       時間片:表明進程被搶佔前所能持續啟動並執行時間,規定一個預設的時間片。時間片過長導致系統互動性的響應不好,

      程式並行性效果差;時間片太短增大進程切換帶來的處理器耗時。矛盾!

       時間片耗盡進程運行到期,暫時不可運行狀態。直到所有進程時間片都耗盡,重新計算進程時間片。

       Linux發送器提高互動式程式優先順序,提供較長時間片;實現動態調整優先順序和時間片長度機制。

       進程搶佔:Linux系統是搶佔式,始終運行優先順序高的進程。

3 調度演算法

       可執行隊列:runqueue;給定處理器上可執行進程的鏈表,每個處理器一個。每個可執行進程都唯一歸屬於一個可執行隊列。

 

運行隊列是發送器中最基本的資料結構:    

struct runqueue {   spinlock_t lock; /* 保護運行隊列的自旋鎖*/   unsigned long nr_running; /* 可運行任務數目*/   unsigned long nr_switches; /* 環境切換數目*/   unsigned long expired_timestamp; /* 隊列最後被換出時間*/   unsigned long nr_uninterruptible; /* 處於不可中斷睡眠狀態的任務數目*/   unsigned long long timestamp_last_tick; /* 最後一個發送器的節拍*/   struct task_struct *curr; /* 當前運行任務*/   struct task_struct *idle; /* 該處理器的空任務*/   struct mm_struct *prev_mm; /* 最後運行任務的mm_struct結構體*/   struct prio_array *active; /* 活動優先順序隊列*/   atomic_t nr_iowait; /* 等待I/O操作的任務數目*/   ……};

 

 

提供了一組宏來擷取給定CPU的進程執行隊列:  

  #define cpu_rq(cpu)         //返回給定處理器可執行隊列的指標  #define this_rq()        //返回當前處理器的可執行隊列  #define task_rq(p)            //返回給定任務所在的隊列指標

 

 

在操作處理器任務隊列時候要用鎖:

__task_rq_lock……__task_rq_unlock

 

4 schedule

       系統要選定下一個執行的進程通過調用schedule函數完成。

調度時機:

  l  進程狀態轉換的時刻:進程終止、進程睡眠;

  l  當前進程的時間片用完時(current->counter=0);

  l  裝置驅動程式調用;

  l  進程從中斷、異常及系統調用返回到使用者態時;

睡眠和喚醒:

       休眠(被阻塞)的進程處於一個特殊的不可執行狀態。休眠有兩種進程狀態:

    TASK_INTERRUPTIBLE:接收到訊號就被喚醒

    TASK_UNINTERRUPTIBLE:忽略訊號

  兩種狀態進程位於同一個等待隊列上,等待某些事件,不能夠運行。

進程休眠策略:  

//q是我們希望睡眠的等待隊列DECLARE_WAITQUEUE(wait, current); add_wait_queue(q, &wait); //condition 是我們在等待的事件while (!condition){       //將進程狀態設為不可執行休眠狀態 or TASK_UNINTERRUPTIBLE        set_current_state(TASK_INTERRUPTIBLE);       if(signal_pending(current))               //調度進程              schedule(); }//進程被喚醒條件滿足 進程可執行狀態set_current_state(TASK_RUNNING);  //將進程等待隊列中移除remove_wait_queue(q, &wait);

 

 

進程通過執行下面幾個步驟將自己加入到一個等待隊列中:

  1) 調用DECLARE_WAITQUEUE()建立一個等待隊列的項。

 

  2) 調用add_wait_queue()把自己加入到隊列中。該隊列會在進程等待的條件滿足時喚醒它。

    當然我們必須在其他地方撰寫相關代碼,在事件發生時,對等待隊列執行wake_up()操作。

 

  3) 將進程的狀態變更為 TASK_INTERRUPTIBLE或TASK_UNINTERRUPTIBLE。

 

  4) 如果狀態被置為TASK_INTERRUPTIBLE,則訊號喚醒進程。這就是所謂的偽喚醒(喚醒不是因為事件的發生),因此檢查並處理訊號。

 

  5) 檢查條件是否為真;如果是的話,就沒必要休眠了。如果條件不為真,調用schedule()。

 

  6) 當進程被喚醒的時候,它會再次檢查條件是否為真。如果是,它就退出迴圈,如果不是,它再次調用schedule()並一直重複這步操作。

 

  7) 當條件滿足後,進程將自己設定為TASK_RUNNING並調用remove_wait_queue()把自己移出等待隊列。

 

二 搶佔和環境切換

       進程切換schedule函數調用context_switch()函數完成以下工作:

    l  調用定義在<asm/mmu_context.h>中的switch_mm(),該函數負責把虛擬記憶體從上一個進程映射切換到新進程中。

    l  調用定義在<asm/system.h>中的switch_to(),該函數負責從上一個進程的處理器狀態切換到新進程的處理器狀態。

      這包括儲存、恢複棧資訊和寄存器資訊。在前面看到schedule函數調用有很多種情況,完全依靠使用者來調用不能達到

      很好的效果。核心需要判斷什麼時候調用schedule,核心提供了一個need_resched標誌來表明是否需要重新執行一次調度:

    l  當某個進程耗盡它的時間片時,scheduler_tick()就會設定這個標誌;

    l  當一個優先順序高的進程進入可執行狀態的時候,try_to_wake_up()也會設定這個標誌。

  每個進程都包含一個need_resched標誌,這是因為訪問進程描述符內的數值要比訪問一個全域變數快

  (因為current宏速度很快並且描述符通常都在快取中)。

1 使用者搶佔

       核心即將返回使用者空間時候,如果need_resched標誌被設定,會導致schedule函數被調用,此時發生使用者搶佔。

       使用者搶佔在以下情況時產生:

    l  從系統調返回使用者空間。

    l  從中斷處理常式返回使用者空間。

2 核心搶佔

       只要重新調度是安全的,那麼核心就可以在任何時間搶佔正在執行的任務。

什麼時候重新調度才是安全的呢?只要沒有持有鎖,核心就可以進行搶佔。鎖是非搶佔地區的標誌。由於核心是支援SMP的,

所以,如果沒有持有鎖,那麼正在執行的代碼就是可重新匯入的,也就是可以搶佔的。

  為了支援核心搶佔所作的第一處變動就是為每個進程的thread_info引入了preempt_count計數器。該計數器初始值為0,

每當使用鎖的時候數值加1,釋放鎖的時候數值減1。當數值為0的時候,核心就可執行搶佔。從中斷返回核心空間的時候,

核心會檢查need_resched和preempt_count的值。如果need_resched被設定,並且preempt_count為0的話,這說明

有一個更為重要的任務需要執行並且可以安全地搶佔,此時,發送器就會被調用。

核心搶佔會發生在:

  l  當從中斷處理常式正在執行,且返回核心空間之前。

  l  當核心代碼再一次具有可搶佔性的時候。

  l  如果核心中的任務顯式的調用schedule()。

  l  如果核心中的任務阻塞(這同樣也會導致調用schedule())。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.