首页
/
每日頭條
/
科技
/
windows操作系統基礎知識整理歸納
windows操作系統基礎知識整理歸納
更新时间:2024-11-29 17:33:44

本章的内容是針對Windows XP的32位版本的,但是絕大多數内容也适用于Windows的其他32位版本(Windows NT、Windows 2000和Windows Vista),并且可以比較容易地推廣到64位版本的Windows系統。

11.1 中斷描述符表

在保護模式下,當有中斷或異常發生時,CPU是通過中斷描述符表(Interrupt Descriptor Table,IDT)來尋找處理函數的。因此,可以說IDT是CPU(硬件)與操作系統(軟件)交接中斷和異常的關口(gate)。操作系統在啟動早期的一個重要任務就是設置IDT,準備好處理異常和中斷的各個函數。

11.1.1 概況

簡單來說,IDT是一張位于物理内存中的線性表,共有256個表項。在IA-32e(64位)模式下,每個IDT項的長度是16字節,IDT的總長度是4096字節(4KB)。在32位模式下,每個IDT項的長度是8字節,IDT的總長度是2048字節(2KB)。32位與64位的主要差異在于地址長度的變化,因此,下文隻讨論32位的情況。

IDT的位置和長度是由CPU的IDTR來描述的。IDTR共有48位,高32位是IDT的基地址,低16位是IDT的長度(limit)。LIDT(Load IDT)指令用于将操作數指定的基地址和長度加載到IDTR中,也就是改寫IDTR的内容。SIDT(Store IDT)指令用于将IDTR的内容寫到内存變量中,也就是讀取IDTR的内容。LIDT和SIDT指令隻能在實模式或保護模式的高特權級(Ring 0)下執行。在内核調試時,可以使用rigtr和rigtl命令觀察IDTR的内容(卷1中的2.6.2節)。

在Windows操作系統中,IDT的初始化過程大緻是這樣的。IDT的最初建立和初始化工作是由Windows系統的加載程序(NTLDR或WinLoad)在實模式下完成的。在準備好一個内存塊後,加載程序先執行CLI指令關閉中斷處理,然後執行LIDT指令将IDT的位置和長度信息加載到CPU中,而後,加載程序将CPU從實模式切換到保護模式,并将執行權移交給NT内核的入口函數KiSystemStartup。接下來,内核中的處理器初始化函數會通過SIDT指令取得IDT的信息,對其進行必要的調整,然後以參數形式傳遞給KiInitializePcr函數,後者将其記錄到描述處理器的基本數據區PCR(Processor Control Region)和Prcb(Processor control block)中。

以上介紹的過程都是發生在0号處理器中的,也就是所謂的Bootstrap Processor,簡稱BSP。因為即使是多CPU的系統,在把NTLDR或WinLoad及執行權移交給内核的階段都隻有BSP在運行。在BSP完成了内核初始化和執行體的階段0初始化後,在階段1初始化時,BSP才會執行KeStartAllProcessors函數來初始化其他CPU。BSP之外的其他CPU一般稱為AP(Application Processor)。對于每個AP,KeStartAllProcessors函數會為其建立一個單獨的處理器狀态區,包括它的IDT,然後調用KiInitProcessor函數,後者會根據啟動CPU的IDT為要初始化的AP複制一份,并做必要的修改。

在内核調試會話中,可以使用!pcr命令觀察CPU的PCR内容,清單11-1顯示了Windows Vista系統中0号CPU的PCR内容。

清單11-1 Windows Vista系統中0号CPU的PCR内容

kd> !pcr KPCR for Processor 0 at 81969a00: // KPCR結構的線性内存地址 Major 1 Minor 1 // KPCR結構的主版本号和子版本号 NtTib.ExceptionList: 9f1d9644 // 異常處理注冊鍊表 […] // 省略數行關于NTTIB的信息 SelfPcr: 81969a00 // 本結構的起始地址 Prcb: 81969b20 // KPRCB結構的地址 Irql: 0000001f // CPU的中斷請求級别(IRQL) IRR: 00000000 // IDR: ffff20f0 // InterruptMode: 00000000 // IDT: 834da400 // IDT的基地址 GDT: 834da000 // GDT的基地址 TSS: 8013e000 // 任務狀态段(TSS)的地址 CurrentThread: 84af6270 // 當前在執行的線程,ETHREAD地址 NextThread: 00000000 // 下一個準備執行的線程 IdleThread: 8196cdc0 // IDLE線程的ETHREAD地址

内核數據結構KPCR描述了PCR内存區的布局,因此也可以使用dt命令來觀察PCR,例如,kd> dt nt!_KPCR 81969a00。

11.1.2 門描述符

IDT的每個表項是一個所謂的門描述符(gate descriptor)結構。之所以這樣稱呼,是因為IDT項的基本用途就是引領CPU從一個空間到另一個空間去執行,每個表項好像是一個從一個空間進入另一個空間的大門(gate)。在穿越這扇門時CPU會做必要的安全檢查和準備工作。

IDT中可以包含以下3種門描述符。

(1)任務門(task-gate)描述符:用于任務切換,裡面包含用于選擇任務狀态段(TSS)的段選擇子。可以使用JMP或CALL指令通過任務門來切換到任務門所指向的任務,當CPU因為中斷或異常轉移到任務門時,也會切換到指定的任務。

(2)中斷門(interrupt-gate)描述符:用于描述中斷處理例程的入口。

(3)陷阱門(trap-gate)描述符:用于描述異常處理例程的入口。

圖11-1描述了以上3種門描述符的内容布局。

windows操作系統基礎知識整理歸納(從操作系統Windows的角度讨論中斷和異常機制)1

圖11-1 IDT中的3種門描述符的内容布局

從圖11-1可以看出,3種門描述符的格式非常相似,有很多共同的字段。其中DPL代表描述符優先級(descriptor previlege level),用于優先級控制,P是段存在标志。段選擇子用于選擇一個段描述符(位于LDT或GDT中,選擇子的格式參見本書卷1的2.6.3節),偏移部分用來指定段中的偏移,二者共同定義一個準确的内存位置。對于中斷門和陷阱門,二者指定的就是中斷或異常處理例程的地址;對于任務門,它們指定的就是任務狀态段的内存地址。

系統通過門描述符的類型字段,即高4字節的6~12位,來區分一個描述符的種類。例如任務門的類型是0b00101(b代表二進制數),中斷門的類型是0b0D110,其中D位用來表示描述的是16位門(0)還是32位門(1),陷阱門的類型是0b0D111。

11.1.3 執行中斷和異常處理函數

下面我們看看當有中斷或異常發生時,CPU是如何通過IDT尋找和執行處理函數的。首先,CPU會根據其向量号碼和IDTR中的IDT基地址信息找到對應的門描述符。然後判斷門描述符的類型,如果是任務描述符,那麼CPU會執行硬件方式的任務切換,切換到這個描述符所定義的線程;如果是陷阱描述符或中斷描述符,那麼CPU會在當前任務上下文中調用描述符所描述的處理例程。下面分别加以讨論。

我們先來看任務門的情況。簡單來說,任務門描述的是一個TSS,CPU要做的是切換到這個TSS所代表的線程,然後開始執行這個線程。TSS是用來保存任務信息的一段内存區,其格式是CPU所定義的。圖11-2給出了IA-32 CPU的TSS格式。從中我們看到TSS中包含了一個任務的關鍵上下文信息,如段寄存器、通用寄存器和控制寄存器,其中特别值得注意的是靠下方的SS0~SS2和ESP0~ESP2字段,它們記錄着一項任務在不同優先級執行時所應使用的棧,SSx用來選擇棧所在的段,ESPx是棧指針值。

CPU在通過任務門的段選擇子找到TSS描述符後,會執行一系列的檢查動作,比如确保TSS描述符中的存在标志是1,邊界值應該大于0x67,B(Busy)标志不為1等。所有檢查都通過後,CPU會将當前任務的狀态保存到當前任務的TSS中。然後把TSS描述符中的B标志設置為1。接下來,CPU要把新任務的段選擇子(與門描述符中的段選擇子等值)加載到TR寄存器,然後把新任務的寄存器信息加載到物理寄存器中。最後,CPU開始執行新的任務。

windows操作系統基礎知識整理歸納(從操作系統Windows的角度讨論中斷和異常機制)2

圖11-2 32位的任務狀态段(TSS)

下面通過一個小實驗來加深大家的理解。首先,在一個調試Windows Vista的内核調試會話中,通過ridtr命令得到系統IDT的基地址。

kd> r idtr idtr=834da400

因為雙重錯誤異常(Double Fault,#DF)通常是使用任務門來處理的,所以我們觀察這個異常對應的IDT項。因為#DF異常的向量号是8,每個IDT項的長度是8字節,所以我們可以使用如下命令顯示出8号IDT項的内容。

kd> db 834da400 8*8 l8 834da440 00 00 50 00 00 85 00 00 ..P.....

其中第2、3字節(從0起,下同)組成的WORD是段選擇子,即0x0050。第5字節(0x85)是P标志(為1)、DPL(0b00)和類型(0b00101)。

接下來使用dg命令顯示段選擇子所指向的段描述符。

kd> dg 50 P Si Gr Pr Lo Sel Base Limit Type l ze an es ng Flags ---- -------- -------- ---------- - -- -- -- -- ----------- 0050 81967000 00000068 TSS32 Avl 0 Nb By P Nl 00000089

也就是說,TSS的基地址是0x81967000,長度是0x68字節(Gran位指示By即Byte)。Type字段顯示這個段的類型是32位的TSS(TSS32),它的狀态為Available,并非Busy。

至此,我們知道了#DF異常對應的門描述符所指向的TSS,是位于内存地址0x81967000開始的0x68字節。使用内存觀察命令便可以顯示這個TSS的内容了(清單11-2)。

清單11-2 TSS的内容

kd> dd 81967000 81967000 00000000 81964000 00000010 00000000 81967010 00000000 00000000 00000000 00122000 81967020 8193f0a0 00000000 00000000 00000000 81967030 00000000 00000000 81964000 00000000 81967040 00000000 00000000 00000023 00000008 81967050 00000010 00000023 00000030 00000000 81967060 00000000 20ac0000 00000000 81964000 81967070 00000010 00000000 00000000 00000000

參考清單11-2,從上至下,81964000是在優先級0執行時的棧指針,00000010是在優先級0執行時的棧選擇子,00122000是這個任務的頁目錄基地址寄存器(PDBR,即CR3)的值,8193f0a0是程序指針寄存器(EIP)的值,當CPU切換到這個任務時便是從這裡開始執行的。接下來,依次是标志寄存器(EFLAGS)和通用寄存器的值。偏移0x48字節處的0x23是ES寄存器的值,相鄰的00000008是CS寄存器的值,即這個任務的代碼段的選擇子。而後是SS寄存器的值,即棧段的選擇子,再往後是DS、FS和GS寄存器的值(0x23、0x30和0)。偏移0x64字節處的20ac0000是TSS的最後4字節,它的最低位是T标志(0),即我們在卷1的4.3.3節介紹過的TSS中的陷阱标志。高16字節是用來定位IO映射區基地址的偏移地址,它是相對于TSS的基地址的。

使用ln命令可以觀察EIP的值對應的就是内核函數KiTrap08。

kd> ln 8193f0a0 (8193f0a0) nt!KiTrap08 | (8193f118) nt!Dr_kit9_a Exact matches: nt!KiTrap08 = <no type information>

也就是說,當有#DF異常發生時,CPU會切換到以上TSS所描述的線程,然後在這個線程環境中執行KiTrap08函數。之所以要切換到一個新的線程,而不是像其他異常那樣在原來的線程中處理,是因為#DF異常指的是在處理一個異常時又發生了異常,這可能意味着本來的線程環境已經不可靠了,所以有必要切換到一個新的線程來執行。

類似地,代表緊急任務的不可屏蔽中斷(NMI)也是使用任務門機制來處理的。最後要說明的是,因為x64架構不支持硬件方式的任務切換,所以IDT中也不再有任務門了。

大多數中斷和異常是利用中斷門或陷阱門來處理的,下面我們看看這兩種情況。

首先,CPU會根據門描述符中的段選擇子定位到段描述符,然後再進行一系列檢查,如果檢查通過,CPU就判斷是否需要切換棧。如果目标代碼段的特權級别比當前特權級别高(級别的數值小),那麼CPU需要切換棧,其方法是從當前任務的TSS中讀取新棧的段選擇子(SS)和棧指針(ESP),并将其加載到SS和ESP寄存器。然後,CPU會把被中斷過程(舊的)的棧段選擇子(SS)和棧指針(ESP)壓入新的棧。接下來,CPU會執行如下兩項操作。

(1)把EFLAGS、CS和EIP的指針壓入棧。CS和EIP的指針代表了轉到處理例程前CPU正在執行代碼的位置。

(2)如果發生的是異常,而且該異常具有錯誤代碼(參見本書卷1的3.3.2節),那麼把該錯誤代碼也壓入棧。

如果處理例程所在代碼段的特權級别與當前特權級别相同,那麼CPU便不需要進行棧切換,但仍要執行上面的兩步操作。

TR寄存器中存放着指向當前任務TSS的選擇子,使用WinDBG可以觀察TSS的内容。

kd> r tr tr=00000028 kd> dg 28 P Si Gr Pr Lo Sel Base Limit Type l ze an es ng Flags ---- -------- -------- ---------- - -- -- -- -- --------- 0028 8013e000 000020ab TSS32 Busy 0 Nb By P Nl 0000008b

經常做内核調試的讀者可能會發現,TR寄存器的值大多時候是固定的。也就是說,值并不随着應用程序的線程切換而變化。事實上,Windows系統中的TSS個數并不是與系統中的線程個數相關的,而是與CPU個數相關的。在啟動期間,Windows系統會為每個CPU創建3~4個TSS,一個用于處理NMI,一個用于處理#DF異常,一個用于處理機器檢查異常(與版本有關,在XP SP1中存在),另一個供所有Windows線程共享。當Windows系統切換線程時,它把當前線程的狀态複制到共享的TSS中。也就是說,普通的線程切換并不會切換TSS,隻有當NMI或 #DF異常發生時,才會切換TSS,這就是所謂的以軟件方式切換線程(任務)。

11.1.4 IDT一覽

使用WinDBG的!idt擴展命令可以列出IDT中的各個項,不過該命令做了很多翻譯,顯示出的不是門描述符的原始格式。

lkd> !idt -a Dumping IDT: 00: 804dbe13 nt!KiTrap00 // 0号異常,即除以0 01: 804dbf6b nt!KiTrap01 02: Task Selector = 0x0058 // NMI的門描述符,顯示的是TSS的選擇子 03: 804dc2bd nt!KiTrap03

表11-1列出了典型Windows系統的IDT設置,對于不同的Windows版本或硬件配置不同的系統,某些表項可能有所不同,但是大多數表項是一緻的。

表11-1 IDT設置一覽(略)

在Windows XP系統中,處理機器檢查異常(#MC)的18号表項處是一個任務門描述符,指向一個單獨的TSS,對應的處理函數是hal模塊中的HalpMcaExceptionHandlerWrapper。

11.2 異常的描述和登記

為了更好地管理異常,Windows系統定義了專門的數據結構來描述異常,并定義了一系列代碼來标識典型的異常。

在操作系統層次,除了CPU産生的異常,還有通過軟件方式模拟出的異常,比如調用RaiseException API而産生的異常和使用編程語言的throw關鍵字抛出的異常。為了行文方便,我們把前一類稱為CPU異常(或硬件異常),把後一類稱為軟件異常。Windows是使用統一的方式來描述和分發這兩類異常的。本節介紹異常的描述方式,11.3節将介紹異常的分發過程。

11.2.1 EXCEPTION_RECORD結構

Windows系統使用EXCEPTION_RECORD結構來描述異常,清單11-3給出了這個結構的定義。

清單11-3 EXCEPTION_RECORD結構

typedef struct _EXCEPTION_RECORD { DWORD ExceptionCode; // 異常代碼 DWORD ExceptionFlags; // 異常标志 struct _EXCEPTION_RECORD* ExceptionRecord; // 相關的另一個異常 PVOID ExceptionAddress; // 異常發生地址 DWORD NumberParameters; // 參數數組中的元素個數 ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; // 參數數組 } EXCEPTION_RECORD, *PEXCEPTION_RECORD;

其中ExceptionCode為異常代碼,是一個32位的整數,其格式是Windows系統的狀态代碼格式,NtStatus.h中包含了已經定義的所有狀态代碼,在WinBase.h中可以看到異常代碼隻是狀态代碼的别名,例如:

#define EXCEPTION_BREAKPOINT STATUS_BREAKPOINT #define EXCEPTION_SINGLE_STEP STATUS_SINGLE_STEP

表11-2列出了常見的用于異常代碼的狀态代碼。

字段用來記錄異常标志,它的每一位代表一種标志,目前已經定義的标志位如下。

(1)EH_NONCONTINUABLE(1),該異常不可恢複繼續執行。

(2)EH_UNWINDING(2),當因為執行棧展開而調用異常處理函數時,會設置此标志。

(3)EH_EXIT_UNWIND(4),也是用于棧展開,較少使用。

(4)EH_STACK_INVALID(8),當檢測到棧錯誤時,設置此标志。

(5)EH_NESTED_CALL(0x10),用于标識内嵌的異常(第24章)。

EH_NONCONTINUABLE位用來表示該異常是否可以恢複繼續執行,如果試圖恢複運行一個不可繼續的異常,便會導緻EXCEPTION_NONCONTINUABLE_EXCEPTION異常。

ExceptionRecord指針指向與該異常有關的另一個異常記錄,如果沒有相關的異常,那麼這個指針便為空。

表11-2 用于的異常代碼的狀态代碼(略)

ExceptionAddress字段用來記錄異常地址,對于硬件異常,它的值因為異常類型不同而可能是導緻異常的那條指令的地址,或者是導緻異常指令的下一條指令的地址。例如,非法訪問異常(EXCEPTION_ACCESS_VIOLATION)屬于錯誤(Fault)類異常,ExceptionAddress的值是導緻異常的那條指令的地址。數據斷點觸發的調試異常屬于陷阱(Trap)類異常,ExceptionAddress的值是導緻異常指令的下一條指令的地址。

NumberParameters是附加參數的個數,即ExceptionInformation數組中包含的有效參數個數,該結構最多允許存儲15個附加參數。

導緻非法訪問異常的原因主要來源于CPU的頁錯誤異常#PF(14),但也可能是由于系統檢測到的其他違反系統規則的情況。

11.2.2 登記CPU異常

對于CPU異常,KiTrapXX例程在完成針對本異常的特别動作後,通常會調用CommonDispatchException函數,并通過寄存器将如下信息傳遞給這個函數。

(1)将唯一标識該異常的一個異常代碼(表11-2)放入EAX寄存器。

(2)将導緻異常的指令地址放入EBX寄存器。

(3)将其他信息作為附帶參數(最多3個)分别放入EDX(參數1)、ESI(參數2)和EDI(參數3)寄存器,并将參數個數放入ECX寄存器。

CommonDispatchException被調用後,它會在棧中分配一個EXCEPTION_ RECORD結構,并把以上異常信息存儲到該結構中。在準備好這個結構後,它會調用内核中的KiDispatchException函數來分發異常。

11.2.3 登記軟件異常

下面看看軟件異常的産生和登記過程。簡單來說,軟件異常是通過直接或間接調用内核服務NtRaiseException而産生的。

NTSTATUS NtRaiseException (IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT ContextRecord, IN BOOLEAN FirstChance )

用戶模式中的程序可以通過RaiseException ()API來調用這個内核服務。RaiseException API是由KERNEL32.DLL導出的API,供應用程序産生“自定義”的異常,其原型如下。

void RaiseException( DWORD , DWORD , DWORD , const DWORD* );

其中是異常代碼,可以是表11-2中的代碼,也可以是應用程序自己定義的代碼。和用來定義異常的常數,相當于EXCEPTION_RECORD結構中的和。事實上,RaiseException的實現也很簡單,它隻是将參數放入一個 EXCEPTION_RECORD 後便調用NTDLL.DLL中的RtlRaiseException()。RtlRaiseException會将當前的執行上下文(通用寄存器等)放入CONTEXT結構,然後通過NTDLL.DLL中的系統服務調用機制調用内核中的NtRaiseException。

NtRaiseException内部會調用另一個内核函數KiRaiseException。

NTSTATUS KiRaiseException (IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT ContextRecord, IN PKEXCEPTION_FRAME ExceptionFrame, IN PKTRAP_FRAME TrapFrame, IN BOOLEAN FirstChance )

ExceptionRecord是指向異常記錄的指針,ContextRecord是指向線程上下文(CONTEXT)結構的指針,ExceptionFrame對于x86平台總是為NULL,TrapFrame就是棧幀的基地址,FirstChance表示這是該異常的第一輪(TRUE)還是第二輪(FALSE)處理機會。

内核中的代碼可以通過RtlRaiseException(相當于NTDLL.DLL中的版本)來調用NtRaiseException和KiRaiseException。也就是說,不論是從用戶模式調用RaiseException API,還是從内核模式調用相應的函數,最後都會轉到KiRaiseException。

KiRaiseException内部會通過KeContextToKframes例程把ContextRecord結構中的信息複制到當前線程的内核棧,然後把ExceptionRecord 中的異常代碼的最高位清0,以便把軟件産生的異常與CPU異常區分開來。接下來KiRaiseException會調用KiDispatchException開始分發該異常。

對于Visual C 程序抛出的異常,比如MFC中從CException派生來的各個異常類對應的異常,throw關鍵字直接對應的是CxxThrowException函數,CxxThrowException會調用RaiseException,并将ExceptionCode參數固定為0xe06d7363(對應的ASCII碼為.msc)。接下來的過程與上面直接調用RaiseException的情況相同。因為C 異常的實現與編譯器有關,所以本書隻讨論使用Visual C 編譯器的情況。

.NET程序抛出的異常(CLR異常)也是通過RaiseException API産生的,其異常代碼固定為0xe0434f4d(對應的ASCII碼為.COM)。

綜上所述,不論是CPU異常還是軟件異常,盡管産生的原因不同,但最終都會調用内核中的KiDispatchException來分發異常,也就是說,Windows系統是使用統一的方法來分發CPU異常和軟件異常的。

11.3 異常分發過程

根據前面兩節的介紹,當有異常發生時,CPU會通過IDT找到異常處理函數,即内核中的KiTrapXX系列函數,然後轉去執行。但是,KiTrapXX函數通常隻是對異常作簡單的表征和描述,為了支持調試和軟件自己定義的異常處理函數,系統需要将異常分發給調試器或應用程序的處理函數。對于軟件異常,Windows系統是以和CPU異常統一的方式來分發和處理的,本節将介紹分發異常的核心函數KiDispatchException和它的工作過程。

11.3.1 KiDispatchException函數

Windows内核中的KiDispatchException函數是分發各種Windows異常的樞紐。其函數原型如下。

VOID KiDispatchException ( IN PEXCEPTION_RECORD ExceptionRecord, IN PKEXCEPTION_FRAME ExceptionFrame, IN PKTRAP_FRAME TrapFrame, IN KPROCESSOR_MODE PreviousMode, IN BOOLEAN FirstChance )

其中,參數ExceptionRecord指向的是上一節介紹的EXCEPTION_RECORD結構,用來描述要分發的異常。參數ExceptionFrame對于x86系統總是為NULL。參數TrapFrame指向的是 KTRAP_FRAME 結構,用來描述異常發生時的處理器狀态,包括各種通用寄存器、調試寄存器、段寄存器等。參數PreviousMode 是一個枚舉類型的常量,DDK的頭文件中有這個枚舉類型的定義。

typedef enum _MODE { KernelMode, UserMode, MaximumMode} MODE;

也就是說,PreviousMode等于0表示前一個模式(通常是觸發異常代碼的執行模式)是内核模式,1表示用戶模式。FirstChance參數表示是否是第一輪分發這個異常。對于一個異常,Windows系統最多分發兩輪。

圖11-3畫出了KiDispatchException分發異常的基本過程(示意圖)。

從圖11-3中可以看到,KiDispatchException會先調用KeContextFromKframes函數,目的是根據TrapFrame參數指向的KTRAP_FRAME結構産生一個CONTEXT結構,以供向調試器和異常處理器函數報告異常時使用。

接下來,根據前一個模式(異常發生的模式)是内核模式還是用戶模式,KiDispatchException會選取左右兩個流程之一來分發異常,下面我們分别作進一步說明。

本文截選自《軟件調試 第2版 卷2 Windows平台調試 上、下冊》

windows操作系統基礎知識整理歸納(從操作系統Windows的角度讨論中斷和異常機制)3

本書是國内當前集中介紹軟件調試主題的權威著作。本書第2 卷分為5 篇,共30 章,主要圍繞Windows系統展開介紹。第一篇(第1~4 章)介紹Windows 系統簡史、進程和線程、架構和系統部件,以及Windows系統的啟動過程,既從空間角度講述Windows 的軟件世界,也從時間角度描述Windows 世界的搭建過程。第二篇(第5~8 章)描述特殊的過程調用、墊片、托管世界和Linux 子系統。第三篇(第9~19 章)深入探讨用戶态調試模型、用戶态調試過程、中斷和異常管理、未處理異常和JIT 調試、硬錯誤和藍屏、錯誤報告、日志、事件追蹤、WHEA、内核調試引擎和驗證機制。第四篇(第20~25 章)從編譯和編譯期檢查、運行時庫和運行期檢查、棧和函數調用、堆和堆檢查、異常處理代碼的編譯、調試符号等方面概括編譯器的調試支持。第五篇(第26~30 章)首先縱覽調試器的發展曆史、工作模型和經典架構,然後分别讨論集成在Visual Studio 和Visual Studio(VS)Code 中的調試器,最後深度解析WinDBG 調試器的曆史、結構和用法。本書理論與實踐結合,不僅涵蓋了相關的技術背景知識,還深入研讨了大量具有代表性的技術細節,是學習軟件調試技術的珍貴資料。本書适合所有從事軟件開發工作的讀者閱讀,特别适合從事軟件開發、測試和支持的技術人員閱讀。

,
Comments
Welcome to tft每日頭條 comments! Please keep conversations courteous and on-topic. To fosterproductive and respectful conversations, you may see comments from our Community Managers.
Sign up to post
Sort by
Show More Comments
推荐阅读
戴爾網課筆記本
戴爾網課筆記本
杭州拱墅區杭州大廈、中央商城武林廣場B1-125室,(地鐵1号線武林廣場站);是杭州核心區大型城市綜合體——杭州大廈的重要組成部分,當然杭州戴爾電腦旗艦店及售後維修服務中心也在這裡,位于杭州大廈中央商場B1層125室,是杭州首家2.0新概念...
2024-11-29
蘋果門禁卡怎麼複制
蘋果門禁卡怎麼複制
蘋果門禁卡怎麼複制?要讓蘋果手機刷門禁卡,需要曲線實現首先需要我們在蘋果手機上添加一種類型的公交卡請先在手機屏幕上找到「錢包」應用,打開它,我來為大家科普一下關于蘋果門禁卡怎麼複制?以下内容希望對你有幫助!蘋果門禁卡怎麼複制要讓蘋果手機刷門...
2024-11-29
手機怎麼分屏
手機怎麼分屏
手機怎麼分屏?首先打開華為手機桌面的“設置”,然後在設置中找到并打開“智能輔助”,點擊進入後選擇“手勢控制”,最後将“分屏手勢”打開,現在小編就來說說關于手機怎麼分屏?下面内容希望能幫助到你,我們來一起看看吧!手機怎麼分屏首先打開華為手機桌...
2024-11-29
華為好用的錄屏軟件
華為好用的錄屏軟件
相信喜歡煲劇和玩遊戲的朋友,經常都會有錄屏的需要,但是華為手機和電腦錄屏的正确姿勢,你真的會嗎?接下來就帶各位一起看看吧!一、手機錄屏1.華為錄屏首先是我們華為手機的錄屏操作,非常簡單粗暴,隻要你雙指敲擊屏幕,瞬間就可以完成錄制操作了,是不...
2024-11-29
怎麼定位丢失的手機
怎麼定位丢失的手機
怎麼定位丢失的手機?工具/原料:手機:小米9,系統:miui1120.3.12,今天小編就來說說關于怎麼定位丢失的手機?下面更多詳細答案一起來看看吧!怎麼定位丢失的手機工具/原料:手機:小米9,系統:miui1120.3.12。打開手機設置...
2024-11-29
Copyright 2023-2024 - www.tftnews.com All Rights Reserved