改善Linux內(nèi)核實(shí)時(shí)性方法的研究與實(shí)現(xiàn)
0 引言
本文引用地址:http://2s4d.com/article/261723.htm由于Linux具有功能強(qiáng)大、源代碼開放、支持多種硬件平臺(tái)、模塊化的設(shè)計(jì)方案以及豐富的開發(fā)工具支持等特點(diǎn),在實(shí)際系統(tǒng)中,得到了廣泛的應(yīng)用。但由于其最初的設(shè)計(jì)目標(biāo)為通用分時(shí)操作系統(tǒng),對(duì)于實(shí)時(shí)系統(tǒng)而言,Linux仍然存在核心不可搶占、關(guān)中斷、時(shí)鐘粒度粗糙等缺陷。為了使其應(yīng)用于嵌入式系統(tǒng),實(shí)時(shí)控制等領(lǐng)域,越來(lái)越多的廠家和研究機(jī)構(gòu)熱衷于改善其實(shí)時(shí)性,構(gòu)建基于Linux的實(shí)時(shí)操作系統(tǒng)。
在Linux 2.4和以前的版本,內(nèi)核是不可搶占的,也就是說,如果當(dāng)前任務(wù)運(yùn)行在內(nèi)核態(tài),即使當(dāng)前有更緊急的任務(wù)需要運(yùn)行,當(dāng)前任務(wù)也不能被搶占。因此那個(gè)緊急任務(wù)必須等到當(dāng)前任務(wù)執(zhí)行完內(nèi)核態(tài)的操作返回用戶態(tài)后或當(dāng)前任務(wù)因需要等待某些條件滿足而主動(dòng)讓出CPU才能被考慮執(zhí)行,這很明顯嚴(yán)重影響搶占延遲。在 Linux 2.6中,內(nèi)核已經(jīng)可以搶占,因而實(shí)時(shí)性得到了加強(qiáng)。但是內(nèi)核中仍有大量的不可搶占區(qū)域, 如由自旋鎖spinlock保護(hù)的臨界區(qū),以及一些失效搶占的臨界區(qū)。另一個(gè)影響Linux實(shí)時(shí)性的因素就是關(guān)中斷,同步操作中使用的關(guān)中斷指令增大了中斷延遲,這樣很多由中斷驅(qū)動(dòng)的實(shí)時(shí)任務(wù)得不到及時(shí)的執(zhí)行,系統(tǒng)的實(shí)時(shí)性能得不到保障。因此提高Linux的可搶占性,改進(jìn)其中斷機(jī)制有利于改善內(nèi)核的實(shí)時(shí)性。
本文詳細(xì)闡述了這些措施的原理并基于標(biāo)準(zhǔn)Linux2.6內(nèi)核加以實(shí)現(xiàn),最后通過測(cè)試,驗(yàn)證了此改進(jìn)方法的效果。
1 中斷線程化
1.1 Linux中斷對(duì)內(nèi)核實(shí)時(shí)性的影響
中斷處理是由內(nèi)核執(zhí)行的最敏感的任務(wù)之一,當(dāng)內(nèi)核正打算去做一些別的事情時(shí),中斷隨時(shí)會(huì)到來(lái),中斷當(dāng)前的任務(wù)進(jìn)而執(zhí)行中斷處理程序。因此內(nèi)核的目標(biāo)就是讓中斷盡可能快的處理完,盡其所能把更多的處理工作向后推遲。為此Linux把中斷的處理分成上半部分和下半部分。上半部分立即執(zhí)行,下半部分將喚醒相應(yīng)的和中斷處理相關(guān)的進(jìn)程稍后執(zhí)行。雖然這種機(jī)制使得中斷處理變得更加高效和易于維護(hù),但是對(duì)于系統(tǒng)如果有嚴(yán)重的網(wǎng)絡(luò)負(fù)載或其他I/O負(fù)載時(shí),中斷將非常頻繁,內(nèi)核當(dāng)前的實(shí)時(shí)任務(wù)會(huì)被不停中斷,這對(duì)于Linux的實(shí)時(shí)應(yīng)用來(lái)說是不可接受的。
另外,Linux為了使內(nèi)核同步而采用了關(guān)中斷,在內(nèi)核的關(guān)中斷區(qū)域,中斷是被屏蔽的。即使此時(shí)有通過中斷驅(qū)動(dòng)的實(shí)時(shí)任務(wù)也得不到響應(yīng),增加了實(shí)時(shí)任務(wù)的中斷延遲。實(shí)時(shí)化后的Linux中,自旋鎖被互斥鎖取代,而中斷處理代碼中大量運(yùn)用了自旋鎖,中斷處理代碼就有可能因?yàn)榈貌坏芥i而需要被掛到該鎖的等待隊(duì)列上去。但是只有可調(diào)度的進(jìn)程才可這么做,如果中斷處理代碼仍然使用原來(lái)的自旋鎖,那么互斥鎖取代自旋鎖改進(jìn)內(nèi)核實(shí)時(shí)性的努力將大打折扣。
線程化的中斷管理可以有效的解決這些問題。中斷線程化后,中斷將作為內(nèi)核線程運(yùn)行而且賦予不同的實(shí)時(shí)優(yōu)先級(jí),實(shí)時(shí)任務(wù)可以有比中斷線程更高的優(yōu)先級(jí),這樣,實(shí)時(shí)任務(wù)就可以作為最高優(yōu)先級(jí)的執(zhí)行單元來(lái)運(yùn)行,即使在嚴(yán)重負(fù)載下仍有實(shí)時(shí)性保證。另一方面中斷處理線程也可以因?yàn)樵趦?nèi)核同步中得不到鎖而掛載到鎖的等待隊(duì)列中。很多關(guān)中斷就不必真正的禁止硬件中斷了,而是禁止內(nèi)核進(jìn)程搶占,這樣就可以減小中斷延遲。
1.2 設(shè)計(jì)與實(shí)現(xiàn)
Linux提供了kthread_create創(chuàng)建內(nèi)核線程,該內(nèi)核線程在內(nèi)核空間執(zhí)行,因此在調(diào)度時(shí)沒有用戶空間和內(nèi)核空間切換,使得其運(yùn)行更為高效。中斷線程化要做的工作是創(chuàng)建中斷線程以及中斷的處理。中斷線程是在系統(tǒng)初始化或者調(diào)用requestirq函數(shù)時(shí)通過 kthread_create函數(shù)創(chuàng)建的。其過程等同于如下功能代碼:
對(duì)于非緊急中斷,kthread_create為其創(chuàng)建一個(gè)內(nèi)核線程,并且根據(jù)中斷號(hào)為其賦予一定的靜態(tài)實(shí)時(shí)優(yōu)先級(jí)和設(shè)置其調(diào)度策略。中斷到來(lái)后,內(nèi)核并不是直接進(jìn)入中斷服務(wù)函數(shù),而是通過設(shè)置調(diào)度標(biāo)志告知內(nèi)核,內(nèi)核調(diào)度程序比較該中斷線程的優(yōu)先級(jí)和當(dāng)前運(yùn)行任務(wù)的優(yōu)先級(jí),作出調(diào)度決策。因此當(dāng)前正在運(yùn)行的高優(yōu)先級(jí)的實(shí)時(shí)任務(wù)不會(huì)受中斷的太大的影響,保證了實(shí)時(shí)任務(wù)運(yùn)行的可靠性和準(zhǔn)確性,中斷線程將會(huì)其他合適的時(shí)刻被調(diào)度執(zhí)行,而且 Linux2.6內(nèi)核的O(1)調(diào)度機(jī)制也不會(huì)因?yàn)閮?nèi)核線程數(shù)的增加在調(diào)度時(shí)間上額外增加調(diào)度開銷。對(duì)于緊急的中斷(比如時(shí)鐘中斷),內(nèi)核保持原來(lái)的中斷處理方式,而不為其創(chuàng)建中斷線程,這樣保證了緊急中斷的快速響應(yīng)。
2 自旋鎖改互斥鎖
2.1 新的自旋鎖設(shè)計(jì)
為了同步不同內(nèi)核控制路徑對(duì)共享資源的訪問,標(biāo)準(zhǔn)Linux內(nèi)核提供了很多內(nèi)核同步原語(yǔ),其中自旋鎖spinlock是一種廣泛應(yīng)用于可搶占內(nèi)核,SMP環(huán)境下的內(nèi)核同步機(jī)制。在spinlock的保持期間,內(nèi)核是搶占失效的。被自旋鎖保護(hù)的區(qū)域稱為臨界區(qū),內(nèi)核中大量使用了spinlock,存在大量的內(nèi)核不可搶占的臨界區(qū),這將嚴(yán)重影響系統(tǒng)的實(shí)時(shí)性,我們使用新的實(shí)時(shí)互斥鎖rt_mutex來(lái)替換spinlock,即讓臨界區(qū)內(nèi)內(nèi)核可搶占。其結(jié)構(gòu)體如下:
類型raw_spinlock_t就是原來(lái)的spinlock_t。新的自旋鎖還是使用spinlock_t來(lái)標(biāo)記。在結(jié)構(gòu)struct rt_mutex中的wait_list字段就是優(yōu)先級(jí)化的等待隊(duì)列。Owner字段為擁有該鎖的進(jìn)程的環(huán)境信息。mutex比spinlock優(yōu)越的地方有這么幾點(diǎn):(1)當(dāng)遇到一個(gè)鎖住的臨界區(qū)時(shí),任務(wù)被掛起到鎖的優(yōu)先級(jí)等待隊(duì)列wait_list中,臨界區(qū)解鎖時(shí)等待任務(wù)被激活。(2)內(nèi)核將一個(gè)鎖住的臨界區(qū)和一個(gè)任務(wù)關(guān)聯(lián),當(dāng)獲得互斥鎖時(shí)將任務(wù)的標(biāo)識(shí)存入鎖中。(3)臨界區(qū)可以在被保護(hù)的同時(shí)不禁止搶占。(4)在被鎖住的臨界區(qū)中可以實(shí)現(xiàn)優(yōu)先級(jí)繼承。
2.2 實(shí)時(shí)互斥鎖的操作
并不是所有內(nèi)核中的自旋鎖都可以轉(zhuǎn)換為互斥鎖的,一些底層的臨界區(qū)必須是不可搶占的,所以必須由不可搶占的自旋鎖保護(hù),比如:保護(hù)硬件寄存器的鎖、調(diào)度器的運(yùn)行隊(duì)列鎖、和其它不可搶占自旋鎖嵌套的鎖。實(shí)時(shí)內(nèi)核中,不可搶占的自旋鎖與RT互斥鎖共存,不可搶占的自旋鎖被重命為 raw_spinlock_t。spin_lock函數(shù)利用gcc的內(nèi)嵌技術(shù)根據(jù)鎖的類型通過預(yù)處理選擇具體的鎖執(zhí)行函數(shù)。預(yù)處理器使用 __builtin_types_compatible函數(shù),由宏TYPE_EQUAL調(diào)用:
linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)linux相關(guān)文章:linux教程
評(píng)論