新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > 改善Linux內核實時性方法的研究與實現(xiàn)

改善Linux內核實時性方法的研究與實現(xiàn)

作者: 時間:2009-03-04 來源:網絡 收藏
0 引言
由于具有功能強大、源代碼開放、支持多種硬件平臺、模塊化的設計方案以及豐富的開發(fā)工具支持等特點,在實際系統(tǒng)中,得到了廣泛的應用。但由于其最初的設計目標為通用分時操作系統(tǒng),對于系統(tǒng)而言,仍然存在核心不可搶占、關中斷、時鐘粒度
粗糙等缺陷。為了使其應用于嵌入式系統(tǒng),控制等領域,越來越多的廠家和機構熱衷于,構建基于的實時操作系統(tǒng)。
在Linux 2.4和以前的版本,是不可搶占的,也就是說,如果當前任務運行在態(tài),即使當前有更緊急的任務需要運行,當前任務也不能被搶占。因此那個緊急任務必須等到當前任務執(zhí)行完態(tài)的操作返回用戶態(tài)后或當前任務因需要等待某些條件滿足而主動讓出CPU才能被考慮執(zhí)行,這很明顯嚴重影響搶占延遲。在Linux 2.6中,內核已經可以
搶占,因而得到了加強。但是內核中仍有大量的不可搶占區(qū)域, 如由spinlock保護的臨界區(qū),以及一些失效搶占的臨界區(qū)。另一個影響Linux的因素就是關中斷,同步操作中使用的關中斷指令增大了中斷延遲,這樣很多由中斷驅動的實時任務得不到及時的執(zhí)行,系統(tǒng)的實時性能得不到保障。因此提高Linux的,改進其中斷機制有利于內核的實時性。
本文詳細闡述了這些措施的原理并基于標準Linux2.6內核加以,最后通過測試,驗證了此改進的效果。
1 中斷線程化
1.1 Linux中斷對內核實時性的影響
中斷處理是由內核執(zhí)行的最敏感的任務之一,當內核正打算去做一些別的事情時,中
斷隨時會到來,中斷當前的任務進而執(zhí)行中斷處理程序。因此內核的目標就是讓中斷盡可能快的處理完,盡其所能把更多的處理工作向后推遲。為此Linux把中斷的處理分成上半部分和下半部分。上半部分立即執(zhí)行,下半部分將喚醒相應的和中斷處理相關的進程稍后執(zhí)行。雖然這種機制使得中斷處理變得更加高效和易于維護,但是對于系統(tǒng)如果有嚴重的網絡負載或其他I/O負載時,中斷將非常頻繁,內核當前的實時任務會被不停中斷,這對于Linux的實時應用來說是不可接受的。
另外,Linux為了使內核同步而采用了關中斷,在內核的關中斷區(qū)域,中斷是被屏蔽的。即使此時有通過中斷驅動的實時任務也得不到響應,增加了實時任務的中斷延遲。實時化后的Linux中,取代,而中斷處理代碼中大量運用了,中斷處理代碼就有可能因為得不到鎖而需要被掛到該鎖的等待隊列上去。但是只有可調度的進程才可這么做,如果中斷處理代碼仍然使用原來的自旋鎖,那么取代自旋鎖改進內核實時性的努力將大打折扣。
線程化的中斷管理可以有效的解決這些問題。中斷線程化后,中斷將作為內核線程運行而且賦予不同的實時優(yōu)先級,實時任務可以有比中斷線程更高的優(yōu)先級,這樣,實時任務就可以作為最高優(yōu)先級的執(zhí)行單元來運行,即使在嚴重負載下仍有實時性保證。另一方面中斷處理線程也可以因為在內核同步中得不到鎖而掛載到鎖的等待隊列中。很多關中斷就不必真正的禁止硬件中斷了,而是禁止內核進程搶占,這樣就可以減小中斷延遲。
1.2 設計與
Linux提供了kthread_create創(chuàng)建內核線程,該內核線程在內核空間執(zhí)行,因此在調度時沒有用戶空間和內核空間切換,使得其運行更為高效。中斷線程化要做的工作是創(chuàng)建中斷線程以及中斷的處理。中斷線程是在系統(tǒng)初始化或者調用requestirq函數(shù)時通過kthread_create函數(shù)創(chuàng)建的。其過程等同于如下功能代碼:
for (i = 0; i NR_IRQS; i++) {
irq_desc_t *desc = irq_desc + i;
if (desc->action !(desc->status IRQ_NODELAY))
desc->thread = kthread_create();
}
對于非緊急中斷,kthread_create為其創(chuàng)建一個內核線程,并且根據(jù)中斷號為其賦予一定的靜態(tài)實時優(yōu)先級和設置其調度策略。中斷到來后,內核并不是直接進入中斷服務函數(shù),而是通過設置調度標志告知內核,內核調度程序比較該中斷線程的優(yōu)先級和當前運行任務的優(yōu)先級,作出調度決策。因此當前正在運行的高優(yōu)先級的實時任務不會受中斷的太大的影響,保證了實時任務運行的可靠性和準確性,中斷線程將會其他合適的時刻被調度執(zhí)行,而且Linux2.6內核的O(1)調度機制也不會因為內核線程數(shù)的增加在調度時間上額外增加調度開銷。對于緊急的中斷(比如時鐘中斷),內核保持原來的中斷處理方式,而不為其創(chuàng)建中斷線程,這樣保證了緊急中斷的快速響應。
2 自旋鎖改
2.1 新的自旋鎖設計
為了同步不同內核控制路徑對共享資源的訪問,標準Linux內核提供了很多內核同步原語,其中自旋鎖spinlock是一種廣泛應用于可搶占內核,SMP環(huán)境下的內核同步機制。在spinlock的保持期間,內核是搶占失效的。被自旋鎖保護的區(qū)域稱為臨界區(qū),內核中大量使用了spinlock,存在大量的內核不可搶占的臨界區(qū),這將嚴重影響系統(tǒng)的實時性,我們使用新的實時互斥鎖rt_mutex來替換spinlock,即讓臨界區(qū)內內核可搶占。其結構體如下:
typedef struct {
struct rt_mutex lock;
unsigned int break_lock;
} spinlock_t;
struct rt_mutex {

raw_spinlock_t wait_lock;
struct plist wait_list;
struct thread_info *owner;
……
}
類型raw_spinlock_t就是原來的spinlock_t。新的自旋鎖還是使用spinlock_t來標記。在結構struct rt_mutex中的wait_list字段就是優(yōu)先級化的等待隊列。Owner字段為擁有該鎖的進程的環(huán)境信息。mutex比spinlock優(yōu)越的地方有這么幾點:(1)當遇到一個鎖住的臨界區(qū)時,任務被掛起到鎖的優(yōu)先級等待隊列wait_list中,臨界區(qū)解鎖時等待任務被激活。(2)內核將一個鎖住的臨界區(qū)和一個任務關聯(lián),當獲得互斥鎖時將任務的標識存入鎖中。(3)臨界區(qū)可以在被保護的同時不禁止搶占。(4)在被鎖住的臨界區(qū)中可以優(yōu)先級繼承。
2.2 實時互斥鎖的操作
并不是所有內核中的自旋鎖都可以轉換為互斥鎖的,一些底層的臨界區(qū)必須是不可搶占的,所以必須由不可搶占的自旋鎖保護,比如:保護硬件寄存器的鎖、調度器的運行隊列鎖、和其它不可搶占自旋鎖嵌套的鎖。實時內核中,不可搶占的自旋鎖與RT互斥鎖共存,不可搶占的自旋鎖被重命為raw_spinlock_t。spin_lock函數(shù)利用gcc的內嵌技術根據(jù)鎖的類型通過預處理選擇具體的鎖執(zhí)行函數(shù)。預處理器使用__builtin_types_compatible函數(shù),由宏TYPE_EQUAL調用:
#define TYPE_EQUAL(lock, type)
__builtin_types_compatible_p(typeof(lock), type *)
函數(shù)映射結構PICK_OP是允許兩種鎖共存的機制,PICK_OP在編譯階段將鎖操作轉化為合適的種類(mutex或者spinlock):
#define PICK_OP(type, optype, op, lock)
do {
if (TYPE_EQUAL((lock), type))
_raw_##optype##op((type *)(lock));
else if (TYPE_EQUAL(lock, spinlock_t))
_spin##op((spinlock_t *)(lock));
else __bad_spinlock_type();
} while (0)
#define spin_lock(lock)
PICK_OP(raw_spinlock_t, spin, _lock, lock)
根據(jù)宏處理的結果,如果類型為spinlock_t,將運行函數(shù)_spin_lock,而如果類型為raw_spinlock_t,將運行函數(shù)_raw_spin_lock。對于實時rt_mutex獲取,當前任務由于優(yōu)先級高如果可以搶占該鎖,則把鎖的先前擁有者添加到該鎖的等待隊列中并且在新的鎖擁有者的task_struct中標記等待該鎖的所有任務;而如果不能獲得鎖,則把當前任務放到鎖的優(yōu)先級等待隊列中,直到鎖的擁有者釋放該鎖,喚醒等待隊列中最高優(yōu)先級的任務進入臨界區(qū)。為了防止優(yōu)先級反轉,可以改變鎖的當前擁有者的優(yōu)先級為鎖的等待隊列中任務的最高優(yōu)先級。
實時互斥鎖的應用使得高優(yōu)先級的任務通過搶占鎖可以進入臨界區(qū),這樣內核的不可搶占區(qū)的數(shù)量和范圍都大大縮小,內核有了很大的提高,充分減小了實時高優(yōu)先級任務的搶占延遲。
3 改進后的內核實時性能測試
對Linux進行了實時化改造后,需要對其進行測試來確定系統(tǒng)是否符合實際應用的需要。實時性能測試主要包括測試內核的最大中斷延遲和任務調度時間延遲兩個重要的指標。
中斷延遲反映的是中斷信號發(fā)生到內核對中斷做出響應所需要的時間,通過利用并口的7號中斷,短路并口的9-10腳,其中10腳為中斷引腳,9口為并口數(shù)據(jù)口的高位,往IO口0X378寫8就可以引發(fā)中斷,然后在中斷服務程序里往0x378寫0就會重新拉低中斷引腳電平。用高精度示波器測量這個脈沖的寬度來測得中斷延遲時間。對于賽揚650MHz,內存128M的工控平臺,負載為拷貝CF卡情況下,標準Linux2.6內核最長中斷延遲為240us,而改進后的實時內核最長中斷延遲為16us。
采用開源軟件LMbench3.0測試系統(tǒng)調度延遲時間。測試機器配置為:CPU ,Intel P4 2.8GHz,內存512M,負載情況為拷貝硬盤、訪問網絡。標準Linux2.6內核調度延遲為1038us,而改進后的內核的調度延遲為140us。
可見改進后的內核的最長中斷延遲和調度延遲比標準內核要短很多,內核的實時性能有了很大的提高。
4 結束語
針對標準Linux2.6內核由于中斷關閉時間過長、內核臨界不可搶占區(qū)過大而多,明顯存在實時性能方面的不足,提出了改進其實時性的,實現(xiàn)了實時Linux內核的中斷線程化以及新的內核同步自旋鎖,使其具有更短的中斷延遲和調度延遲。
本文作者的創(chuàng)新點:在標準的Linux2.6可搶占內核上對其中斷處理機制進行線程化改造,大大的減小了中斷響應時間。另外對內核同步機制采用新的自旋鎖使得內核能更加優(yōu)異,改進后的內核可以適用于對Linux內核實時性要求更高的場合。
linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)


評論


相關推薦

技術專區(qū)

關閉