歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> Linux內核

Linux內核中的同步與任務調度

摘要:同步概念在多線程和多進程編程中已經被诠釋得很全面。同步方法對於用戶應用程序來講使用簡單,無需過多考慮它們產生的原因(唯一的原因就是線程或進程並發)。但是內核中的同步處理就要復雜得多,開發者必須知道內核中任務得調度方式,才能有效的控制內核中的同步。所以本文就將結合內核任務調度,分析內核中的同步措施,並結合一個實例講述內核中如何綜合運用各種同步方法。

並發,競爭與同步:
並發,競爭和同步的概念,我們假定大家都有所了解,本文不再重申。我們討論的重點放在什麼情況會發生內核並發上?如何防止內核並發?有那些同步方法?以及這些方法的行為有何特點和如何使用它們?

下面一段描述了上述幾個概念之間的大致關系,這種關系在內核中同樣適用。

對於多線程程序的開發者來說,往往會利用多線程訪問共享數據,避免繁瑣的進程間通訊。但是多線程對共享數據的並發訪問有可能產生競爭,使得數據處於不一致狀態,所以需要一些同步方法來保護共享數據。多線程的並發執行是由於線程被搶占式的調度——一個線程在對共享數據訪問期間(還未完成)被調度程序中斷,將另一個線程投入運行——如果新被調度的線程也要對這個共享數據進行訪問,就將產生競爭。為了避免競爭產生,需要使線程串行地訪問共享數據 ,也就是說訪問需要同步——在一方對數據訪問結束後,另一方才能對同一數據進行訪問。

內核並發原因
上述情況是用戶空間並發產生的普遍原因,對於內核來說並發原因也大致類似,但是情況要更多樣,也更復雜。

對於單處理機器來說情況相對簡單一些。在2.6版本內核之前,Linux內核是非搶占式的——在內核任務沒有執行完之前不能被打斷,這樣的話,內核中程序並發執行的情況很少,准確地講只有兩種可能:

一 :中斷發生 ,因為中斷執行是異步的,而且中斷是在非搶占式內核中打斷當前運行內核代碼的唯一方法,所以中斷顯然是可以和其它內核代碼並發執行的。因此如果中斷操作和被中斷的那內核代碼都訪問同樣的內核數據,那麼就會發生競爭。

二 :睡眠和再調度, 處於進程上下文(下面會進行講述)的內核任務可以睡眠(睡眠意味放棄處理器),這時調度程序會調度其它程序去執行(首先執行調度任務隊列中的內核任務,然後執行軟中斷等,最後從運行隊列中選擇一個高優先級的用戶進程運行)。顯然這裡也會造成內核並發訪問,當睡眠的內核任務和新投入運行的內核任務訪問同一共享數據時,就發生了競爭。請看參考資料 1

2.6版本的內核變成了搶占式內核——內核可能在任何時刻搶占正在運行的內核代碼。所以內核中發生並發執行的情況大大增加了。內核搶占成為了內核程序並發的又一種可能,所以在開發搶占式內核代碼時需要時刻警惕搶占產生的競爭。

單處理器上的並發是邏輯上的偽並發,事實上所謂並發的內核程序其實是交錯地占用處理器。真正的並發執行程序,必須依靠對稱多處理器。但無論是邏輯上的並發還是真正的並發,都會產生競爭,而且它們的處理也是相同的。但是對於對稱多處理器來說,由於兩個或多個處理器可以在同一時刻執行代碼,所以會不可避免地給內核帶來並發可能,如果分別在不同處理器上執行的內核代碼同時訪問同一共享數據,競爭就產生了。因此,不用說對稱多處理是內核並發的又一種可能。 請看參考資料2

可以看到隨著Linux內核不斷演化,在內核對系統支持更加全面,對任務調度更加高效的同時,也給內核帶來了更多的並發可能,更容易引起競爭。上面提到的各種並發情況在內核中都必須得到有效的處理,才能確保內核有高穩定性。

無論是中斷產生的並發或是睡眠引起的並發,還是內核搶占引起的並發,要想在內核開發中很好地避免,就必須從本質上了解它們的並發原因。只有在掌握內核任務的調度機制後,才可以真正的達到對並發可能的預測,進而能夠采取合適的同步方法——鎖——來避免並發。

下面我們就對任務調度進行討論。對比並發產生的條件,分析內核中的調度發生的條件。

內核中的任務調度:
我們這裡所說的任務調度不同於常說的進程調度。進程調度是:內核中的調度程序在進程運行隊列中選擇合適的(優先級高的)進程執行。而我們所說的內核任務調度指的是,內核中的任務獲得執行機會。對於內核並發來說,內核任務之間的關系尤為重要。

首先我們來看看內核有那些任務,各有什麼特點。

內核任務種類
硬中斷操作:

硬中斷是指那些由處理器以外的外設產生的中斷,這些中斷被處理器接收後交給內核中的中斷處理程序處理。要注意的是:第一,硬中斷是異步產生的,中斷發生後立刻得到處理,也就是說中斷操作可以搶占內核中正在運行的代碼。這點非常重要。第二,中斷操作是發生在中斷上下文中的(所謂中斷上下文指的是和任何進程無關的上下文環境)。中斷上下文中,不可以使用進程相關的資源,也不能夠進行調度。請看參考資料2

 

軟中斷操作:

軟中斷是Linux中為了執行一些硬中斷操作來不及完成的任務而采取的推後執行機制。因為硬中斷操作期間的中斷會被拋棄,所以硬中斷是在不安全時間運行的。不安全時間應該盡量短,所以采用軟中斷來執行大部分任務,它會把硬中斷做不完的耗時任務推後到安全時間執行(軟中斷期間不會丟棄中斷信號)。

軟中斷不象硬中斷那樣時隨時都能夠被執行,籠統來講軟中斷會在內核處理任務處理完畢後返回用戶級程序前得到處理機會。具體的講有三個時刻它將被執行(do_softirq()):硬件中斷操作完成後;內核調度程序中;系統調用返回時,(另外的內核線程ksoftirqd周期執行軟中斷)。需要說明的是軟中斷的執行也處於中斷上下文中,所以中斷上下文對它的限制是和硬中斷一樣的。

Tasklet 和bottom half

Tasklet和bottom half都是建立在軟中斷之上的兩種延遲機制,其中具體不同在於軟中斷是靜態分配的,而且同類軟中斷可以並發地在幾個CPU上運行;Tasklet可以動態分配,並且不同種類的Tasklets可以並發地在幾個CPU上運行,但同類的tasklets 不可以;bottom half只能靜態分配,實質上下半部分是一個不能與其它下半部分並發執行的高優先級tasklet,即使它們類型不同,而且在不同CPU上運行。

Copyright © Linux教程網 All Rights Reserved