linux核心的調度機制
搶佔式核心與非搶佔式核心
linux搶佔式核心與即時系統的關係
一個好的系統的進程調度機制,要兼顧三種不同的應用的需求:
1互動式應用。這種應用,著重於系統的響應速度,當系統中有大量的進程共存時(多使用者),要保證每個使用者都有可以接受的響應速度,而不感到明顯的延遲。當延遲超過150毫秒時,使用者會明顯地感覺到。
2.批處理應用。批處理的應用往往都是“後台作業”,對響應速度沒有要求,但要考慮到“平均速度”
3.即時應用。這是時間要求最強的,不但要考慮進程執行的平均速度,還要考慮到“即時速度”;不但要考慮響應速度(即從一個事件發生到系統對此作出反應,並開始執行有關程度之間所需的時間),還要考慮有關程式(用記程式)能否在規定時間內執行完。在即時應用中,注重的是對程式執行的“可預測性”。
在設計一個進程調度機制時考慮的問題有:
1.調度的時機:在什麼情況下,什麼時候調度?【在什麼情況下,什麼時候,把現在佔用CPU的進程換下來。主要在什麼位置調用schedule函數】
2. 調度的“政策”policy:根據什麼準則挑選下一個進入啟動並執行進程。【從running的進程隊列中找出一個進程,來佔用CPU,讓它運行】。
3.調度的方式:是”可剝奪“(preemptive)還是“不可剝奪”(nonpreemptive)。【一進程主動讓出CPU,進程在使用者態或是在核心態調用schedule,二是強制剝奪其使用權,在發生中斷或是異常或是系統調用之後,從核心態返回到使用者態的前夕,由核心調用schedule。】
調度的時機:
自願方式
1.在核心裡面,進程可以通過schedule()或是schedule_timeout啟動一次調度。在使用者空間可以使用調用pause()或是sleep(s)也可以。【這是可見的主動讓出的方式。這裡指程式員可以看見,程式員編程時主動地讓出。】
2.當使用者使用open(),read(),write()等N多個涉及到外設的系統調用時,都可能受阻。這時在核心中自願放棄運行是不可見的。【程式員認為是阻塞了,其實就是讓出CPU,進入等待隊列,等一個訊號或是非強制中斷,或是硬體中斷】
不自願方式,即強制地發生在每次從系統調用返回的前夕,以及每次從中斷或是異常處理返回到使用者空間的前夕。注意:返回到使用者空間是關鍵性的。這意味著只有在使用者空間(當CPU在使用者空間運行時)發生的中斷 或是異常才會引起調度。(在核心空間發生的中斷或是異常,不引起調度。linux2.4)
【以上這種方式不自願地方式我們習慣地稱為“非搶佔式核心”也有叫“使用者搶佔”。其實也就只能叫作“半搶佔式核心”或是“有條件搶佔”。這種方式是linux2.4的實現方式。在linux2.6中對此進行了修改。大家習慣地稱linux2.6核心是“搶佔式核心”。】
搶佔式核心
以下是“搶佔式核心”的英文解釋。
Kernel preemption is a method used mainly in monolithic and hybrid kernels where all or most device drivers are run in kernel space, whereby the scheduler is permitted to
forcibly perform a context switch (ie, preemptively schedule; on behalf of a runnable and higher priority process) on a driver or other part of the kernel during its execution,
rather than co-operatively wait for the driver or kernel function (such as a system call) to complete its execution and return control of the processor to the scheduler.
There are two main benefits to this method in monolithic and hybrid kernels, and answer one of the main criticisms of monolithic kernels from microkernel advocates,
which is that;
1 A device driver can enter an infinite loop or other unrecoverable state, crashing the whole system
2 Some drivers and system calls on monolithic kernels are slow to execute, and can't return control of the processor to the scheduler or other program until they complete
execution.
源於:http://en.wikipedia.org/wiki/Kernel_preemption
對“非搶佔式核心”、“搶佔式核心”的認識過程。
當一看到這兩個名詞時,第一感覺就是這是一個不同調度方式的核心。在有一些瞭解之後,發現這種理解有一些問題。“非搶佔式核心”說的含義是:不可搶佔核心態的調度方式。當然這種方式與核心實現有關,但它的重點是講一種什麼樣的調度方式。針對Kernel preemption我們可以翻譯為“核心搶佔調度模式”,或是“搶佔核心調度模式”。
搶佔式核心與半搶佔式核心的不同
Linux2.4隻實現了“有條件搶佔式”的調度。它的缺點在於:當進程在核心態時,調度的時機有局限。就是只能在xxx的前夕。例如:當外部來一中斷,中斷程式過程完後,需要一個使用者進程B對此進行進一步的處理(響應IP包資料)。此時進程A正在使用系統調用進入了核心態。那麼等到A從系統調用返回之際,核心進行調度,B才有可能運行。假設A的系統調用佔用了CPU的時間為T。這個T大於使用者要求的回應時間。那這個系統就不夠即時。
為了提高linux的即時性。在linux2.6中引入了“Kernel preemption”(核心搶佔調度模式)。並很好的解決了這個問題。一句話就是搶佔式核心可以在進程處於核心態時,進行搶佔。
當然搶佔式核心在以下幾種情況下不可搶佔:
1.當核心運行中斷處理常式和例外處理常式時,在linux核心中進程不能搶佔中斷,在中斷常式中不允許進行調度。進程調度函數schedule會對此作出判斷,如果是在中斷中調用,會列印出出錯資訊。
2.當進程在核心態運行臨界區的代碼時,不可搶佔。這些臨界區被自旋鎖spin_lock保護了起來。【但是當進程使用spin_lock時,自己被鎖住並自旋時,這時可以調度。】
3. 核心進行中bottom half(中斷的底半部)處理時,不可搶佔。【不太懂】
4.核心正在執行發送器Scheduler時,不可搶佔。
5.核心正在對每一個CPU“私人”資料結構操作(per CPU date structures)時,不可搶佔。在SMP中,對於Per-cpu資料結構未用spinlocks保護,因為這些資料結構隱含地被保護了。
搶佔式核心什麼時候,什麼位置調用schedule函數?
當中斷髮生,並完成中斷處理時,在返回之前被中斷的進程時,可以根據需要進行調度。
搶佔式核心為每一個進程的task_struct結構引入了preempt_count變數,稱為核心搶佔鎖。每當進程進入以上五種狀態時,preempt_count加1.表示不可搶佔。當退出以上五種狀態時,preempt_count減1. 每次進行搶佔式調度時,先判斷preempt_count與0大小,preempt_count<0,表示可搶佔。preempt_count>0表示不可搶佔。
一系統搶佔式的調度器函數:preempt_schedule;preempt_schedule_irq。它們都是調用schedule來完成調度的。
即時作業系統與搶佔式核心的關係
即時作業系統要求就是對來自外部的請求,要求有及時的處理。及時到什麼程度就是即時作業系統呢?這個沒有一個明確的定義,因為使用者對回應時間的要求各不相同。
我們可以說當在同樣的硬體條件下,Linux2.4的即時性不高,或是不如linux2.6的即時性高。那麼提高系統的即時性的方法有很多,提高CPU速度,增加CPU核。最佳化作業系統等。那麼 linux在提高系統即時性的重要貢獻就是引入了“核心搶佔調度模式”。那麼我們也可以說linux很好的支援了即時性。
參考網文:
1《Linux可搶佔核心的分析》
http://wenku.baidu.com/view/835905768e9951e79b89272f.html
2《Linux之搶佔式核心》
http://www.yuanma.org/data/2008/0508/article_3037.htm
3.linux搶佔式核心的研究與實現
http://www.docin.com/p-74007197.html
4.搶佔式核心與非搶佔式核心的區別
http://hi.baidu.com/zhangkai008/blog/item/eee55d208f420e49ad34de87.html
5.《linux核心情景分析》
註:由於此文大量引用了其它網路文章和一些論文,在此能出處。所以此帖也只能算是轉載。