一、調度的學習方法
1、調度策略(憑什麼選這個進程使用cpu) 2、調度時機(什麼時候) 3、調度步驟(怎樣調度)
二、Linux調度策略(在Linux系統中,每個進程都有自己的調度策略,整個系統的調度策略並不是唯一的):
1、SCHED_NORMAL(SCHED_OTHER) : 普通的分時進程
2、SCHED_FIFO :時間片輪轉的即時進程
3、SCHED_RR :時間片輪轉的即時進程
4、SCHED_BATCH : 批處理進程
5、SCHED_IDLE :只在系統空閑時才能被調度執行的進程
三、調度類(以上5種調度策略又可以分成兩個類)
1、CFS調度類,Completely Fair Scheduler,公平調度類,(在kernel/sched_fair.c中實現),用於以下調度策略:SCHED_NORMAL、SCHED_BATCH、SCHED_IDLE
2、即時調度類(在kernel/sched_rt.c 中實現),用於SCHED_RR和SCHED_FIFO策略
四、調度時機(在Linux中,處理調度的函數是schedule(),所以討論調度時機就是討論schedule函數什麼時候被調用)
1、調度的發生有兩種方式:
(1)主動式:在核心中,進程自己直接調用schedule()。當進程需要等待資源而暫時停止運行時,會把狀態置於掛起(睡眠),並主動請求調度,讓出CPU
eg:
current->state = TASK_INTERRUPTIBLE;
schdule();
(2)被動式(搶佔)
I、使用者搶佔(發生的時候,歸納下都是從核心空間返回到使用者空間):
==從系統調用返回 使用者空間
==從中斷處理常式返回使用者空間
II、核心搶佔:更高優先順序的 進程/線程 可以搶佔正在核心空間啟動並執行低優先順序 進程/線程
==有些特例下不允許核心搶佔的
--核心正進行中斷處理
--核心進行中中斷內容相關的Bottom Half(中斷的底半部)處理。
--進程持有 spinlock自旋鎖、writelock/readlock 讀寫鎖,(如果搶佔可能發生死結)
--核心正在執行發送器 scheduler
==為了保證Linux在以上情況不會被搶佔,搶佔式核心使用了一個變數preempt_count,稱為核心搶佔計數。這一變數被設定在進程的thread_info結構中。每當核心要進入以上幾種狀態時,變數 preempt_count 就加1,指示核心不允許搶佔。每當核心從以上幾種狀態退出時,變數preempt_count就減一,同時進行可搶佔的判斷和調度。(preempt 就是搶佔的意思 )總之,preempt_count >0 搶佔不能發生,preempt_count
== 0 搶佔可以發生
==核心搶佔發生的時候:
--中斷處理常式完成,返回核心空間之前
--當核心代碼再一次具有可搶佔性的時候,如解鎖、時能非強制中斷等。
2、調度標誌,TIF_NEED_RESCHED:該標誌用來表明核心是否需要重新執行一次調度。
(1)當某個進程耗盡它的事件片時,會設定這個標誌
(2)當一個優先順序更高的進程進入可執行狀態時,也會設定這個標誌
五、調度步驟(所謂的調度步驟,實際上就是schedule函數的工作流程)
1、清理當前運行中的進程
2、選擇下一個要啟動並執行進程;(pic_next_task 分析)
3、設定新進程的運行環境
4、進程環境切換