<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 牛人業(yè)話 > linux中斷處理原理分析

          linux中斷處理原理分析

          作者: 時(shí)間:2016-12-09 來源:網(wǎng)絡(luò) 收藏

            Tasklet作為一種新機(jī)制,顯然可以承擔(dān)更多的優(yōu)點(diǎn)。正好這時(shí)候SMP越來越火了,因此又在tasklet中加入了SMP機(jī)制,保證同種只能在一個(gè)cpu上執(zhí)行。在軟時(shí)代,顯然沒有這種考慮。因此同一種可以在兩個(gè)cpu上同時(shí)執(zhí)行,很可能造成沖突。

          本文引用地址:http://www.ex-cimer.com/article/201612/341381.htm

            Linux中斷下半部處理有三種方式:軟中斷、tasklet、工作隊(duì)列。

            曾經(jīng)有人問我為什么要分這幾種,該怎么用。當(dāng)時(shí)用書上的東西蒙混了過去,但是自己明白自己實(shí)際上是不懂的。最近有時(shí)間了,于是試著整理一下的中斷處理機(jī)制,目的是起碼從原理上能夠說得通。

            一、最簡單的中斷機(jī)制

            最簡單的中斷機(jī)制就是像芯片手冊上講的那樣,在中斷向量表中填入跳轉(zhuǎn)到對應(yīng)處理函數(shù)的指令,然后在處理函數(shù)中實(shí)現(xiàn)需要的功能。類似下圖:  

           

            這種方式在原來的單片機(jī)課程中常常用到,一些簡單的單片機(jī)系統(tǒng)也是這樣用。

            它的好處很明顯,簡單,直接。

            二、下半部

            中斷處理函數(shù)所作的第一件事情是什么?答案是屏蔽中斷(或者是什么都不做,因?yàn)槌3J侨绻磺宄齀F位,就等于屏蔽中斷了),當(dāng)然只屏蔽同一種中斷。之所以要屏蔽中斷,是因?yàn)樾碌闹袛鄷俅握{(diào)用中斷處理函數(shù),導(dǎo)致原來中斷處理現(xiàn)場的破壞。即,破壞了 interrupt context。

            隨著系統(tǒng)的不斷復(fù)雜,中斷處理函數(shù)要做的事情也越來越多,多到都來不及接收新的中斷了。于是發(fā)生了中斷丟失,這顯然不行,于是產(chǎn)生了新的機(jī)制:分離中斷接收與中斷處理過程。中斷接收在屏蔽中斷的情況下完成;中斷處理在時(shí)能中斷的情況下完成,這部分被稱為中斷下半部。

              

           

            從上圖中看,只看int0的處理。Func0為中斷接收函數(shù)。中斷只能簡單的觸發(fā)func0,而func0則能做更多的事情,它與funcA之間可以使用隊(duì)列等緩存機(jī)制。當(dāng)又有中斷發(fā)生時(shí),func0被觸發(fā),然后發(fā)送一個(gè)中斷請求到緩存隊(duì)列,然后讓funcA去處理。

            由于func0做的事情是很簡單的,所以不會影響int0的再次接收。而且在func0返回時(shí)就會使能int0,因此funcA執(zhí)行時(shí)間再長也不會影響int0的接收。

            三、軟中斷

            下面看看中斷處理。作為一個(gè)操作系統(tǒng)顯然不能任由每個(gè)中斷都各自為政,統(tǒng)一管理是必須的。

            我們不可中斷部分的共同部分放在函數(shù)do_IRQ中,需要添加中斷處理函數(shù)時(shí),通過request_irq實(shí)現(xiàn)。下半部放在do_softirq中,也就是軟中斷,通過open_softirq添加對應(yīng)的處理函數(shù)。

              

           

            四、tasklet

            舊事物跟不上歷史的發(fā)展時(shí),總會有新事物出現(xiàn)。

            隨著中斷數(shù)的不停增加,軟中斷不夠用了,于是下半部又做了進(jìn)化。

            軟中斷用輪詢的方式處理。假如正好是最后一種中斷,則必須循環(huán)完所有的中斷類型,才能最終執(zhí)行對應(yīng)的處理函數(shù)。顯然當(dāng)年開發(fā)人員為了保證輪詢的效率,于是限制中斷個(gè)數(shù)為32個(gè)。

            為了提高中斷處理數(shù)量,順道改進(jìn)處理效率,于是產(chǎn)生了tasklet機(jī)制。

            Tasklet采用無差別的隊(duì)列機(jī)制,有中斷時(shí)才執(zhí)行,免去了循環(huán)查表之苦。

              

           

            總結(jié)下tasklet的優(yōu)點(diǎn):

            (1)無類型數(shù)量限制;

            (2)效率高,無需循環(huán)查表;

            (3)支持SMP機(jī)制;

            五、工作隊(duì)列

            前面的機(jī)制不論如何折騰,有一點(diǎn)是不會變的。它們都在中斷上下文中。什么意思?說明它們不可掛起。而且由于是串行執(zhí)行,因此只要有一個(gè)處理時(shí)間較長,則會導(dǎo)致其他中斷響應(yīng)的延遲。為了完成這些不可能完成的任務(wù),于是出現(xiàn)了工作隊(duì)列。工作隊(duì)列說白了就是一組內(nèi)核線程,作為中斷守護(hù)線程來使用。多個(gè)中斷可以放在一個(gè)線程中,也可以每個(gè)中斷分配一個(gè)線程。

            工作隊(duì)列對線程作了封裝,使用起來更方便。

            因?yàn)楣ぷ麝?duì)列是線程,所以我們可以使用所有可以在線程中使用的方法。

              

           

            Tasklet其實(shí)也不一定是在中斷上下文中執(zhí)行,它也有可能在線程中執(zhí)行。

            假如中斷數(shù)量很多,而且這些中斷都是自啟動型的(中斷處理函數(shù)會導(dǎo)致新的中斷產(chǎn)生),則有可能cpu一直在這里執(zhí)行中斷處理函數(shù),會導(dǎo)致用戶進(jìn)程永遠(yuǎn)得不到調(diào)度時(shí)間。

            為了避免這種情況,發(fā)現(xiàn)中斷數(shù)量過多時(shí),會把多余的中斷處理放到一個(gè)單獨(dú)的線程中去做,就是ksoftirqd線程。這樣又保證了中斷不多時(shí)的響應(yīng)速度,又保證了中斷過多時(shí)不會把用戶進(jìn)程餓死。

            問題是我們不能保證我們的tasklet或軟中斷處理函數(shù)一定會在線程中執(zhí)行,所以還是不能使用進(jìn)程才能用的一些方法,如放棄調(diào)度、長延時(shí)等。

            六、使用方式總結(jié)

            Request_irq掛的中斷函數(shù)要盡量簡單,只做必須在屏蔽中斷情況下要做的事情。

            中斷的其他部分都在下半部中完成。

            軟中斷的使用原則很簡單,永遠(yuǎn)不用。它甚至都不算是一種正是的中斷處理機(jī)制,而只是tasklet的實(shí)現(xiàn)基礎(chǔ)。

            工作隊(duì)列也要少用,如果不是必須要用到線程才能用的某些機(jī)制,就不要使用工作隊(duì)列。其實(shí)對于中斷來說,只是對中斷進(jìn)行簡單的處理,大部分工作是在驅(qū)動程序中完成的。所以有什么必要非使用工作隊(duì)列呢?

            除了上述情況,就要使用tasklet。

            即使是下半部,也只是作必須在中斷中要做的事情,如保存數(shù)據(jù)等,其他都交給驅(qū)動程序去做。



          關(guān)鍵詞: linux 中斷

          評論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();