中斷請求級
在設計windows的時候,設計者3將中斷請求劃分為軟體中斷和硬體中斷,並將這些中斷都對映成不同級別的中斷請求級(irql)。同步處理機制很大程度上依賴於中斷請求級。
1.中斷請求(irq)與可程式設計中斷控制器(pic)
中斷請求(irq)一般有兩種,一種是外部中斷,也就是硬體產生的中斷,另一種由軟體指令int n產生的中斷。
pic的中斷向量
irq編號 裝置名稱 用途
iqr0 time 計算機系統計時器
irq1 keyboard 鍵盤
irq2 redirectirq9 與irq9相接,mpu-401 mdi使用該irq
irq3 com2 串列埠裝置
irq4 com1 串列埠裝置
irq5 lpt2 建議音效卡使用該irq
irq6 fdd 軟碟機傳輸控制用
irq7 lpt1 印表機傳輸控制用
irq8 cmos alert 即時時鐘
irq9 redirectirq2 與irq2相接。可設定給其他硬體使用
irq10 reversed 建議保留給網絡卡使用該irq
irq11 reversed 建議保留給agp顯示卡使用
irq12 ps/2mouse 接ps/2滑鼠,若無也可設定給其他硬體使用
irq13 fpu 協處理器用,例如fpu(浮點運算器)
irq14 primaryide 主硬碟傳輸控制用
irq15 sccondaryide 從硬碟傳輸控制用
2.高階可程式設計控制器(apic)
傳統pc一般使用2片intel8259a中斷控制器。然後在x86計算機基本都是用高階可程式設計控制器,即advanced programmable interrupt controller(apic)。
(見末尾處)
3.中斷請求級(irqp)
在apic中,irq的數量被增加到了24個,每個irp有各自的優先級別,正在執行的執行緒隨時可以被中斷打斷,進入到中斷處理程式。當優先順序搞的中斷來臨時,處在優先順序低的中斷處理程式,也會被打斷,
進入到更高階別的中斷處理函式。
windows將中斷的概念進行了擴充套件,提出了乙個中斷請求級(irql)的概念。其中規定了32個中斷,分別是0-2級別為軟體中斷,3-31級別為硬體中斷(這裡包括apic中的24個中斷),其中數字從0-31,
優先級別啄次遞增。
windows將24個irq對映到了從dispatch_level到profile_level之間,不同硬體的中斷處理程式執行在不同的irql級別中。硬體的irql稱為裝置中斷請求級,或者簡稱dirql。windows大部分時間執行在軟體中斷級別中。
當裝置中斷來臨時,作業系統提公升irql至dirql級別,並且執行中斷處理函式。當中斷處理函式結束後,作業系統把irql降到原來的級別。
high_leve 31
power_level 30
ipi_level 29
clock2_level 28
clock1_level 28
profile_level 27
......
dispatch_level 2
apc_level 1
passive_level 0
使用者模式的**執行在最低優先順序的passive_level級別。驅動程式的driverentry函式、派遣函式、adddevice等函式一般都執行在passive_level級別,它們在必要時可以申請進入dispatch_level級別。
windows負責執行緒排程的元件是執行在dispatch_level級別,當前的執行緒執行完時間片後,系統自動從passive_level級別提公升到dispatch_level級別。當執行緒切換完畢後,作業系統又從dispatch_level級別降到passivel級別。
4.執行緒排程與執行緒優先順序
在應用程式的程式設計中,經常會聽到執行緒優先順序的概念。執行緒優先順序和irql是兩個容易混淆的概念。所有應用程式都執行在passive_level級別上,它的優先級別最低,可以被其他irql級別的程式打斷。
執行緒優先順序只針對應用程式而言,只有程式執行在passive_level級別才有意義。
執行緒優先順序是指某執行緒是否有更多的幾號執行在cpu上,執行緒優先順序高的執行緒有更多的機會被核心排程。負責排程執行緒的核心組建執行在dispatch_level級的irql上,這時候所有應用程式的執行緒都停止,等待被排程。
readfile內部建立irp_mj_read,然後這個irp被傳遞到驅動程式的派遣函式中。這時候派遣函式執行於readfile所在的執行緒中,或者說readfile和派遣函式位於同乙個執行緒上下文中。
5.irql的變化
為了更好地理解irql概念,筆者在下面詳細描述了乙個執行緒的執行過長。這個執行緒在執行中,被乙個中斷打斷,並且在中斷服務執行時,被更高階別的中斷打斷,執行緒的執行分為以下幾個階段。
階段1:乙個普通執行緒a正在執行。
階段2:這個時刻有乙個中斷傳送,它的irql為0xd。cpu中斷當前執行的執行緒a,將irql提公升至0xd級別。
階段3:這個時候有乙個更高優先順序的中斷傳送,它的irql是0x1a。這時候cpu將irql提公升至0x1a級別。
階段5:這時候irql為0x1a的中斷結束,於是進入irql為0x18的中斷服務。
階段6:這時候irql為0x18中斷結束,於是進入irql為0xd的中斷服務。
階段7:最後irql為0xd的中斷結束,作業系統恢復執行緒a。
執行緒執行在passive_level級別,這個時候作業系統隨時可能將當前執行緒切換到別的執行緒。但是如果提公升irql到dispatch_level級別,這時候不會出現執行緒的切換。這是一種很常用的通比處理機制,但這種方法只能使用於單cpu的系統。
對於多cpu的系統,需要採用別的同步處理機制。
6.irql與記憶體分頁
在使用分頁記憶體時,可能會導致頁故障。因為分頁記憶體隨時可能從物理記憶體交換到磁碟檔案。讀取不再物理記憶體中的分頁記憶體時,會引發乙個頁故障,從而執行這個異常的處理函式。
異常處理函式會重新將磁碟檔案的內容交換到物理記憶體中。
頁故障允許出現在passive_level級別的程式中,但如果在dispatch_level或者更高階別irql的程式中會帶來系統崩潰。
對於等於或者高於dispatch_level級別的程式不能使用分頁記憶體,必須使用非分頁記憶體。驅動程式的startio例程、dpc例程、中斷服務例程都執行在dispatch_level或者更高的irql。
因此,在這些例程中不能使用分頁記憶體,否則會導致系統崩潰。
7.控制irql提公升與降低
有時候,驅動程式中需要提公升irql級別。在執行一段時間後,再降回原來的irql級別。這樣做的目的一般是基於同步處理的需要。
首先驅動程式需要知道當前狀態是什麼irql級別,可以通過kegetcurrentirql核心函式獲取當前irql級別。
然後驅動程式使用核心函式keraiseirql將irql提高。keraiseirql需要兩個引數,第乙個引數是提公升後的irql級別,第二個引數儲存提公升前的irql級別。
最後,驅動程式在某個時刻需要將irql恢復到以前的irql級別,驅動程式可以呼叫kelowerirql核心函式。
void rasieirql_test(void)
windows中斷請求級(IRQL)
windows是完全按照模組化設計的,那麼它很重要的乙個概念就是 互動 在linux中,沒有所謂的 互動 如果非要對應乙個,那麼互動就是函式 呼叫,而windows的核心卻不是這樣簡單。這也許就是單核心和微核心的區別吧?windows是乙個基本的c s模式的系統,核心裡面也不乏這樣的例 子,到處都是...
windows中斷請求級(IRQL)
windows是完全按照模組化設計的,那麼它很重要的乙個概念就是 互動 在linux中,沒有所謂的 互動 如果非要對應乙個,那麼互動就是函式 呼叫,而windows的核心卻不是這樣簡單。這也許就是單核心和微核心的區別吧?windows是乙個基本的c s模式的系統,核心裡面也不乏這樣的例 子,到處都是...
中斷請求request irq
今天在跟marvell溝通問題的時候,覺得有些地方的 看得不夠仔細,於是細看了一下。發現了幾個請求中斷的函式。request threaded irq,這個函式在核心中有注釋,引數有好多,大概引數有handler,這是要指定的中斷處理函式,thread fn是要在核心執行緒中呼叫的函式,還有申請中斷...