Linux內核學習-進程調度二

    計算優先級和時間片:進程擁有一個初始的優先級,叫做nice值,該數值變化範圍由-20到+19,默認值爲0,19優先級最低,-20最高,他一開始由用戶指定後就不能修改,所以稱作靜態優先級,動態優先級通過一個關於靜態優先級和進程交互性的函數關係計算而來,這個函數爲effective_prio()函數可以返回一個進程的動態優先級,這個函數以nice值爲基礎,加上-5到+5之間的進程交互性的獎勵或懲罰,得到動態優先級。

      如何判斷一個進程的交互性強不強?最明顯的標準就是通過進程休眠時間的長短,如果一個進程長時間都在休眠,它就是 I/O消耗型的,若一個進程的執行時間比休眠時間長則是處理器消耗型的。Linux紀錄一個用於休眠和用於執行的時間,該值存放在sleep_avg中。它的範圍從0到MAX當進程休眠時,該值會增長,當進程每運行一個節拍時,該值會減短。

      重新計算時間片:以靜態優先級爲基礎(nice值)在一個進程創建的時候,新建的子進程和父進程均分父進程剩餘的時間片,可以防止用戶不斷創建進程來截獲時間片。優先級最低的進程(+19)爲5ms優先級最高的進程(-20)爲800ms,默認優先級(0)爲100ms。

      休眠和喚醒:休眠的進程處於一個特殊的不可執行的狀態,一般進程休眠都是爲了等待一些事件,如I/O文件讀取更多數據,或某個硬件事件,或獲取鍵盤的輸入等,當進程需要休眠時,內核都會把該進程從可執行隊列中移除放入等待隊列,然後調用Schedule()調用其他進程。喚醒則是把進程從等待隊列移到可執行隊列。休眠有兩種狀態:TASK——INTERRUPTIBLE(會接受信號提前喚醒)和TASK _UNINTERRUPTIBLE(會忽略信號)

       負載均衡策略:當處理器之間可執行隊列的負載出現不均衡的狀態,負載平衡程序會進行合理的調度。由kernel/sched.c中函數load_balance()實現。該函數有兩種調用方法(情況)1.在shcedule執行的時候發現當前可執行隊列爲空,會調用一次。

            2.他會被定時器調用,系統空閒時每隔1ms調用一次,或者在其他情況下每隔200ms被調用一次。

        load_balance()的邏輯:首先找到最繁忙的可執行隊列,與當前隊列比較,若進程數目多於25%以上,則從該最繁忙的可執行隊列中抽取進程到當前隊列中來。抽取進程的原則:過期數組-》活動數組-》優先級最高-》滿足:沒有執行,與處理器無關,不在高速緩存等條件-》抽取

        搶佔和上下文切換:(1)上下文切換,就是從一個可執行進程切換到另一個可執行進程,context_switch(),被schedule()調用,完成兩項工作:

                                           1.switch_mm()負責把虛擬內存從上一個進程切換到新進程。

                                           2.switch_to()負責從上一個進程的處理器狀態切換到新進程的處理器狀態。內核通過檢查need_resched標誌來決定是否調用schedule()。                                        (2)搶佔:

                                           1. 用戶搶佔:內核在即將返回用戶空間的時候如果need_resched被設置會導致schedule()被調用,發生搶佔,用戶搶佔發生在系統調用返回用戶空間時和從中斷處理程序返回用戶空間

                                           2.內核搶佔:只要重新調度是安全的,也就是隻要沒有持有鎖內核就可以進行搶佔。是否持有鎖,通過thread_info中的preempt_count計數器來判斷,該值爲0時沒有持有鎖。當中斷返回內核空間時會檢查need_resched和preempt_count,若need_resched被設置,preempt_count爲0時說明需要並且可以搶佔。內核搶佔發生在:(中斷處理程序正在執行返回內核空間前),(內核代碼再一次具有可搶佔性的時候),(如果內核中的任務顯示調用schedule),(內核中人物阻塞的時候)

        實時調度策略:兩種策略,SCHED_FIFO和SCHED_RR。非實時的策略爲SCHED_NORMAL

                                1.SCHED_FIFO先入先出的調度算法,SCHED_FIFO級的進程只要處於可執行狀態就會一直執行,優先級低的或者非實時的進程只能等待其執行完才能繼續執行,只有具有較高SCHED_FIFO或者SCHED_RR任務才能進行搶佔。

                                2. SCHED_RR是帶有時間片分配的SCHED_FIFO,需要耗盡它所分配的時間片纔會讓出處理器。其他與SCHED_FIFO相同。且這兩種算法都是依靠靜態優先級,內核不會爲實時進程計算動態優先級(可以保證實時進程總可以搶佔優先級低的進程)

        軟實時:內核調度進程,盡力使進程在它的限定時間到來前運行,但內核不保證總能滿足這些進程的需求。硬實時則可以滿足任何需求,linux提供了一種軟實時的工作方式。且實時優先級的範圍從0到(MAX_RT_PRIO(默認100)-1),SCHED_NORMAL(非實時,優先級低)共享這一取值空間其nice值-20到+19則對應MAX_RT_PRIO到(MAX_RT_PRIO+40)即100到139.

        一些調度相關的系統調用:1.與調度策略和優先級相關的:設置獲取調度策略sched_setscheduler()和sched_getscheduler(),設置獲取實時進程的實時優先級sched_setparam()和sched_getparam(),對於普通進程nice()可以將給定的進程的靜態優先級增加一個給定的量。

                                            2.與處理器綁定系統調用,sched_setaffinity()和sched_getaffinity()設置和獲取位掩碼。

                                            3.放棄處理器時間:sched_yield()提供一種進程顯式將處理器時間讓給其他等待執行進程的機制。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章