2018-09-08 系統(tǒng)機(jī)制——陷阱分發(fā)

陷阱分發(fā)

? ? 陷阱(trap)指的是這樣一種機(jī)制,當(dāng)異辰栋纾或中斷發(fā)生時(shí)怨绣,處理器捕捉到一個(gè)執(zhí)行線程角溃,并且將控制權(quán)轉(zhuǎn)移到操作系統(tǒng)中某一固定地址處。在Windows中篮撑,處理器會(huì)將控制權(quán)轉(zhuǎn)給陷阱處理器减细。所謂陷阱處理器是指與某個(gè)特定的中斷或異常相關(guān)聯(lián)的函數(shù)。

? ? 中斷是一個(gè)異步事件(可以在任何時(shí)候發(fā)生)赢笨,并且與處理器正在執(zhí)行的任務(wù)毫無(wú)關(guān)系未蝌。中斷主要由I/O設(shè)備、處理器時(shí)鐘或者定時(shí)器產(chǎn)生的茧妒,并且可以被啟用或者禁用萧吠。相反的,異常是一個(gè)同步條件桐筏,它往往是一個(gè)特殊指令執(zhí)行的結(jié)果纸型。內(nèi)核把系統(tǒng)服務(wù)調(diào)用也看作異常(不過(guò)從技術(shù)上講,它們是系統(tǒng)陷阱)。

? ? 當(dāng)硬件異痴纾或者中斷產(chǎn)生時(shí)除破,處理器將在被中斷的線程的內(nèi)核棧中記錄下足夠多的機(jī)器狀態(tài)信息,因而可以回到控制流中的該點(diǎn)處繼續(xù)執(zhí)行琼腔,就好像什么也沒有發(fā)生過(guò)一樣瑰枫。如果該線程在用戶模式下繼續(xù)執(zhí)行,那么Windows就切換到該線程的內(nèi)核模式棧丹莲。然后光坝,Windows在被中斷線程的內(nèi)核棧上創(chuàng)建一個(gè)陷阱幀,并且把線程的執(zhí)行狀態(tài)保存到陷阱幀里圾笨。

? ? 在大多數(shù)情況下教馆,內(nèi)核安裝了前端陷阱處理函數(shù),在內(nèi)核將控制權(quán)轉(zhuǎn)交給與特定陷阱相關(guān)的處理函數(shù)之前或之后擂达,由這些前端陷阱處理函數(shù)來(lái)執(zhí)行一些常規(guī)的陷阱處理任務(wù)土铺。例如,如果陷阱條件是一個(gè)設(shè)備中斷板鬓,則內(nèi)核的硬件中斷陷阱處理器將控制權(quán)交給一個(gè)由設(shè)備驅(qū)動(dòng)程序提供給該中斷設(shè)備的中斷服務(wù)例程悲敷。


中斷分發(fā)

? ? 硬件中斷處理。在Windows所支持的硬件平臺(tái)上俭令,外部I/O中斷進(jìn)入到中斷控制器的一根線上后德。該控制器接著在某一根線上中斷處理器。處理器一旦被中斷抄腔,就會(huì)詢問(wèn)控制器以獲得此中斷請(qǐng)求(IRQ)瓢湃。中斷控制器將該IRQ轉(zhuǎn)譯成一個(gè)中斷號(hào),利用該編號(hào)作為索引赫蛇,在一個(gè)稱為中斷分發(fā)表(IDT)的結(jié)構(gòu)中找到一個(gè)IDT項(xiàng)绵患,并且將控制權(quán)傳遞給恰當(dāng)?shù)闹袛喾职l(fā)例程。每個(gè)處理器都有單獨(dú)的IDT悟耘,所以落蝙,如果合適,不同的處理器可以運(yùn)行不同的ISR暂幼。

? ? x86中斷控制器筏勒。 絕大多數(shù)x86系統(tǒng)或者依賴于i8259A可編程中斷控制器(PIC),或者依賴于i82489高級(jí)可編程中斷控制器(APIC)的某個(gè)變種旺嬉;今天的計(jì)算機(jī)都包含APIC管行。IBM PC體系架構(gòu)額外定義了一個(gè)從PIC,它的中斷按多路復(fù)用的方式鹰服,連接到主PIC的某一根中斷線上病瞳。這樣就提供了總共15根中斷線(主PIC上7根揽咕,從PIC上8根,這8根中斷線通過(guò)主PIC上的第8根中斷線進(jìn)行多路復(fù)用)套菜。APIC工作在多處理器系統(tǒng)上亲善,有256根中斷線。APIC支持一種包含15個(gè)中斷的PIC兼容模式逗柴,并且只將中斷遞交給主處理器蛹头。APIC實(shí)際上由幾個(gè)部件構(gòu)成:一個(gè)接收設(shè)備中斷的I/O APIC、一些本地APIC戏溺,以及一個(gè)與i8259A兼容的中斷控制器渣蜗。

? ? x64中斷控制器。因?yàn)閤64體系架構(gòu)與x86操作系統(tǒng)兼容旷祸,所以x64系統(tǒng)必須提供與x86同樣的中斷控制器耕拷。然而,一個(gè)重要的區(qū)別是托享,Windows的x64版本將無(wú)法運(yùn)行于不具有APIC的系統(tǒng)上骚烧,因?yàn)樗鼈兪褂肁PIC進(jìn)行中斷控制。

? ? IA64中斷控制器闰围。IA64體系機(jī)構(gòu)依賴于精簡(jiǎn)的高級(jí)可編程中斷控制器(SAPIC)赃绊,這是APIC的一個(gè)演化。即使固件中有中斷傳送和負(fù)載均衡的功能羡榴,Windows也不使用碧查,而是采用輪轉(zhuǎn)方式靜態(tài)的將中斷分配給相應(yīng)的處理器。

? ? 軟件中斷請(qǐng)求級(jí)別(IRQL)校仑。雖然中斷控制器已經(jīng)實(shí)現(xiàn)了中斷優(yōu)先級(jí)忠售,但是Windows仍然強(qiáng)制使用它自己的中斷優(yōu)先級(jí)方案,稱為中斷請(qǐng)求級(jí)別(IRQL)迄沫。在x86系統(tǒng)上档痪,內(nèi)核內(nèi)部使用0~31的數(shù)值來(lái)表示IRQL;而在x64和IA64系統(tǒng)上邢滑,內(nèi)核采用0~15的數(shù)值來(lái)表示IRQL。數(shù)值越大愿汰,代表中斷優(yōu)先級(jí)越高困后。每個(gè)處理器的IRQL設(shè)置決定了該處理器可以接收哪些中斷。IRQL也被用來(lái)實(shí)現(xiàn)對(duì)某些內(nèi)核模式數(shù)據(jù)結(jié)構(gòu)的同步訪問(wèn)衬廷。內(nèi)核模式的線程運(yùn)行時(shí)摇予,它通過(guò)調(diào)用KeRaiseIrql或KeLowerIrql直接的提升或降低處理器的IRQL。當(dāng)中斷源的IRQL高于處理器當(dāng)前的級(jí)別吗跋,則從該源處發(fā)生的中斷會(huì)打斷處理器侧戴;如果中斷源的IRQL等于或者低于當(dāng)前級(jí)別宁昭,則這樣的中斷會(huì)被屏蔽,知道有一個(gè)正在執(zhí)行的線程降低IRQL級(jí)別為止酗宋。因?yàn)樵L問(wèn)PIC是一個(gè)相對(duì)比較慢的操作积仗,所以,那些要求訪問(wèn)I/O總線來(lái)改變IRQL的HAL蜕猫,比如PIC和32位ACPI系統(tǒng)的HAL寂曹,它們實(shí)現(xiàn)了一種性能優(yōu)化,稱為延遲IRQL回右。每個(gè)中斷級(jí)別都有特定的目的隆圆,例如,內(nèi)核發(fā)出一個(gè)處理器間的中斷(IPI)翔烁,以請(qǐng)求另一個(gè)處理器執(zhí)行某個(gè)動(dòng)作渺氧,比如調(diào)度一個(gè)特定的線程使其執(zhí)行,或者更新它的地址轉(zhuǎn)譯快查緩沖區(qū)(TLB)的緩存蹬屹。

? ? 將中斷映射到IRQL侣背。IRQL級(jí)別與中斷控制器定義的中斷請(qǐng)求(IRQ)并不相同。在Windows中哩治,一種稱為總線驅(qū)動(dòng)程序的設(shè)備驅(qū)動(dòng)程序用以確定它的總線上出現(xiàn)了哪些設(shè)備秃踩,以及哪些中斷可以分配給每一個(gè)設(shè)備∫捣ぃ總線驅(qū)動(dòng)程序?qū)⑦@些信息匯報(bào)給即插即用管理器憔杨,即插即用管理器在考慮所有其他設(shè)備的可接受的中斷分配方案以后,確定為每個(gè)設(shè)備分配哪個(gè)中斷蒜胖。然后消别,它調(diào)用即插即用中斷仲裁者,由它將中斷映射到對(duì)應(yīng)的IRQL台谢。在非ACPI系統(tǒng)上使用根仲裁者寻狂,而在ACPI兼容的系統(tǒng)上,ACPI HAL有它自己的仲裁者朋沮。

? ? 預(yù)定義的IRQL蛇券。從最高級(jí)別開始,預(yù)定義的IRQL使用情況如下:

? ? ? ? 內(nèi)核僅當(dāng)它在KeBugCheckEx中停止了系統(tǒng)并屏蔽了所有中斷時(shí)樊拓,才會(huì)使用高端級(jí)別的IRQl纠亚。

? ? ? ? 電源失敗級(jí)別最初出現(xiàn)在WindowsNT的原始設(shè)計(jì)文檔中,該文檔指定了系統(tǒng)電源失敗代碼的行為筋夏,但是此IRQL從來(lái)沒有被真正用到過(guò)肯适。

? ? ? ? 處理器間的中斷級(jí)別被用于向另一個(gè)處理器請(qǐng)求執(zhí)行某個(gè)動(dòng)作莲绰,比如更新該處理器的TLB緩存、系統(tǒng)停機(jī)或者系統(tǒng)崩潰硫椰。

? ? ? ? 時(shí)鐘級(jí)別主要用于系統(tǒng)的時(shí)鐘,內(nèi)核利用該終端級(jí)別來(lái)跟蹤日期和時(shí)間,以及為線程測(cè)量或分配CPU時(shí)間。

? ? ? ? 當(dāng)內(nèi)核的性能剖析功能被打開時(shí),系統(tǒng)的實(shí)時(shí)時(shí)鐘就會(huì)用到性能剖析級(jí)別指蚜。當(dāng)內(nèi)核的性能剖析功能被激活時(shí),內(nèi)核的性能剖析陷阱處理器就會(huì)記錄下中斷發(fā)生時(shí)被執(zhí)行代碼的地址牡昆。隨著時(shí)間的推移姚炕,一張地址采樣表會(huì)建立起來(lái)。

? ? ? ? 同步IRQl級(jí)別是內(nèi)核內(nèi)部使用的丢烘,分發(fā)器和調(diào)度器代碼利用該級(jí)別來(lái)保護(hù)對(duì)全局線程調(diào)度代碼和等待/同步代碼的訪問(wèn)柱宦。通常被定義為緊跟在設(shè)備IRQL之后的最高IRQL級(jí)別。

? ? ? ? 設(shè)備IRQL用于對(duì)設(shè)備中斷進(jìn)行優(yōu)先級(jí)區(qū)分播瞳。

? ? ? ? CMCI(可糾正的機(jī)器檢查中斷)級(jí)別用于在下述條件下向操作系統(tǒng)發(fā)出信號(hào):當(dāng)CPU或固件通過(guò)MCE(機(jī)器檢查錯(cuò)誤)接口報(bào)告了一個(gè)雖然嚴(yán)重但是可以糾正的硬件條件或錯(cuò)誤時(shí)掸刊。

? ? ? ? DPC/Dispatch級(jí)別和APC級(jí)別的中斷是由內(nèi)核和設(shè)備驅(qū)動(dòng)程序產(chǎn)生的軟件中斷。

? ? ? ? 最低的IRQL級(jí)別為被動(dòng)級(jí)別赢乓,它實(shí)際上根本不是一個(gè)中斷級(jí)別忧侧,它是普通線程運(yùn)行時(shí)的設(shè)置,此時(shí)所有的中斷都允許發(fā)生牌芋。

? ? 中斷對(duì)象蚓炬。內(nèi)核提供了一種可移植的機(jī)制,使得設(shè)備驅(qū)動(dòng)程序可以為它們的設(shè)備注冊(cè)ISR躺屁,這種機(jī)制就是一個(gè)被稱為中斷對(duì)象的內(nèi)核控制對(duì)象肯夏。中斷對(duì)象中包含了所有“供內(nèi)核將一個(gè)設(shè)備的ISR與一個(gè)特定級(jí)別的中斷關(guān)聯(lián)起來(lái)而需要”的信息,包括該ISR的地址犀暑、該設(shè)備中斷時(shí)所在的IRQL驯击,以及內(nèi)核中與該ISR關(guān)聯(lián)的IDT項(xiàng)。中斷對(duì)象被初始化時(shí)耐亏,少量的匯編語(yǔ)言代碼指令(稱為分發(fā)代碼)將被從中斷處理模板KiInterruptTemplate中復(fù)制過(guò)來(lái)徊都,保存在該對(duì)象中。當(dāng)中斷發(fā)生時(shí)广辰,這些代碼將被執(zhí)行暇矫。在x64 Windows系統(tǒng)上,內(nèi)核優(yōu)化了中斷分發(fā)過(guò)程择吊,其做法是袱耽,使用一些特殊的例程,通過(guò)忽略一些不必要的功能來(lái)節(jié)省處理器的指令開銷干发。比如,針對(duì)性能中斷或性能剖析中斷史翘,使用KiInterruptDispatchLBControl處理器枉长,它支持現(xiàn)代處理器所提供的最后分支控制MSR冀续。另一個(gè)內(nèi)核中斷處理器是KiFloatingDispatch,它用于那些要求保存浮點(diǎn)狀態(tài)的中斷必峰。浮點(diǎn)分發(fā)例程僅在32位系統(tǒng)上被支持洪唐。中斷對(duì)象的ISR的地址保存在ServiceRoutine域中(正如在!idt的輸出中所顯示的):中斷發(fā)生時(shí),實(shí)際執(zhí)行的中斷代碼被存放在該中斷對(duì)象末尾的DiapatchCode數(shù)組中吼蚁。這里存儲(chǔ)的中斷代碼編寫如下:首先在棧中建立起陷阱幀凭需,然后調(diào)用在DispatchAddress域中存儲(chǔ)的函數(shù),并且將指向該中斷對(duì)象的指針傳遞給它肝匆。


Windows和實(shí)時(shí)處理過(guò)程

? ? 因?yàn)閃indows并不以任何一種可控的方式對(duì)設(shè)備IRQ進(jìn)行優(yōu)先處理粒蜈,并且用戶應(yīng)用程序只能在處理器的IRQL為被動(dòng)級(jí)別的時(shí)候執(zhí)行,所以旗国,Windows往往不適合用作實(shí)時(shí)操作系統(tǒng)枯怖。盡管如此,有一些第三方廠商為Windows提供了實(shí)時(shí)內(nèi)核能曾。這些廠商使用的辦法是度硝,將實(shí)時(shí)內(nèi)核嵌在一個(gè)自定義的HAL中,并且將Windows當(dāng)做實(shí)時(shí)操作系統(tǒng)中的一個(gè)任務(wù)來(lái)運(yùn)行寿冕。

? ? 將一個(gè)ISR與某個(gè)特定級(jí)別的中斷關(guān)聯(lián)起來(lái)蕊程,這一操作稱為連接中斷對(duì)象,而將一個(gè)ISR與一個(gè)IDT項(xiàng)斷開關(guān)聯(lián)驼唱,則稱為斷開中斷對(duì)象藻茂。這些操作是通過(guò)調(diào)用內(nèi)核函數(shù)IoConnectInterruprEx和IoDisconnectInterruprEx來(lái)完成的,正是這兩個(gè)操作曙蒸,使得設(shè)備驅(qū)動(dòng)程序可以在加載到系統(tǒng)中的時(shí)候“打開”一個(gè)ISR捌治,而如果驅(qū)動(dòng)程序被卸載,則可以“關(guān)閉”該ISR纽窟。

? ? 使用中斷對(duì)象注冊(cè)ISR肖油,可以避免設(shè)備驅(qū)動(dòng)程序直接操縱中斷硬件,也可以不必知道任何有關(guān)IDT的細(xì)節(jié)臂港。這一內(nèi)核特性有助于創(chuàng)建可移植的設(shè)備驅(qū)動(dòng)程序森枪,因?yàn)樗沟瞄_發(fā)人員無(wú)需使用匯編語(yǔ)言來(lái)編碼,也無(wú)須在設(shè)備驅(qū)動(dòng)程序中反映處理器的差異审孽。

? ? 如果共享同一中斷的多個(gè)設(shè)備同時(shí)請(qǐng)求服務(wù)县袱,那么,有些設(shè)備佑力,由于其ISR尚未被服務(wù)到式散,一旦中斷分發(fā)器降低了IRQL,它們將再次中斷系統(tǒng)打颤。只有當(dāng)所有想要使用同一中斷的設(shè)備驅(qū)動(dòng)程序向內(nèi)核表示它們可以共享該中斷時(shí)暴拄,這種鏈?zhǔn)浇Y(jié)構(gòu)才被允許漓滔;如果它們未能向內(nèi)核做出這種表態(tài),則即插即用管理器會(huì)重新組織它們的中斷分配方案乖篷,以確保尊重每一個(gè)設(shè)備的共享需求响驴。


基于線的中斷與基于消息信號(hào)的中斷

? ? 共享的中斷通常是高中斷延遲的來(lái)源,也可能引起穩(wěn)定性問(wèn)題撕蔼。它們往往并不是期望的行為豁鲤,而是一臺(tái)計(jì)算機(jī)中因?yàn)槲锢碇袛嗑€數(shù)量有限而導(dǎo)致的副作用。通過(guò)IRQ線來(lái)產(chǎn)生中斷的其他問(wèn)題還有鲸沮,不正確地管理IRQ信號(hào)可能會(huì)導(dǎo)致機(jī)器上發(fā)生中斷風(fēng)暴或者其他種類的死鎖琳骡,因?yàn)橹挥挟?dāng)ISR確認(rèn)了IRQ信號(hào)以后才會(huì)驅(qū)動(dòng)該信號(hào)“高”或“低”。如果由于出現(xiàn)錯(cuò)誤诉探,而導(dǎo)致這兩者都沒有發(fā)生日熬,那么系統(tǒng)可能永久地處于一種被破壞的狀態(tài),更進(jìn)一步中斷可能被屏蔽肾胯,或兩者兼而有之竖席。最后,在多處理器環(huán)境中基于線的中斷也會(huì)帶來(lái)更差的可伸縮性敬肚。

? ? 所有這些問(wèn)題的一個(gè)解決方案是毕荐,在PCI22標(biāo)準(zhǔn)中率先引入的一種新的中斷機(jī)制,稱為基于消息信號(hào)的中斷艳馒。盡管這仍然是該標(biāo)準(zhǔn)的一個(gè)可選組件憎亚,在客戶機(jī)器上很少能找得到,但是弄慰,越來(lái)越多的服務(wù)器和工作站實(shí)現(xiàn)了MSI支持第美,并且所有最新的Windows版本完全支持MSI。在MSI模型中陆爽,一個(gè)設(shè)備通過(guò)往一個(gè)特定的內(nèi)存地址寫數(shù)據(jù)的做法什往,來(lái)向它的驅(qū)動(dòng)程序遞交消息。這一寫操作會(huì)引發(fā)一個(gè)中斷慌闭,然后Windows調(diào)用ISR别威,把消息的內(nèi)容和該消息被遞交的地址傳遞給ISR。設(shè)備也可以遞交多個(gè)消息(可多達(dá)32)到該內(nèi)存地址上驴剔,根據(jù)事件來(lái)遞交不同的載荷部分省古。

? ? 因?yàn)檫@一通信建立在內(nèi)存值的基礎(chǔ)上,并且丧失,因?yàn)閮?nèi)容隨著中斷一起被遞交豺妓,所以,對(duì)IRQ線的需求不再必要,而且科侈,驅(qū)動(dòng)程序ISR也不必再向設(shè)備查詢與該中斷有關(guān)的數(shù)據(jù)载佳,從而降低了延遲。

? ? 最后臀栈,MSI模型有一個(gè)擴(kuò)展,稱為MSI-X挠乳,它是在PCI 3.0中引入的权薯,增加了對(duì)32位消息的支持,允許最多2048個(gè)(而不僅僅32個(gè))不同的消息睡扬,更重要的是盟蚣,每個(gè)MSI載荷可以使用不同的地址(可以動(dòng)態(tài)決定)。這使得MSI載荷可以寫到不同的物理地址范圍中卖怜,這些地址范圍分別屬于不同的處理器屎开,或者不同的目標(biāo)處理器集合,而這可以有效地支持NUMA架構(gòu)的中斷遞交马靠,將中斷發(fā)送給相應(yīng)的發(fā)起了設(shè)備請(qǐng)求的那個(gè)處理器奄抽。通過(guò)在中斷完成過(guò)程中監(jiān)視負(fù)載和最近的NUMA節(jié)點(diǎn),可以改進(jìn)中斷的延遲和可伸縮性甩鳄。


中斷親和性和優(yōu)先級(jí)

? ? 在既支持ACPI又包含APIC的系統(tǒng)上逞度,Windows允許驅(qū)動(dòng)程序開發(fā)人員和管理員在一定程度上控制處理器親和性(選擇一個(gè)處理器或一組處理器允許接收相應(yīng)的中斷)和親和性策略(如何選擇處理器,以及在一個(gè)組中選擇哪些處理器)妙啃。更進(jìn)一步档泽,它支持一種基于IRQL選擇的中斷優(yōu)先級(jí)機(jī)制。

? ? Windows不是一個(gè)實(shí)時(shí)操作系統(tǒng)揖赴,同樣的馆匿,這些IRQ優(yōu)先級(jí)只是給系統(tǒng)的提示,它們僅僅控制了與中斷相關(guān)聯(lián)的IRQL燥滑,而沒有提供除Windows的IRQL優(yōu)先級(jí)方案外的額外優(yōu)先級(jí)渐北。因?yàn)镮RQ優(yōu)先級(jí)也被存儲(chǔ)在注冊(cè)表中,所以突倍,對(duì)于那些沒有充分利用此特性的驅(qū)動(dòng)程序腔稀,若它們要求更低的延遲,管理員可以盡管設(shè)置羽历。

? ? 軟件中斷焊虏。雖然大多數(shù)中斷是硬件產(chǎn)生的,但是秕磷,Windows內(nèi)核也為了各種各樣的任務(wù)而產(chǎn)生軟件中斷诵闭,這樣的任務(wù)包括:激發(fā)線程分發(fā),并非時(shí)間緊急的中斷處理,處理定時(shí)器到期疏尿,在特定線程的環(huán)境中異步地執(zhí)行一個(gè)過(guò)程瘟芝,支持異步I/O操作。

? ? 分發(fā)或者延遲過(guò)程調(diào)用(DPC)中斷褥琐。當(dāng)線程不能繼續(xù)往下執(zhí)行時(shí)锌俱,比如它已經(jīng)終止或者主動(dòng)進(jìn)入等待狀態(tài),內(nèi)核就會(huì)直接調(diào)用分發(fā)器敌呈,從而立即導(dǎo)致環(huán)境切換贸宏。然而,有時(shí)候磕洪,內(nèi)核檢測(cè)到它已經(jīng)深入到許多層代碼中吭练,這時(shí)應(yīng)該進(jìn)行重新調(diào)度。這種情況下析显,內(nèi)核請(qǐng)求分發(fā)操作鲫咽,但將它推遲到完成當(dāng)前的行為以后再進(jìn)行。使用DPC軟件中斷是實(shí)現(xiàn)這種延遲的一種便捷途徑谷异。

? ? 內(nèi)核在需要對(duì)共享的內(nèi)核數(shù)據(jù)結(jié)構(gòu)的訪問(wèn)進(jìn)行同步時(shí)分尸,總是將處理器的IRQL提升到DPC/Dispatch或更高級(jí)別。這禁止了另外的軟件中斷和線程分發(fā)動(dòng)作晰绎。當(dāng)內(nèi)核檢測(cè)到應(yīng)該進(jìn)行線程分發(fā)時(shí)寓落,它會(huì)請(qǐng)求一個(gè)DPC/Dispatch級(jí)別的中斷;但是荞下,因?yàn)镮RQL是在此級(jí)別或更高級(jí)別上伶选,所以處理器將保留住該中斷。利用軟件中斷來(lái)激活線程分發(fā)器尖昏,這是一種將分發(fā)過(guò)程推遲到條件合適時(shí)才進(jìn)行的方法仰税,然而,Windows也使用軟件中斷來(lái)推遲其他類型的處理過(guò)程抽诉。

? ? 除了線程分發(fā)之外陨簇,內(nèi)核也在此IRQL上處理延遲的過(guò)程調(diào)用(DPC)。DPC是完成某項(xiàng)系統(tǒng)任務(wù)的函數(shù)——這一系統(tǒng)任務(wù)不像當(dāng)前任務(wù)那樣時(shí)間緊迫迹淌。這些函數(shù)之所以被稱為延遲的河绽,是因?yàn)樗鼈兛赡懿粫?huì)立即執(zhí)行。

? ? DPC賦予了操作系統(tǒng)這樣一種能力:產(chǎn)生一個(gè)中斷并且在內(nèi)核模式下執(zhí)行一個(gè)系統(tǒng)函數(shù)唉窃。內(nèi)核利用DPC來(lái)處理器定時(shí)器到期(并解除那些正在等待定時(shí)器的線程)耙饰,以及在一個(gè)線程的時(shí)限到期后重新調(diào)度處理器。

? ? DPC是通過(guò)DPC對(duì)象來(lái)表示的纹份,DPC對(duì)象是一種內(nèi)核控制對(duì)象苟跪,它對(duì)于用戶模式程序是不可見的廷痘,但是對(duì)于設(shè)備驅(qū)動(dòng)程序和其他的系統(tǒng)代碼則是可見的。DPC對(duì)象所包含的最重要的信息是件已,內(nèi)核處理該DPC中斷時(shí)將要調(diào)用的那個(gè)系統(tǒng)函數(shù)的地址笋额。正在等待執(zhí)行的DPC例程被存儲(chǔ)在由內(nèi)核管理的隊(duì)列中,每個(gè)處理器都有一個(gè)這樣的隊(duì)列篷扩,稱為DPC隊(duì)列兄猩。要請(qǐng)求一個(gè)DPC,系統(tǒng)代碼需要調(diào)用內(nèi)核來(lái)初始化一個(gè)DPC對(duì)象鉴未,然后把它放到DPC隊(duì)列中厦滤。

? ? 目標(biāo)定在某個(gè)特定CPU上的DPC被認(rèn)為是定向的DPC,如果一個(gè)DPC是高優(yōu)先級(jí)的歼狼,則內(nèi)核將該DPC對(duì)象插在隊(duì)列的前端;否則享怀,對(duì)于所有其他的優(yōu)先級(jí)羽峰,內(nèi)核把DPC對(duì)象放在隊(duì)列的末尾。

? ? 內(nèi)核通常通過(guò)DPC/Dispatch級(jí)別的中斷來(lái)激發(fā)DPC隊(duì)列的“抽干”動(dòng)作添瓷。只有當(dāng)一個(gè)DPC被定位在發(fā)出ISR請(qǐng)求的處理器上梅屉,并且該DPC的優(yōu)先級(jí)高于低級(jí)時(shí),內(nèi)核才會(huì)產(chǎn)生這樣一個(gè)中斷鳞贷。如果該DPC的優(yōu)先級(jí)是低級(jí)坯汤,則只有當(dāng)針對(duì)該處理器并且尚未處理的DPC請(qǐng)求的數(shù)量在某個(gè)閾值以上,或者在一個(gè)時(shí)間窗口內(nèi)該處理器上的DPC請(qǐng)求的數(shù)量很少時(shí)搀愧,內(nèi)核才會(huì)請(qǐng)求中斷惰聂。如果DPC被定位于并不在運(yùn)行其ISR的CPU之上,并且該DPC的優(yōu)先級(jí)是高級(jí)或者中-高級(jí)咱筛,那么搓幌,內(nèi)核將立即用信號(hào)通知目標(biāo)CPU(給它發(fā)送一個(gè)分發(fā)IPI),以便“抽干”它的DPC隊(duì)列迅箩,但只有當(dāng)目標(biāo)處理器空閑時(shí)才可以溉愁。如果優(yōu)先級(jí)為中級(jí)或者低級(jí),則目標(biāo)處理器上排隊(duì)的DPC數(shù)量必須超過(guò)一定閾值饲趋,這樣內(nèi)核才會(huì)激發(fā)DPC/Dispatch中斷拐揭。

? ? 因?yàn)镈PC執(zhí)行時(shí)根本不管系統(tǒng)中當(dāng)前哪個(gè)線程在運(yùn)行,所以奕塑,它們也往往是客戶機(jī)系統(tǒng)或者工作站系統(tǒng)招致用戶能感知到不響應(yīng)的一個(gè)主要原因堂污,因?yàn)榧词棺罡邇?yōu)先級(jí)的線程也會(huì)被待處理的DPC打斷。有些DPC運(yùn)行時(shí)間很長(zhǎng)爵川,因而用戶可能會(huì)感覺到視頻或聲音時(shí)斷時(shí)續(xù)敷鸦,甚至鼠標(biāo)和鍵盤出現(xiàn)非正常的延遲,所以,針對(duì)需要長(zhǎng)時(shí)間運(yùn)行DPC的驅(qū)動(dòng)程序扒披,Windows提供了線程化DPC值依。

? ? 線程化DPC的工作方式是,在被動(dòng)級(jí)別上碟案,在一個(gè)實(shí)時(shí)優(yōu)先級(jí)的線程上執(zhí)行DPC例程愿险。這使得DPC可以搶占絕大多用用戶模式線程,但又允許其他的中斷价说、非線程化的DPC辆亏、APC和更高優(yōu)先級(jí)的線程來(lái)?yè)屨即薉PC例程。

? ? 異步過(guò)程調(diào)用(APC)中斷鳖目。異步過(guò)程調(diào)用提供了一種在特定用戶線程環(huán)境(從而也是在特定的進(jìn)程地址空間)中執(zhí)行用戶程序和系統(tǒng)代碼的途徑扮叨。因?yàn)锳PC被插入隊(duì)列,以便在特定線程環(huán)境執(zhí)行领迈,并且運(yùn)行在低于DPC/Dispatch級(jí)別的IRQL上彻磁,所以,它們不需要在像DPC那樣的限制下工作狸捅。APC例程可以訪問(wèn)資源衷蜓、等待對(duì)象句柄、引發(fā)頁(yè)面錯(cuò)誤尘喝,以及調(diào)用系統(tǒng)服務(wù)磁浇。

? ? APC是由稱為APC對(duì)象的內(nèi)核控制對(duì)象來(lái)描述的。正在等待執(zhí)行的APC駐留在由內(nèi)核管理的APC隊(duì)列中朽褪,DPC隊(duì)列是系統(tǒng)范圍的置吓,與此不同,APC隊(duì)列是與特定線程相關(guān)的鞍匾,即每個(gè)線程有它自己的APC隊(duì)列交洗。當(dāng)內(nèi)核接到請(qǐng)求,要將APC排隊(duì)時(shí)橡淑,它會(huì)將該APC插入將來(lái)執(zhí)行此APC例程的那個(gè)線程的隊(duì)列中构拳。然后,內(nèi)核請(qǐng)求一個(gè)APC級(jí)別的軟件中斷梁棠,當(dāng)該線程最終開始運(yùn)行時(shí)置森,它就會(huì)執(zhí)行此APC。

? ? 有兩種APC類型:內(nèi)核模式和用戶模式符糊。內(nèi)核模式的無(wú)須目標(biāo)線程的干涉或者同意凫海,就可以中斷該線程并執(zhí)行一個(gè)過(guò)程。內(nèi)核模式的APC也有兩種:普通的和特殊的男娄。特殊的APC在APC級(jí)別上執(zhí)行行贪,并且允許APC例程修改某些APC參數(shù)漾稀;普通的在被動(dòng)級(jí)別上執(zhí)行,并且接收被特殊APC例程修改過(guò)的參數(shù)建瘫。

? ? 執(zhí)行體使用內(nèi)核模式的APC來(lái)完成那些必須在特定線程的地址空間才能完成的操作系統(tǒng)任務(wù)崭捍。它可以利用特殊的內(nèi)核模式APC來(lái)指示某個(gè)線程停止執(zhí)行一個(gè)可中斷的系統(tǒng)服務(wù)。

? ? 內(nèi)核模式APC的另一個(gè)重要用途與線程的掛起和終止有關(guān)啰脚。因?yàn)檫@些操作可以從任意的線程中發(fā)起殷蛇,也可以指定其他任意的線程,所以橄浓,內(nèi)核使用APC來(lái)詢問(wèn)線程環(huán)境粒梦,以及終止目標(biāo)線程。

? ? 有幾個(gè)Windows API荸实,比如ReadFileEx匀们、WriteFileEx和QueueUserAPC,用到了用戶模式APC准给。只有當(dāng)一個(gè)線程處于可警醒的等待狀態(tài)時(shí)昼蛀,用戶模式APC才可以交付給該線程。內(nèi)核模式的APC運(yùn)行在APC級(jí)別上圆存,與此不同,用戶模式的APC運(yùn)行在被動(dòng)級(jí)別上仇哆。

? ? APC的交付可能會(huì)導(dǎo)致等待隊(duì)列的重新排序沦辙,這里,等待隊(duì)列是指哪些線程正在為了什么而等待讹剔,以及它們等待的順序油讯。如果當(dāng)一個(gè)APC被交付時(shí),線程正處于等待狀態(tài)延欠,則在APC例程完成以后陌兑,此等待將被重新發(fā)起或者重新執(zhí)行。如果等待尚未被解決由捎,則線程返回到等待狀態(tài)兔综,但現(xiàn)在,在它所等待的對(duì)象中狞玛,它位于等待列表的末尾软驰。


定時(shí)器處理

? ? Windows對(duì)系統(tǒng)時(shí)鐘進(jìn)行編程,以便使機(jī)器按照最合適的間隔來(lái)激發(fā)中斷心肪,繼而允許驅(qū)動(dòng)程序锭亏、應(yīng)用程序和管理員根據(jù)需要修改時(shí)鐘間隔。通常硬鞍,系統(tǒng)時(shí)鐘或者由PIT(可編程的中斷定時(shí)器)芯片來(lái)維護(hù)慧瘤,或者由RTC(實(shí)時(shí)時(shí)鐘)來(lái)維護(hù)戴已。PIT的工作基礎(chǔ)是一個(gè)石英晶體,它被調(diào)整為1/3NTSC彩色載波頻率锅减,HAL利用各種可以實(shí)現(xiàn)的復(fù)合技術(shù)來(lái)達(dá)到毫秒級(jí)的時(shí)間間隔糖儡。另一方面,RTC運(yùn)行在32.768KHz的頻率上上煤,由于是2的冪次休玩,因此比較容易配置成在2的冪次的各種時(shí)間間隔上工作。

? ? 有些類型的Windows應(yīng)用程序要求非辰俸荩快的響應(yīng)時(shí)間拴疤,比如多媒體應(yīng)用程序。事實(shí)上独泞,有些多媒體任務(wù)要求低于1ms的時(shí)鐘中斷率呐矾。由于這個(gè)原因,Windows實(shí)現(xiàn)了一組API和相應(yīng)的機(jī)制允許降低系統(tǒng)時(shí)鐘中斷的間隔懦砂,但這會(huì)導(dǎo)致更多的時(shí)鐘中斷蜒犯。

? ? Windows在可能的情況下都盡量將時(shí)鐘定時(shí)器恢復(fù)到原始值。每當(dāng)一個(gè)進(jìn)程請(qǐng)求改變時(shí)鐘定時(shí)器時(shí)荞膘,Windows都增加一個(gè)內(nèi)部的引用計(jì)數(shù)罚随,并將此計(jì)數(shù)與該進(jìn)程關(guān)聯(lián)起來(lái)。類似地羽资,驅(qū)動(dòng)程序(也可能會(huì)改變時(shí)鐘率)被加到一個(gè)全局的引用計(jì)數(shù)上淘菩。當(dāng)所有的驅(qū)動(dòng)程序都已恢復(fù)時(shí)鐘,所有修改過(guò)時(shí)鐘的進(jìn)程都已退出或者恢復(fù)了時(shí)鐘時(shí)屠升,Windows將時(shí)鐘恢復(fù)到默認(rèn)的值潮改。

? ? 定時(shí)器到期。對(duì)于RTC或PIT所產(chǎn)生的中斷腹暖,與之關(guān)聯(lián)的ISR主要任務(wù)之一是汇在,跟蹤記錄系統(tǒng)時(shí)間,主要是由KeUpdateSystemTime例程來(lái)完成的脏答。它的第二項(xiàng)任務(wù)是:跟蹤記錄邏輯運(yùn)行時(shí)間糕殉,比如進(jìn)程/線程執(zhí)行時(shí)間和系統(tǒng)嘀嗒時(shí)間,開發(fā)人員利用諸如GetTickCount之類的API殖告,在其應(yīng)用程序中對(duì)各種操作進(jìn)行計(jì)時(shí)時(shí)糙麦,這些API用到的底層數(shù)值即系統(tǒng)嘀嗒時(shí)間。這部分工作是由KeUpdateRunTime來(lái)完成的丛肮。然而赡磅,KeUpdateRunTime在做這些工作以前,會(huì)首先檢查是否有定時(shí)器已經(jīng)到期宝与。

? ? Windows定時(shí)器可以是絕對(duì)定時(shí)器焚廊,這意味著將來(lái)某個(gè)確定的到期時(shí)間冶匹;也可以是相對(duì)定時(shí)器,其中包含一個(gè)負(fù)的到期值咆瘟,用作從定時(shí)器插入時(shí)刻的當(dāng)前時(shí)間開始一個(gè)正的偏移值嚼隘。在系統(tǒng)內(nèi)部,所有的定時(shí)器都被轉(zhuǎn)換成一個(gè)絕對(duì)的到期時(shí)間袒餐。

? ? 因?yàn)闀r(shí)鐘在已知間隔的倍數(shù)上才能激發(fā)飞蛹,所以,當(dāng)前系統(tǒng)時(shí)間的最底下幾位將是64個(gè)已知位置之一灸眼。Windows就利用這一事實(shí)卧檐,把所有的驅(qū)動(dòng)程序和應(yīng)用程序定時(shí)器組織到一組鏈表中,其中每一項(xiàng)對(duì)應(yīng)于系統(tǒng)時(shí)間的一個(gè)可能倍數(shù)焰宣。這張表稱為定時(shí)器表霉囚,位于PRCB中,這使得每個(gè)處理器都可以完成它自己獨(dú)立的定時(shí)器到期處理匕积,而無(wú)需獲得一個(gè)全局的鎖盈罐。?

? ? 因?yàn)槎〞r(shí)器是通過(guò)手鏈接在一起的,所以到期代碼會(huì)從頭到尾解析一遍該鏈表闪唆。一個(gè)定時(shí)器到期盅粪,無(wú)外乎兩種主要任務(wù):定時(shí)器被看作分發(fā)器同步對(duì)象(線程正在等待此定時(shí)器,作為超時(shí)的一部分悄蕾,或者直接作為一次等待)湾揽,等待測(cè)試和等待滿足算法將在此定時(shí)器上運(yùn)行;定時(shí)器被看做控制對(duì)象笼吟,與DPC回調(diào)例程關(guān)聯(lián)在一起,當(dāng)定時(shí)器到期時(shí)霸旗,此回調(diào)例程被執(zhí)行贷帮,這種方法僅保留給驅(qū)動(dòng)程序使用,并且對(duì)定時(shí)器的到期動(dòng)作可以做到非常低的延遲诱告。

? ? 選擇處理器撵枢。在插入定時(shí)器時(shí),必須選擇使用哪個(gè)表即選擇一個(gè)最恰當(dāng)?shù)奶幚砥骶印H绻摱〞r(shí)器沒有與之關(guān)聯(lián)的DPC锄禽,那么,內(nèi)核掃描當(dāng)前處理器所在組中尚未停運(yùn)的所有處理器靴姿。如果當(dāng)前處理器已停運(yùn)沃但,則從該組中選擇下一個(gè)處理器,否則使用當(dāng)前處理器佛吓。另一方面宵晚,如果定時(shí)器有一個(gè)關(guān)聯(lián)的DPC垂攘,那么插入代碼只是簡(jiǎn)單的看一看與該DPC關(guān)聯(lián)的目標(biāo)處理器,并且選擇該處理器的定時(shí)器表淤刃。

? ? 定時(shí)器合并晒他。在沒有定時(shí)器到期的時(shí)間段里將時(shí)鐘中斷最少化從而使處理器睡眠,這樣可以顯著提升狀態(tài)間隔的長(zhǎng)度逸贾,但是陨仅,由于定時(shí)器的粒度是15ms,許多定時(shí)器可能將被加到指定手的隊(duì)列中铝侵,并且頻繁的到期灼伤。降低軟件定時(shí)器到期工作的數(shù)量既可以幫助降低延遲,也可以讓其他處理器待在睡眠狀態(tài)更長(zhǎng)時(shí)間哟沫。為了充分優(yōu)化空閑時(shí)間的持續(xù)長(zhǎng)度饺蔑,內(nèi)核需要采用一種合并機(jī)制來(lái)把分散的定時(shí)器手組合到一個(gè)單獨(dú)的手中,讓它處理多個(gè)定時(shí)器到期嗜诀。

? ? 定時(shí)器合并能工作的前提條件是猾警,絕大多數(shù)驅(qū)動(dòng)程序和用戶模式應(yīng)用程序并不特別在意其定時(shí)器的確切激發(fā)周期。周期性的定時(shí)器設(shè)置了可容忍的延遲后隆敢,在定時(shí)器被對(duì)齊到最優(yōu)的周期間隔倍數(shù)之前发皿,Windows會(huì)使用一個(gè)稱為“移轉(zhuǎn)”的過(guò)程,這一過(guò)程會(huì)導(dǎo)致定時(shí)器在周期之間漂移拂蝎。


異常分發(fā)

? ? 中斷可以在任何時(shí)候發(fā)生穴墅,與此不同的是,異常是直接由當(dāng)前正在運(yùn)行的程序在執(zhí)行過(guò)程中產(chǎn)生的條件温自。Windows使用了一種稱為結(jié)構(gòu)化異常處理的設(shè)施玄货,使得應(yīng)用程序可以在異常發(fā)生時(shí)獲得控制。然后應(yīng)用程序可以修正此條件悼泌,并返回到異常發(fā)生處松捉,將棧展開;或者馆里,向系統(tǒng)報(bào)告該異常不可識(shí)別隘世,因而系統(tǒng)應(yīng)該繼續(xù)搜索一個(gè)有可能處理此異常的異常處理器。

? ? 在x86和x64處理器上鸠踪,所有的異常都有預(yù)定義的中斷號(hào)丙者,直接對(duì)應(yīng)于IDT中的表項(xiàng),而每個(gè)表項(xiàng)又指向每個(gè)特定異常的陷阱處理器营密。

? ? 所有的異常械媒,除了那些簡(jiǎn)單到直接由陷阱處理器就可以解決的以外,都是由一個(gè)稱為異常分發(fā)器的內(nèi)核模塊來(lái)服務(wù)的评汰。異常分發(fā)器的任務(wù)是找到一個(gè)能夠處置該異常的異常處理器滥沫。有些異常也允許原封不動(dòng)的濾回用戶模式侣集。例如,有些特定類型的內(nèi)存訪問(wèn)違例或者算術(shù)溢出產(chǎn)生的異常兰绣,操作系統(tǒng)不會(huì)對(duì)它們進(jìn)行處理世分。32位應(yīng)用程序可以建立起基于幀的異常處理器來(lái)處理這些異常∽罕纾“基于幀”是指將一個(gè)異常處理器與一個(gè)特定過(guò)程的激活動(dòng)作關(guān)聯(lián)起來(lái)臭埋。當(dāng)一個(gè)過(guò)程被調(diào)用時(shí),代表該過(guò)程激活動(dòng)作的“棧幀”被壓到棧中臀玄。一個(gè)棧幀可以關(guān)聯(lián)一個(gè)或者多個(gè)異常處理器瓢阴,每個(gè)異常處理器包保護(hù)源程序中一塊特定的代碼。對(duì)于64位應(yīng)用程序健无,結(jié)構(gòu)化異常處理機(jī)制并不使用基于幀的處理器荣恐,而是對(duì)于每個(gè)函數(shù),有一張異常處理器表被編譯到映像模塊中累贤,內(nèi)核檢查與每個(gè)函數(shù)相關(guān)聯(lián)的處理器叠穆。另一種異常處理機(jī)制被稱為向量化的異常處理。這種方法僅被用于用戶模式應(yīng)用程序臼膏。

? ? 如果在內(nèi)核模式中發(fā)生了異常硼被,則異常分發(fā)器只是簡(jiǎn)單的調(diào)用一個(gè)例程來(lái)找到一個(gè)基于幀的異常處理器,將來(lái)由它處理該異常渗磅。因?yàn)槲刺幚淼膬?nèi)核模式異常被認(rèn)為是嚴(yán)重的操作系統(tǒng)錯(cuò)誤嚷硫,所以可以假定,分發(fā)器總會(huì)找到一個(gè)異常處理器始鱼。但對(duì)于有些陷阱仔掸,并不能找到異常處理器,這樣的嚴(yán)重錯(cuò)誤會(huì)導(dǎo)致代碼為UNEXPECTED_KERNEL_MODE_TRAP的錯(cuò)誤檢查医清。

? ? 調(diào)試器斷點(diǎn)是常見的異常來(lái)源起暮,因此,異常分發(fā)器采取的第一個(gè)動(dòng)作是状勤,看一看引發(fā)該異常的進(jìn)程是否有一個(gè)相關(guān)聯(lián)的調(diào)試器進(jìn)程。如果有双泪,那么持搜,異常分發(fā)器向該進(jìn)程關(guān)聯(lián)的調(diào)試對(duì)象(在系統(tǒng)內(nèi)部稱為一個(gè)端口),發(fā)送一個(gè)調(diào)試器對(duì)象消息焙矛。如果沒有葫盼,那么,異常分發(fā)器切換到用戶模式下村斟,將陷阱幀按照CONTEXT數(shù)據(jù)結(jié)構(gòu)的格式復(fù)制到用戶棧中贫导,并且調(diào)用例程來(lái)找到一個(gè)結(jié)構(gòu)化的或向量化的異常處理器抛猫。如果沒有找到,則異常分發(fā)器切換回內(nèi)核模式下孩灯,并且再次調(diào)用調(diào)試器闺金,以便讓用戶做更多的調(diào)試工作。如果調(diào)試器不在運(yùn)行峰档,并且沒有找到用戶模式異常處理器败匹,那么,內(nèi)核向與該線程的進(jìn)程關(guān)聯(lián)在一起的異常端口發(fā)送一個(gè)消息讥巡。該異常端口如果存在掀亩,則是由控制該線程的環(huán)境子系統(tǒng)注冊(cè)的。該異常端口使得環(huán)境子系統(tǒng)有機(jī)會(huì)將一個(gè)異常轉(zhuǎn)譯成一個(gè)與環(huán)境相關(guān)的信號(hào)或者異常欢顷。然而槽棍,如果內(nèi)核在處理該異常的過(guò)程中已經(jīng)向前走的很遠(yuǎn)了,而且子系統(tǒng)并沒有處理該異常抬驴,那么炼七,內(nèi)核就向系統(tǒng)全局的錯(cuò)誤端口發(fā)送一個(gè)消息,并且執(zhí)行一個(gè)默認(rèn)的異常處理器怎爵,它只是簡(jiǎn)單的將引發(fā)該異常的線程所在的進(jìn)程終止掉特石。

? ? 未處理的異常。所有的Windows線程都有一個(gè)異常處理器鳖链,負(fù)責(zé)處理所有未被處理的異常姆蘸。該異常處理器是在Windows內(nèi)部的線程啟動(dòng)函數(shù)中聲明的。線程啟動(dòng)函數(shù)是在用戶創(chuàng)建進(jìn)程或者任何額外線程的時(shí)候運(yùn)行的芙委,它調(diào)用由環(huán)境子系統(tǒng)提供的線程啟動(dòng)例程交汤,這個(gè)例程在初始的線程環(huán)境結(jié)構(gòu)中指定,而這個(gè)線程啟動(dòng)例程又調(diào)用在CreateThread中由用戶提供的線程啟動(dòng)例程细溅。如果一個(gè)線程的異常沒有被處理卖陵,則Windows的未處理異常過(guò)濾器將被調(diào)用。此過(guò)濾器函數(shù)的用途是侧啼,當(dāng)一個(gè)異常未被處理時(shí)牛柒,為其提供一種由系統(tǒng)定義的行為:?jiǎn)?dòng)WerFault.exe進(jìn)程。然而痊乾,在默認(rèn)配置中皮壁,WindowsErrorReportingService服務(wù)將處理該異常,所以哪审,未處理異常過(guò)濾器永遠(yuǎn)不會(huì)被執(zhí)行蛾魄。

? ? Windows錯(cuò)誤報(bào)告。Windows錯(cuò)誤報(bào)告是一項(xiàng)極為復(fù)雜的機(jī)制,它可以自動(dòng)提交用戶模式的進(jìn)程崩潰和內(nèi)核模式的系統(tǒng)崩潰滴须。當(dāng)一個(gè)未處理的異常被未處理異常過(guò)濾器捕捉到時(shí)舌狗,它會(huì)首先建立起執(zhí)行環(huán)境信息,并打開一個(gè)ALPC端口扔水,連接到WER服務(wù)上痛侍。于是WER服務(wù)開始分析崩潰程序的狀態(tài),并執(zhí)行恰當(dāng)?shù)膭?dòng)作來(lái)通知用戶铭污。在默認(rèn)配置的系統(tǒng)上恋日,將向Microsoft的在線崩潰分析服務(wù)發(fā)送一個(gè)錯(cuò)誤報(bào)告。最終嘹狞,這一服務(wù)將獲得一個(gè)針對(duì)該問(wèn)題的解決方案岂膳,它向用戶顯示一條提示消息,告訴用戶采取怎樣的步驟來(lái)解決此問(wèn)題磅网。如果未處理異常過(guò)濾器本身崩潰谈截,則Windows的WER機(jī)制將在被崩潰的線程之外執(zhí)行前述工作,這使得任何種類的進(jìn)程或線程崩潰都可以被記錄下來(lái)涧偷,并且相應(yīng)的通知到用戶簸喂。

????WER服務(wù)通過(guò)NtSetInformationProcess來(lái)注冊(cè)全局錯(cuò)誤端口,結(jié)果是燎潮,所有的Windows進(jìn)程都有了一個(gè)錯(cuò)誤端口喻鳄,而該端口實(shí)際上是由WER服務(wù)注冊(cè)的一個(gè)ALPC端口對(duì)象。


系統(tǒng)服務(wù)分發(fā)

? ? 系統(tǒng)服務(wù)分發(fā)确封。在Pentium II之前的x86處理器上除呵,Windows使用int 0x2e(46)指令,它會(huì)導(dǎo)致一個(gè)陷阱爪喘。Windows填充IDT的46號(hào)表項(xiàng)颜曾,使其指向系統(tǒng)服務(wù)分發(fā)器。該陷阱導(dǎo)致執(zhí)行線程轉(zhuǎn)換到內(nèi)核模式中秉剑,并且進(jìn)入系統(tǒng)服務(wù)分發(fā)器泛豪。EAX寄存器中傳遞的數(shù)值參數(shù)指明了所請(qǐng)求的系統(tǒng)服務(wù)號(hào),EDX寄存器指向調(diào)用者傳遞給該系統(tǒng)服務(wù)的參數(shù)列表侦鹏。要回到用戶模式诡曙,系統(tǒng)服務(wù)分發(fā)器需要使用iret指令(即中斷返回指令)。

? ? 在更高級(jí)的處理器上略水,Windows使用專門的sysenter指令价卤,這是Intel特別為快速系統(tǒng)服務(wù)分發(fā)而定義的指令。Windows在引導(dǎo)時(shí)將內(nèi)核的系統(tǒng)服務(wù)分發(fā)器例程的地址保存在與該指令相關(guān)聯(lián)的一個(gè)MSR中聚请。該指令一旦被執(zhí)行荠雕,就會(huì)導(dǎo)致變換到內(nèi)核模式下,并且執(zhí)行系統(tǒng)服務(wù)分發(fā)器驶赏。為了返回到用戶模式炸卑,系統(tǒng)服務(wù)分發(fā)器通常執(zhí)行sysexit指令。在有些情況下煤傍,如當(dāng)處理器上單步標(biāo)志被打開時(shí)盖文,系統(tǒng)服務(wù)分發(fā)器改而使用iret指令,因?yàn)閟ysexit不允許返回到用戶模式時(shí)有不同的EFLAGS寄存器蚯姆。

? ? 在x64體系架構(gòu)上五续,Windows使用syscall指令,系統(tǒng)調(diào)用號(hào)通過(guò)EAX傳遞龄恋,前四個(gè)參數(shù)在寄存器中傳遞疙驾,剩下參數(shù)放在棧中。在IA64體系架構(gòu)上郭毕,Windows使用epc(Enter Privileged Mode)指令它碎,前八個(gè)系統(tǒng)調(diào)用參數(shù)在寄存器中傳遞,余下的放在棧中傳遞显押。

? ? 內(nèi)核模式下系統(tǒng)服務(wù)分發(fā)扳肛。內(nèi)核利用系統(tǒng)調(diào)用號(hào),在系統(tǒng)服務(wù)分發(fā)表中找到相應(yīng)的系統(tǒng)服務(wù)信息乘碑,在32位系統(tǒng)上挖息,系統(tǒng)服務(wù)分發(fā)表類似于中斷分發(fā)表,只不過(guò)在這里每個(gè)表項(xiàng)都包含了一個(gè)指向系統(tǒng)服務(wù)的指針兽肤,而不是指向中斷處理例程套腹。在64位系統(tǒng)上,該表的實(shí)現(xiàn)略有不同——它包含的不是指向系統(tǒng)服務(wù)的指針轿衔,而是相對(duì)于該表本身的偏移沉迹。

? ? 系統(tǒng)服務(wù)分發(fā)器KiSystemService將調(diào)用者的參數(shù)從線程的用戶模式棧中復(fù)制到內(nèi)核模式棧中,然后執(zhí)行該系統(tǒng)服務(wù)害驹。內(nèi)核使用了第二個(gè)表鞭呕,稱為參數(shù)表,參數(shù)表是一個(gè)字節(jié)數(shù)組宛官,每一項(xiàng)描述了要復(fù)制的字節(jié)數(shù)葫松。在64位系統(tǒng)上,Windows通過(guò)一個(gè)稱為系統(tǒng)調(diào)用表縮緊的過(guò)程底洗,將這一信息實(shí)際編碼在服務(wù)表內(nèi)部腋么。如果傳遞給一個(gè)系統(tǒng)服務(wù)的參數(shù)指向了用戶空間中的緩沖區(qū),那么亥揖,內(nèi)核模式的代碼在復(fù)制數(shù)據(jù)時(shí)珊擂,要先檢查這些緩沖區(qū)是否可以訪問(wèn)圣勒。只有當(dāng)線程的原先模式屬性被設(shè)置為用戶模式,才會(huì)執(zhí)行緩沖區(qū)檢查工作摧扇。

? ? 內(nèi)核模式代碼也可以進(jìn)行系統(tǒng)調(diào)用圣贸。這里不需要中斷或sysenter操作,CPU已經(jīng)在正確的特權(quán)級(jí)上了扛稽。內(nèi)核可以訪問(wèn)所有它自己的例程吁峻,只需簡(jiǎn)單的調(diào)用即可,然而在张,對(duì)于外部的情形用含,只有當(dāng)這些系統(tǒng)調(diào)用被導(dǎo)出以后,驅(qū)動(dòng)程序才能訪問(wèn)它們帮匾。實(shí)際上啄骇,只有少數(shù)系統(tǒng)調(diào)用被導(dǎo)出。

? ? Zw版本實(shí)質(zhì)上僅被用于驅(qū)動(dòng)程序瘟斜。因?yàn)檫@一原先模式值只有在內(nèi)核每次建立陷阱幀的時(shí)候才會(huì)更新肠缔,所以,在一個(gè)簡(jiǎn)單的API調(diào)用內(nèi)部哼转,這一值實(shí)際上不會(huì)發(fā)生變化明未,若直接調(diào)用Nt版本函數(shù),內(nèi)核保存的原先模式值指明了它是用戶模式下的壹蔓,但又檢測(cè)到傳遞過(guò)來(lái)的地址是一個(gè)內(nèi)核模式地址趟妥,于是,該調(diào)用失敗佣蓉。然而披摄,這并非實(shí)際發(fā)生的情形。導(dǎo)出的API實(shí)際上并不是Nt版本的簡(jiǎn)單別名或包裝函數(shù)勇凭,而是對(duì)應(yīng)的Nt系統(tǒng)調(diào)用的“翻版”疚膊,使用了同樣的系統(tǒng)調(diào)用分發(fā)機(jī)制。建立一個(gè)假的中斷棧虾标,并直接調(diào)用KiSystemService例程寓盗,實(shí)質(zhì)上是在模擬CPU中斷。系統(tǒng)服務(wù)分發(fā)器將執(zhí)行同樣的操作璧函,就好像此調(diào)用來(lái)自于用戶模式傀蚌,只不過(guò)它會(huì)檢測(cè)到該調(diào)用的實(shí)際特權(quán)級(jí),并且設(shè)置原先模式為內(nèi)核蘸吓。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末善炫,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子库继,更是在濱河造成了極大的恐慌箩艺,老刑警劉巖窜醉,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異艺谆,居然都是意外死亡酱虎,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門擂涛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人聊记,你說(shuō)我怎么就攤上這事撒妈。” “怎么了排监?”我有些...
    開封第一講書人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵狰右,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我舆床,道長(zhǎng)棋蚌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任挨队,我火速辦了婚禮谷暮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘盛垦。我一直安慰自己湿弦,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開白布腾夯。 她就那樣靜靜地躺著颊埃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蝶俱。 梳的紋絲不亂的頭發(fā)上班利,一...
    開封第一講書人閱讀 51,155評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音榨呆,去河邊找鬼罗标。 笑死,一個(gè)胖子當(dāng)著我的面吹牛积蜻,可吹牛的內(nèi)容都是我干的馒稍。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼浅侨,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼纽谒!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起如输,我...
    開封第一講書人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤鼓黔,失蹤者是張志新(化名)和其女友劉穎央勒,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體澳化,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡崔步,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了缎谷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片井濒。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖列林,靈堂內(nèi)的尸體忽然破棺而出瑞你,到底是詐尸還是另有隱情,我是刑警寧澤希痴,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布者甲,位于F島的核電站,受9級(jí)特大地震影響砌创,放射性物質(zhì)發(fā)生泄漏虏缸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一嫩实、第九天 我趴在偏房一處隱蔽的房頂上張望刽辙。 院中可真熱鬧,春花似錦甲献、人聲如沸扫倡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)撵溃。三九已至,卻和暖如春锥累,著一層夾襖步出監(jiān)牢的瞬間缘挑,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工桶略, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留语淘,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓际歼,卻偏偏與公主長(zhǎng)得像惶翻,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鹅心,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容