linux中斷系統
❶ linux中斷補充
在系統結構中,CPU工作的模式有兩種,一種是中斷,由各種設備發起;一種是輪詢,由CPU主動發起。
中斷IRQ:
中斷允許讓設備(如鍵盤,串口卡,並口等設備)表明它們需要CPU。一旦CPU接收了中斷請求,CPU就會暫時停止執行正在運行的程序,並且調用一個稱為中斷處理器或中斷服務程序(interrupt service routine)的特定程序。CPU處理完中斷後,就會恢復執行之前被中斷的程序。
中斷分類:
硬中斷+軟中斷
硬中斷:
①非屏蔽中斷:不能被屏蔽,硬體發生的錯誤:內存錯誤,風扇故障,溫度感測器故障等。
②可屏蔽中斷:可被CPU忽略或延遲處理。當緩存控制器的外部針腳被觸發的時候就會產生這種類型的中斷,而中斷屏蔽寄存器就會將這樣的中斷屏蔽掉。我們可以將一個比特位設置為0,來禁用在此針腳觸發的中斷。
軟中斷:
是軟體實現的中斷,也就是程序運行時其他程序對它的中斷;而硬中斷是硬體實現的中斷,是程序運行時設備對它的中斷。
CPU之間的中斷處理(IPI)
處理器間中斷允許一個CPU向系統其他的CPU發送中斷信號,處理器間中斷(IPI)不是通過IRQ線傳輸的,而是作為信號直接放在連接所有CPU本地APIC的匯流排上。
CALL_FUNCTION_VECTOR (向量0xfb)
發往所有的CPU,但不包括發送者,強制這些CPU運行發送者傳遞過來的函數,相應的中斷處理程序叫做call_function_interrupt(),例如,地址存放在群居變數call_data中來傳遞的函數,可能強制其他所有的CPU都停止,也可能強制它們設置內存類型範圍寄存器的內容。通常,這種中斷發往所有的CPU,但通過smp_call_function()執行調用函數的CPU除外。
RESCHEDULE_VECTOR (向量0xfc)
當一個CPU接收這種類型的中斷時,相應的處理程序限定自己來應答中斷,當從中斷返回時,所有的重新調度都自動運行。
INVALIDATE_TLB_VECTOR (向量0xfd)
發往所有的CPU,但不包括發送者,強制它們的轉換後援緩沖器TLB變為無效。相應的處理程序刷新處理器的某些TLB表項。
❷ linux系統中的中斷指令是什麼
什麼是中斷
Linux 內核需要對連接到計算機上的所有硬體設備進行管理,毫無疑問這是它的份內事。如果要管理這些設備,首先得和它們互相通信才行,一般有兩種方案可實現這種功能:
輪詢(polling) 讓內核定期對設備的狀態進行查詢,然後做出相應的處理;中斷(interrupt) 讓硬體在需要的時候向內核發出信號(變內核主動為硬體主動)。
第一種方案會讓內核做不少的無用功,因為輪詢總會周期性的重復執行,大量地耗用 CPU 時間,因此效率及其低下,所以一般都是採用第二種方案 。
對於中斷的理解我們先看一個生活中常見的例子:QQ。第一種情況:你正在工作,然後你的好友突然給你發送了一個窗口抖動,打斷你正在進行的工作。第
二種情況:當然你有時候也會每隔 5 分鍾就去檢查一下 QQ
看有沒有好友找你,雖然這很浪費你的時間。在這里,一次窗口抖動就可以被相當於硬體的中斷,而你就相當於 CPU,你的工作就是 CPU
這在執行的進程。而定時查詢就被相當於 CPU 的輪詢。在這里可以看到:同樣作為 CPU 和硬體溝通的方式,中斷是硬體主動的方式,較輪詢(CPU
主動)更有效些,因為我們都不可能一直無聊到每隔幾分鍾就去查一遍好友列表。
CPU
有大量的工作需要處理,更不會做這些大量無用功。當然這只是一般情況下。好了,這里又有了一個問題,每個硬體設備都中斷,那麼如何區分不同硬體呢?不同設
備同時中斷如何知道哪個中斷是來自硬碟、哪個來自網卡呢?這個很容易,不是每個 QQ 號碼都不相同嗎?同樣的,系統上的每個硬體設備都會被分配一個
IRQ 號,通過這個唯一的 IRQ 號就能區別張三和李四了。
從物理學的角度看,中斷是一種電信號,由硬體設備產生,並直接送入中斷控制器(如
8259A)的輸入引腳上,然後再由中斷控制器向處理器發送相應的信號。處理器一經檢測到該信號,便中斷自己當前正在處理的工作,轉而去處理中斷。此後,
處理器會通知 OS 已經產生中斷。這樣,OS
就可以對這個中斷進行適當的處理。不同的設備對應的中斷不同,而每個中斷都通過一個唯一的數字標識,這些值通常被稱為中斷請求線。
❸ Linux-怎麼理解軟中斷
中斷是系統用來響應硬體設備請求的一種機制,它會打斷進程的正常調度和執行,然後調用內核中的中斷處理程序來響應設備的請求。
你可能要問了,為什麼要有中斷呢?我可以舉個生活中的例子,讓感受一下中斷的魅力。
比如你訂了一份外賣,但是不確定外賣什麼時候送到,也沒有別的方法了解外賣的進度,但是,配送員送外賣是不等人的,到了你這兒沒人取的話,就直接走人了,所以你只能苦苦等著,時不時去門口看看外賣送到沒,而不能幹其他事情。
不過呢,如果在訂外賣的時候,你就跟配送員約定好,讓他送到後給你打個電話,那你就不用苦苦等待了,就可以去忙別的事情,直到電話一響,接電話、取外賣就可以了。
這里的「打電話」,其實就是一個中斷。沒接到電話的時候,你可以做其他的事情;只有接到了電話(也就是發生中斷),你才要進行另一個動作:取外賣。
這個例子你就可以發現, 中斷其實是一種非同步的事件處理機制,可以提高系統的並發處理能力。
由於中斷處理程序會打斷其他進程的運行,所以, 為了減少對正常進程運行調度的影響,中斷處理程序就需要盡可能快地運行。 如果中斷本身要做的事情不多,那麼處理起來也不會有太大問題;但如果中斷要處理的事情很多,中斷服務程序就有可能要運行很長時間。
特別是,中斷處理程序在響應中斷時,還會臨時關閉中斷。這就會導致上一次中斷處理完成之前,其他中斷都不能響應,也就是說中斷有可能會丟失。
那麼還是以取外賣為例。假如你訂了 2 份外賣,一份主食和一份飲料,並且是由 2 個不同的配送員來配送。這次你不用時時等待著,兩份外賣都約定了電話取外賣的方式。但是,問題又來了。
當第一份外賣送到時,配送員給你打了個長長的電話,商量發票的處理方式。與此同時,第二個配送員也到了,也想給你打電話。
但是很明顯,因為電話占線(也就是關閉了中斷響應),第二個配送員的電話是打不通的。所以,第二個配送員很可能試幾次後就走掉了(也就是丟失了一次中斷)。
如果你弄清楚了「取外賣」的模式,那對系統的中斷機制就很容易理解了。事實上,為了解決中斷處理程序執行過長和中斷丟失的問題,Linux 將中斷處理過程分成了兩個階段,也就是 上半部和下半部:
比如說前面取外賣的例子,上半部就是你接聽電話,告訴配送員你已經知道了,其他事兒見面再說,然後電話就可以掛斷了;下半部才是取外賣的動作,以及見面後商量發票處理的動作。
這樣,第一個配送員不會佔用你太多時間,當第二個配送員過來時,照樣能正常打通你的電話。
除了取外賣,我再舉個最常見的網卡接收數據包的例子,讓你更好地理解。
網卡接收到數據包後,會通過 硬體中斷 的方式,通知內核有新的數據到了。這時,內核就應該調用中斷處理程序來響應它。你可以自己先想一下,這種情況下的上半部和下半部分別負責什麼工作呢?
對上半部來說,既然是快速處理,其實就是要把網卡的數據讀到內存中,然後更新一下硬體寄存器的狀態(表示數據已經讀好了),最後再發送一個 軟中斷 信號,通知下半部做進一步的處理。
而下半部被軟中斷信號喚醒後,需要從內存中找到網路數據,再按照網路協議棧,對數據進行逐層解析和處理,直到把它送給應用程序。
所以,這兩個階段你也可以這樣理解:
實際上,上半部會打斷 CPU 正在執行的任務,然後立即執行中斷處理程序。而下半部以內核線程的方式執行,並且每個 CPU 都對應一個軟中斷內核線程,名字為 「ksoftirqd/CPU 編號」,比如說, 0 號 CPU 對應的軟中斷內核線程的名字就是 ksoftirqd/0。
不過要注意的是,軟中斷不只包括了剛剛所講的硬體設備中斷處理程序的下半部,一些內核自定義的事件也屬於軟中斷,比如內核調度和 RCU 鎖(Read-Copy Update 的縮寫,RCU 是 Linux 內核中最常用的鎖之一)等。
不知道你還記不記得,前面提到過的 proc 文件系統。它是一種內核空間和用戶空間進行通信的機制,可以用來查看內核的數據結構,或者用來動態修改內核的配置。其中:
運行下面的命令,查看 /proc/softirqs 文件的內容,你就可以看到各種類型軟中斷在不同 CPU 上的累積運行次數:
在查看 /proc/softirqs 文件內容時,你要特別注意以下這兩點。
第一,要注意軟中斷的類型,也就是這個界面中第一列的內容。從第一列你可以看到,軟中斷包括了 10 個類別,分別對應不同的工作類型。比如 NET_RX 表示網路接收中斷,而 NET_TX 表示網路發送中斷。
第二,要注意同一種軟中斷在不同 CPU 上的分布情況,也就是同一行的內容。正常情況下,同一種中斷在不同 CPU 上的累積次數應該差不多。比如這個界面中,NET_RX 在 CPU0 和 CPU1 上的中斷次數基本是同一個數量級,相差不大。
不過你可能發現,TASKLET 在不同 CPU 上的分布並不均勻。TASKLET 是最常用的軟中斷實現機制,每個 TASKLET 只運行一次就會結束 ,並且只在調用它的函數所在的 CPU 上運行。
因此,使用 TASKLET 特別簡便,當然也會存在一些問題,比如說由於只在一個 CPU 上運行導致的調度不均衡,再比如因為不能在多個 CPU 上並行運行帶來了性能限制。
另外,剛剛提到過,軟中斷實際上是以內核線程的方式運行的,每個 CPU 都對應一個軟中斷內核線程,這個軟中斷內核線程就叫做 ksoftirqd/CPU 編號。那要怎麼查看這些線程的運行狀況呢?
其實用 ps 命令就可以做到,比如執行下面的指令:
注意,這些線程的名字外面都有中括弧,這說明 ps 無法獲取它們的命令行參數(cmline)。一般來說,ps 的輸出中,名字括在中括弧里的,一般都是內核線程。
Linux 中的中斷處理程序分為上半部和下半部:
上半部對應硬體中斷,用來快速處理中斷。
下半部對應軟中斷,用來非同步處理上半部未完成的工作。
Linux 中的軟中斷包括網路收發、定時、調度、RCU 鎖等各種類型,可以通過查看 /proc/softirqs 來觀察軟中斷的運行情況。
❹ Linux中斷 異常 系統調用 中斷上半部 中斷下半部 這些有什麼區別和聯系
中斷分軟中斷跟硬中斷,硬中斷是由硬體從外部觸發,軟中斷由軟體觸發,就像linux系統調用int 80一樣。至於中斷的上下部其實就是因為中斷的處理時間跟它的優先順序不一定成正比,所以一般先處理中斷最重要的部分(上半部),待到不怎麼忙的時候,再來處理比較悠閑的部分(下半部)。就像輸入的時候,拿到鍵盤輸入的是什麼才是最重要的(上半部),顯示字元才是次要的(下半部)。
❺ Linux 系統中的中斷是不是沒有中斷優先順序
關於中斷嵌套:在linux內核里,如果驅動在申請注冊中斷的時候沒有特別的指定,do_irq在做中斷響應的時候,是開啟中斷的,如果在驅動的中斷處理函數正在執行的過程中,出現同一設備的中斷或者不同設備的中斷,這時候新的中斷會被立即處理,還是被pending,等當前中斷處理完成後,再做處理。在2.4和2.6內核里,關於這一塊是否有什麼不同。 一般申請中斷的時候都允許開中斷,即不使用SA_INTERRUPT標志。如果允許共享則加上 SA_SHIRQ,如果可以為內核熵池提供熵值(譬如你寫的驅動是ide之類的驅動),則再加上 SA_SAMPLE_RANDOM標志。這是普通的中斷請求過程。對於這種一般情況,只要發生中斷,就可以搶占內核,即使內核正在執行其他中斷函數。這里有兩點說明:一是因為linux不支持 中斷優先順序,因此任何中斷都可以搶占其他中斷,但是同種類型的中斷(即定義使用同一個 中斷線的中斷)不會發生搶占,他們會在執行本類型中斷的時候依次被調用執行。二是所謂 只要發生中斷,就可以搶占內核這句是有一定限制的,因為當中斷發生的時候系統由中斷門 進入時自動關中斷(對於x86平台就是將eflags寄存器的if位置為0),只有當中斷函數被執行 (handle_IRQ_event)的過程中開中斷之後才能有搶占。 對於同種類型的中斷,由於其使用同樣的idt表項,通過其狀態標志(IRQ_PENDING和 IRQ_INPROGRESS)可以防止同種類型的中斷函數執行(注意:是防止handle_IRQ_event被重入, 而不是防止do_IRQ函數被重入),對於不同的中斷,則可以自由的嵌套。因此,所謂中斷嵌套, 對於不同的中斷是可以自由嵌套的,而對於同種類型的中斷,是不可以嵌套執行的。以下簡單解釋一下如何利用狀態標志來防止同種類型中斷的重入:當某種類型的中斷第一次發生時,首先其idt表項的狀態位上被賦予IRQ_PENDING標志,表示有待處理。 然後將中斷處理函數action置為null,然後由於其狀態沒有IRQ_INPROGRESS標志(第一次),故將其狀態置上IRQ_INPROGRESS並去處IRQ_PENDING標志,同時將action賦予相應的中斷處理函數指針(這里是一個重點,linux很巧妙的用法,隨後說明)。這樣,後面就可以順利執行handle_IRQ_event進行中斷處理,當在handle_IRQ_event中開中斷後,如果有同種類型的中斷發生,則再次進入do_IRQ函數,然後其狀態位上加上IRQ_PENDING標志,但是由於前一次中斷處理中加上的IRQ_INPROGRESS沒有被清除,因此這里無法清除IRQ_PENDING標志,因此action還是為null,這樣就無法再次執行handle_IRQ_event函數。從而退出本次中斷處理,返回上一次的中斷處理函數中,即繼續執行handle_IRQ_event函數。當handle_IRQ_event返回時檢查IRQ_PENDING標志,發現存在這個標志,說明handle_IRQ_event執行過程中被中斷過,存在未處理的同類中斷,因此再次循環執行handle_IRQ_event函數。直到不存在IRQ_PENDING標志為止。2.4和2.6的差別,就我來看,主要是在2.6中一進入do_IRQ,多了一個關閉內核搶占的動作,同時在處理中多了一種對IRQ_PER_CPU類型的中斷的處理,其他沒有什麼太大的改變。這類IRQ_PER_CPU的中斷主要用在smp環境下將中斷綁定在某一個指定的cpu上。例如arch/ppc/syslib/open_pic.c中的openpic_init中初始化ipi中斷的時候。 其實簡單的說,中斷可以嵌套,但是同種類型的中斷是不可以嵌套的,因為在IRQ上發生中斷,在中斷響應的過程中,這個IRQ是屏蔽的,也就是這個IRQ的中斷是不能被發現的。 同時在內核的臨界區內,中斷是被禁止的 關於do_IRQ可能會丟失中斷請求:do_IRQ函數是通過在執行完handle_IRQ_event函數之後判斷status是否被設置了IRQ_PENDING標志來判斷是否還有沒有被處理的同一通道的中斷請求。 但是這種方法只能判斷是否有,而不能知道有多少個未處理的統一通道中斷請求。也就是說,假如在第一個中斷請求執行handle_IRQ_event函數的過程中來了同一通道的兩個或更多中斷請求,而這些中斷不會再來,那麼僅僅通過判斷status是否設置了IRQ_PENDING標志不知道到底有多少個未處理的中斷,handle_IRQ_event只會被再執行一次。這算不算是個bug呢? 不算,只要知道有中斷沒有處理就OK了,知道1個和知道N個,本質上都是一樣的。作為外設,應當能夠處理自己中斷未被處理的情況。不可能丟失的,在每一個中斷描述符的結構體內,都有一個鏈表,鏈表中存放著服務常式序關於中斷中使用的幾個重要概念和關系: 一、基本概念 1. 產生的位置 發生的時刻 時序 中斷 CPU外部 隨機 非同步 異常 CPU正在執行的程序 一條指令終止執行後 同步 2.由中斷或異常執行的代碼不是一個進程,而是一個內核控制路徑,代表中斷發生時正在運行的進程的執行 中斷處理程序與正在運行的程序無關 引起異常處理程序的進程正是異常處理程序運行時的當前進程 二、特點 (2)能以嵌套的方式執行,但是同種類型的中斷不可以嵌套 (3)盡可能地限制臨界區,因為在臨界區中,中斷被禁止 2.大部分異常發生在用戶態,缺頁異常是唯一發生於內核態能觸發的異常 缺頁異常意味著進程切換,因此中斷處理程序從不執行可以導致缺頁的操作 3.中斷處理程序運行於內核態 中斷發生於用戶態時,要把進程的用戶空間堆棧切換到進程的系統空間堆棧,剛切換時,內核堆棧是空的 中斷發生於內核態時, 不需要堆棧空間的切換 三、分類 1.中斷的分類:可屏蔽中斷、不可屏蔽中斷 2.異常的分類: 分類 解決異常的方法 舉例 故障 那條指令會被重新執行 缺頁異常處理程序 陷阱 會從下一條指令開始執行 調試程序