Linux 中斷處理淺析

最近在研究異步消息處理, 突然想起linux內核的中斷處理, 里面由始至終都貫穿著”重要的事馬上做, 不重要的事推后做”的異步處理思想. 于是整理一下~



第一階段--獲取中斷號


每個CPU都有響應中斷的能力, 每個CPU響應中斷時都走相同的流程. 這個流程就是內核提供的中斷服務程序.


在進入中斷服務程序時, CPU已經自動禁止了本CPU上的中斷響應, 因為CPU不能假定中斷服務程序是可重入的.


中斷處理程序的第一步要做兩件事情:


1. 將中斷號壓入棧中; (不同中斷號的中斷對應不同的中斷服務程序入口)
2. 將當前寄存器信息壓入棧中; (以便中斷退出時恢復)


顯然, 這兩步都是不可重入的(如果在保存寄存器值時被中斷了, 那么另外的操作很可能就把寄存器給改寫了, 現場將無法恢復), 所以前面說到的CPU進入中斷服務程序時要自動禁止中斷.


棧上的信息被作為函數參數, 調用do_IRQ函數.


第二階段--中斷串行化


進入do_IRQ函數, 第一步進行中斷的串行化處理, 將多個CPU同時產生的某一中斷進行串行化. 其方法是如果當前中斷處于”執行”狀態(表明另一個CPU正在處理相同的中斷), 則重新設置它的”觸發”標記, 然后立即返回. 正在處理同一中斷的那個CPU完成一次處理后, 會再次檢查”觸發”標記, 如果設置, 則再次觸發處理過程.

于是, 中斷的處理是一個循環過程, 每次循環調用handle_IRQ_event來處理中斷.


第三階段--關中斷條件下的中斷處理


進入handle_IRQ_event函數, 調用對應的內核或內核模塊通過request_irq函數注冊的中斷處理函數.


注冊的中斷處理函數有個中斷開關屬性, 一般情況下, 中斷處理函數總是在關中斷的情況下進行的. 而調用request_irq注冊中斷處理函數時也可以設置該中斷處理函數在開中斷的情況下進行, 這種情況比較少見, 因為這要求中斷處理代碼必須是可重入的. (另外, 這里如果開中斷, 正在處理的這個中斷一般也是會被阻塞的. 因為正在處理某個中斷的時候, 硬件中斷控制器上的這個中斷并未被ack, 硬件不會發起下一次相同的中斷.)


中斷處理函數的過程可能會很長, 如果整個過程都在關中斷的情況下進行, 那么后續的中斷將被阻塞很長的時間.


于是, 有了soft_irq. 把不可重入的一部分在中斷處理程序中(關中斷)去完成, 然后調用raise_softirq設置一個軟中斷, 中斷處理程序結束. 后面的工作將放在soft_irq里面去做.


第四階段--開中斷條件下的軟中斷


上一階段循環調用完當前所有被觸發的中斷處理函數后, do_softirq函數被調用, 開始處理軟件中斷.


在軟中斷機制中, 為每個CPU維護了一個若干位的掩碼集, 每位掩碼代表一個中斷號. 在上一階段的中斷處理函數中, 調用raise_softirq設置了對應的軟中斷, 到了這里, 軟中斷對應的處理函數就會被調用(處理函數由open_softirq函數來注冊).


可以看出, 軟中斷與中斷的模型很類似, 每個CPU有一組中斷號, 中斷有其對應的優先級, 每個CPU處理屬于自己的中斷. 最大的不同是開中斷與關中斷.


于是, 一個中斷處理過程被分成了兩部分, 第一部分在中斷處理函數里面關中斷的進行, 第二部分在軟中斷處理函數里面開中斷的進行.


由于這一步是在開中斷條件下進行的,這里還可能發生新的中斷(中斷嵌套),然后新中斷對應的中斷處理又將開始一個新的第一階段~第三階段。在新的這個第三階段中,可能又會觸發新的軟中斷。但是這個新的中斷處理過程并不會進入第四階段,而是當它發現自己是嵌套的中斷時,完成第三階段之后就會退出了。也就是說,只有第一層中斷處理過程會進入第四階段,嵌套發生的中斷處理過程只執行到第三階段。


然而嵌套發生的中斷處理過程也可能會觸發軟中斷,所以第一層中斷處理過程在第四階段需要是一個循環的過程,需要循環處理嵌套發生的所有軟中斷。為什么要這樣做呢?因為這樣可以按軟中斷觸發的順序來執行這些軟中斷,否則后來的軟中斷可能就會先執行完成了。


極端情況下,嵌套發生的軟中斷可能非常多,全部處理完可能需要很長的時間,于是內核會在處理完一定數量的軟中斷后,將剩下未處理的軟中斷推給一個叫ksoftirqd的內核線程來處理,然后結束本次中斷處理過程。


第五階段--開中斷條件下的tasklet


實際上, 軟中斷很少直接被使用. 而第二部分開中斷情況下的進行的處理過程一般是由tasklet機制來完成的.


tasklet是由軟中斷引出的, 內核定義了兩個軟中斷掩碼HI_SOFTIRQ和TASKLET_SOFTIRQ(兩者優先級不同), 這兩個掩碼對應的軟中斷處理函數作為入口, 進入tasklet處理過程.


于是, 在第三階段的中斷處理函數中, 完成關中斷的部分后, 然后調用tasklet_schedule/tasklet_hi_schedule標記一個tasklet, 然后中斷處理程序結束. 后面的工作由HI_SOFTIRQ/TASKLET_SOFTIRQ對應的軟中斷處理程序去處理被標記的tasklet(每個tasklet在其初始化時都設置了處理函數).


看上去, tasklet只不過是在softirq的基礎上多了一層調用, 其作用是什么呢? 前面說過, softirq是與CPU相對應的, 每個CPU處理自己的softirq. 這些softirq的處理函數需要設計為可重入的, 因為它們可能在多個CPU上同時運行. 而tasklet則是在多個CPU間被串行化執行的, 其處理函數不必考慮可重入的事情.


然而, softirq畢竟還是要比tasklet少繞點彎路, 所以少數實時性要求相對較高的處理過程還是在精心設計之后, 直接使用softirq了. 比如: 時鐘中斷處理過程, 網絡發送/接收處理過程.


結尾階段


CPU接收到中斷以后, 以歷以上五個階段, 中斷處理完成. 最后需要恢復第一階段中被保存在棧上的寄存器信息. 中斷處理結束.


關于調度


上面的流程中, 還隱含了一個問題, 整個處理過程是持續占有CPU的(除了開中斷情況下可能被新的中斷打斷以外). 并且, 中斷處理的這幾個階段中, 程序不能夠讓出CPU!


這是由內核的設計決定的, 中斷服務程序沒有自己的task結構(即操作系統教科書上說的進程控制塊), 所以它不能被內核調度. 通常說一個進程讓出CPU, 在之后如果滿足某種條件, 內核會通過它的task結構找到它, 并調度其運行.


這里可能存在兩方面的問題:


1. 連續的低優先的中斷可能持續占有CPU, 而高優先的某些進程則無法獲得CPU;
2. 中斷處理的這幾個階段中不能調用可能導致睡眠的函數(包括分配內存);


對于第一個問題, 較新的linux內核增加了ksoftirqd內核線程, 如果持續處理的softirq超過一定數量, 則結束中斷處理過程, 然后喚醒ksoftirqd, 讓它來繼續處理. 雖然softirq可能被推后到ksoftirqd內核線程去處理, 但是還是不能在softirq處理過程中睡眠, 因為不能保證softirq一定在ksoftirqd內核線程中被處理.


據說在montavista(一種嵌入式實時linux)中, 將內核的中斷機制做了修改. (某些中斷的)中斷處理過程被賦予了task結構, 能夠被內核調度. 解決了上述兩個問題. (montavista的目標是實時性, 這樣的做法犧牲了一定的整體性能.)


工作隊列


linux基線版本的內核在解決上述問題上, 提供了workqueue機制.


定義一個work結構(包含了處理函數), 然后在上述的中斷處理的幾個階段的某一步中調用schedule_work函數, work便被添加到workqueue中, 等待處理.


工作隊列有著自己的處理線程, 這些work被推遲到這些線程中去處理. 處理過程只可能發生在這些工作線程中, 所以這里可以睡眠.


內核默認啟動了一個工作隊列, 對應一組工作線程events/n(n代表處理器編號, 這樣的線程有n個). 驅動程序可以直接向這個工作隊列添加任務. 某些驅動程序還可能會創建并使用屬于自己的工作隊列.

轉載于:https://www.cnblogs.com/probemark/p/5947236.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/256236.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/256236.shtml
英文地址,請注明出處:http://en.pswp.cn/news/256236.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C#中泛型的相關知識點總結

一、概念 1.1 泛型 泛型是什么? 書本告訴我們泛型是通過通過參數化類型的方法在同一份代碼上對多種數據類型進行調用。也即是說,如果同一個代碼需要使用不同的數據類型的話就可以定義一個泛型的類或者方法。 泛型的優點是什么? 1.通過使用…

用scikit-learn研究局部線性嵌入(LLE)

1. scikit-learn流形學習庫概述 在scikit-learn中,流形學習庫在sklearn.manifold包中。里面實現的流形學習算法有: 1)多維尺度變換MDS算法:這個對應的類是MDS。MDS算法希望在降維時在高維里樣本之間的歐式距離關系在低維可以得到保…

判斷字符串中是否為數字的三種方法

//1用JAVA自帶的函數 public static boolean isNumeric(String str){for (int i str.length();--i>0;){ if (!Character.isDigit(str.charAt(i))){return false;}}return true;}//2用正則表達式 public static boolean isNumeric(String str){ Pattern pattern Pattern.…

【圖像處理】——Python+opencv實現圖像的hu不變矩特征提取(含原理、推導過程、應用、代碼等)

目錄 轉載本文請注明詳細地址本文介紹了矩和圖像矩的含義本文介紹了不變矩的計算、應用本文介紹了如何計算圖像相似度一、思維導圖 二、普通矩的定義 1、零階矩 2、二階矩

MSSQL-to-MySQL v5.3, 從MSSQL遷移到mySQL的最佳工具

將現有的MSSQL數據庫遷移到MySQL數據庫,嘗試了很多種工具 MySQL Workbench / MSSQL to MySQL Export / DB Converter / openDBcopy 都有這樣那樣的問題。 最后發現就MSSQL-to-MySQL好一點,能夠保證所有表和數據成功遷移,并且字段類型都比較正確。 只是對…

C#窗體應用程序崩潰解決方法總結

一、內存不足 內存是最常見的導致程序崩毀的原因,常用解決方式有如下幾種。 算法中聲明的占內存較大的全局變量或類中聲明的私有變量在循環或運行結束后需進行釋放,手動設置Dispose(),然后GC.Collect()。對一些重復調用的類避免多次實例化。…

【學習的心得】——“快餐”的效率與“挖掘”的重要性

從事Python圖像處理和機器學習方向已經有大半年了,現在作為還是一個研究生的我,大部分時間都是在完成老師給的課題任務,但是這幾個月下來我感覺和老師的意見有點分歧了甚至跟一些同學都有所意見分歧了。 Python雖然是最近幾年火起來的語言&a…

Unity3D Input按鍵系統

默認輸入軸: Horizontal 和 Vertical被映射到w, a, s, d鍵和方向鍵 Fire1, Fire2, Fire3被分別映射到Ctrl,Option(Alt)和Command鍵 Mouse X 和 Mouse Y被映射到鼠標移動增量 Window Shake X 和 Window Shake Y 被映射到窗口的移動…

iOS app 企業內部發布及HTTPS服務器配置

轉自: http://www.cnblogs.com/cocoajin/p/4082488.html iOS企業內部發布及HTTPS服務器配置 一:所需的條件 1. 蘋果開發者證書,企業版 299$ 版本 2. ssl 證書,即https使用的服務器證書 3. web服務器,支持https 4. 一個域名&#x…

Pytorch超簡單安裝教程

安裝Pytorch 1.1 安裝Annaconda 安裝Pytorch首先需要安裝Annaconda,按照教程,安裝了Annaconda5.2.0的版本。 路徑 記住安裝路徑即可,其余均選默認。 1.2 安裝Pytorch 第一步,打開Anaconda Prompt 。然后輸入 conda create -n…

【圖像處理】——紋理特征提取方法(LBP局部二值模式和GLCM灰度共生矩陣)

紋理特征提取方法 局部二值模式(LBP) (結構法) Local binary patterns 原理 將像素點的鄰域八個像素點與中心像素點值進行比較,大于設為1,小于設為0,這樣就會得到一個鄰域值為1和0的格子,將這八個值按照一定的規則排列成一個二進制的數字,并且轉換為十進制作為中心像…

44. 源代碼解讀-RocketMQ-架構

1. 前言 1.1 github源代碼 https://github.com/apache/rocketmq 1.2 github其他客戶端,比如c,php https://github.com/apache/rocketmq-externals 1.3 運行進程 RocketMQ分成兩個進程運行 NamesrvBrokerNamesrv,命名服務,主要負責Broker狀態管…

jquery檢測瀏覽器類型

使用jquery如下代碼檢測瀏覽器版本時:出問題,在檢測IE瀏覽器,如果版本是IE11時,會出現 $.browser.msie的返回值是false,$.browser.mozilla的返回值是true,即把IE11檢測成火狐了 結局辦法 判斷IE瀏覽器用 …

【leetcode?python】 9. Palindrome Number

#回文數#Method1:將整數轉置和原數比較,一樣就是回文數;負數不是回文數#這里反轉整數時不需要考慮溢出,但不代表如果是C/C等語言也不需要考慮class Solution(object): def isPalindrome(self, x): """ …

Pytorch基礎(一) —— tensorboard的應用

一、簡介與安裝方法 1.1 概念 Tensorboard 是 TensorFlow 的一個工具包,用于展示網絡圖、張量的指標變化和分布情況,如權重W、偏置B、卷積層數、全連接層數等參數,使用該工具可以方便觀察神經網絡訓練過程,分析學習模型訓練的效…

“RuntimeWarning: overflow encountered in ubyte_scalars像素加減運算溢出異常”原因以及解決辦法

轉載本文請注明詳細地址本文介紹了像素點相加減溢出的原因與解決方法 目錄 原因: 解決方法: 原因: 這個問題一般是會出現在圖像處理像素的加減中,出現的原因是因為圖片的像素一般是八位即最大值是256,最小值是0&…

二叉樹重建

一、已知先序遍歷和中序遍歷。求后序遍歷。http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId944 依據先序遍歷和中序遍歷還原二叉樹的主要思想: 1、先序遍歷序列的第一個元素必然是根節點,能夠由此獲取二叉樹的根節點。 2、依據根節點&…

asyn4j -- java 異步方法調用框架

asyn4j 是一個java異步方法調用框架,基于消費者與生產者模式。包括了異步方法執行,異步回調執行,異步工作緩存模塊.支持Spring. 讓我們寫異步方法不再寫很多的相關多線程代碼。用asyn4j輕松搞定異步方法調用.提高程序的響應能力.轉載于:https…

Pytorch基礎(二)—— Transforms詳解

一、概念 Transforms是pytorch的圖像處理工具包,是torchvision模塊下的一個一個類的集合,可以對圖像或數據進行格式變換,裁剪,縮放,旋轉等,在進行深度學習項目時用途很廣泛。下面對Transforms內的常見類的…