Windows系統架構

系統架構html

 

 

 

關鍵組件
環境子系統和子系統DLL
  環境子系統嚮應用程序提供環境和應用程序編程接口(Appplication Programming Interface, API)。Windows 2000/XP支持三種環境子系統:Win3二、POSIX和OS/2,其中最重要的環境子系統是Win32子系統,其餘子系統都要經過Win32子系統接收用戶的輸入和顯示輸出。環境子系統的做用是將基本的執行體系統服務的某些子集提供給應用程序。 用戶應用程序調用系統服務時必須經過一個或多個子系統動態連接庫做爲中介才能夠完成。前端

  子系統由會話管理器(Session Manager)(Smss.exe)進程啓動。node

Ntdll.dll
  Ntdll.dll是一個特殊的系統支持庫,主要用於子系統DLL。包含兩種類型的函數:c++

系統服務分發存根(stub),在用戶模式下可經過這些函數調用windows執行體的系統服務。
內部支持函數,供子系統、子系統DLL及其餘的原生鏡像文件使用。
執行體
  是Ntoskrnl.exe中的上層,包含了基本的操做系統服務,好比內存管理、進程和線程管理、安全性、I/O、網絡和跨進程通訊等。程序員

內核
  由Ntoskrnl.exe的一組函數以及對於硬件體系架構的低層支持(如中斷和異常分發)構成。這些函數提供了一些最基本的機制,如線程調度和同步服務供執行體組件使用,可是全部的策略決定都留給了執行體,除了線程調度和分發。算法

硬件抽象層(HAL)
  Windows內部組件以及用戶編寫的驅動程序經過hal.dll訪問硬件。
  Ntoskrnl與hal相互連接。shell

設備驅動程序
硬件設備驅動程序
文件系統驅動程序
文件系統過濾驅動程序
網絡重定向器和服務器
協議驅動程序
內核流式驅動程序數據庫

  安裝驅動程序是在系統中添加用戶編寫的內核模式代碼的惟一方法。編程

系統進程
Idle進程(空閒進程,無實際的用戶模式映像文件)
System進程
會話管理器(Smss.exe,第一個用戶模式進程)
本地會話管理器(Lsm.exe)
Windows子系統(Csrss.exe)
會話0初始化(Wininit.exe)
登陸進程(Winlogon.exe)
服務控制管理器(Services.exe)和它建立的子服務進程(如Svchost.exe)
本地安全認證服務器(Lsass.exe)windows

深刻解析Windows操做系統筆記——CH1概念和術語

1.概念和工具

本章主要介紹Windows操做系統的關鍵概念和術語

1.概念和工具

1.1操做系統版本

1.2基礎概念和術語

1.2.1Windows API

1.2.2 服務、函數和例程

1.2.3 進程、線程和做業

1.2.3.1 進程

1.2.3.2 線程

1.2.3.3 虛擬地址描述符

1.2.3.4 做業

1.2.4 虛擬內存

1.2.5 內核模式和用戶模式

1.2.6 終端服務及多個會話

1.2.7 對象和句柄

1.2.8 安全性

1.2.9 註冊表

1.2.10 UNICODE

1.3 挖掘Windows內部機理

參考

 

1.1操做系統版本

Windows操做系統版本已經不少了

 

1.2      基礎概念和術語

1.2.1    Windows API

Windows API(應用程序接口),是針對Windows操做系統的系統編程接口。

Windows API有幾個分類:

n  基本服務

n  組件服務

n  用戶界面服務

n  圖形和多媒體服務

n  消息和協議

n  Web服務

本書重點介紹基本服務(好比,進程和線程,內存管理,I/O,安全性)。

關於.Net和WinFX

.NET FrameWork由框架類庫(FCL)和一個提供託管代碼運行環境的(CLR)組成。

CLR提供即時編譯,類型檢查,垃圾回收和代碼訪問安全性等。

託管代碼:在最初編譯時,將源代碼編譯成中間代碼(IL),而後在運行時,使用運行庫編譯器在受控的環境下,將中間代碼編譯成機器碼。

在微軟體系下,認爲不是託管代碼就是非託管代碼。

CLR是一個典型的COM服務器,創建在Windows API之上。

 

而WinFX就是新的Windows API(爲vista特別設計的),也提供了託管代碼的功能,可是缺容易混淆,後來改成.Net FrameWork 3。(關於WinFX的介紹在第6版中已經沒有了)。

.NET FrameWork是對API的一種擴展。

1.2.2 服務、函數和例程

主要介紹一些書中提到的專業術語:

n  Windows API函數:主要是指已經被文檔化的可調用的子例程

n  原生的系統服務:指操做系統中未文檔化的,能夠在用戶模式下調用的底層服務,如NtCreateProcess

n  內核支持函數(例程):值操做系統內部且只能被內核調用的子例程

n  Windows服務:由Windows服務管理器啓動的進程(在註冊表中,認爲驅動定於爲服務,可是書中並不這樣引用)

n  DLL:一組可調用的子例程,合起來被連接成一個二進制文件,應用程序能夠動態加載這些二進制文件。

1.2.3 進程、線程和做業

1.2.3.1 進程

程序是指一個靜態的指令序列,而進程是程序的實例化,擁有各類資源。一個進程由如下元素組成:

n  私有的虛擬地址空間

n  程序定義的代碼和數據,被映射到進程的虛擬地址空間中

n  一個已打開的句柄列表,這些句柄指向各類資源

n  稱爲訪問令牌的安全環境,標示了改進程關聯的用戶,安全組和特權

n  進程ID,能夠惟一識別一個進程

n  至少一個線程

每一個進程都指向一個父進程或者建立者進程,可是若是父進程被關閉,進程就會指向一個不存在的父進程。

1.2.3.2 線程

線程是在進程中的實體,也是Windows執行此進程的調度實體,沒有線程進程是不可能運行的。

線程的基本部件:

n  一組表明處理器狀態的CPU寄存器中的內容

n  2個棧,一個用於線程在內核模式下執行,一個用於線程在用戶模式下執行

n  線程局部存儲區(TLS),線程私有存儲區域,各個子系統,運行庫,DLL都會用到這個區域

n  惟一表示線程的線程ID

n  線程本身的安全環境

易失的寄存器,棧,私有存儲區域合起來稱爲線程的環境。

雖然線程有本身的環境,可是同一個進程內的線程共享該進程的虛擬地址空間及其餘屬於該進程的資源。

也就是說線程能夠讀寫進程內其餘線程的內存,可是不能跨進程的訪問,除非另一個進程把虛擬地址空間變成共享內存區。

1.2.3.3 虛擬地址描述符

虛擬地址描述符是一些數據結構,內存管理器使用這個數據結構來記錄一個進程所使用的虛擬地址。

1.2.3.4 做業

做業是指,一組進程當一個總體來維護管理。

1.2.4 虛擬內存

Windows 實現了平面地址空間的虛擬內存系統,每一個進程感受本身獨立擁有一個很大的私有地址空間。虛擬內存提供了內存邏輯視圖,並不對應於內存物理佈局。運行的時候,內存管理器藉助硬件支持,講虛擬地址翻譯成真正的物理地址。

進程之間就隔離了,一個進程不會訪問到另一個進程的東西。

大多數系統擁有的物理內存比虛擬地址小,因此當內存不夠的時候,內存管理器會把內存移動到磁盤,釋放內存,讓被的進程使用。

在32bit下,4GB的地址空間,其中2GB是內核地址空間,2GB是用戶模式地址空間,在起用3gb參數,用戶模式地址空間時3GB,內核模式地址空間時1GB

還有AWE地址窗口擴展,可讓32bit系統訪問64GB的內存。缺點是程序員本身解決映射關係。

 

在64bit下地址空間能夠達到8T,在Itanium系統上能夠達到7T

 

1.2.5 內核模式和用戶模式

爲了不用戶程序讀寫關鍵操做系統數據,Windows使用了2中處理器訪問模式:用戶模式,內核模式。用戶程序代碼運行在用戶模式,系統代碼運行在內核模式。內核模式容許訪問全部系統內存和cpu指令。用內核模式來保護操做系統穩定。

雖然Windows 進程都有本身的地址空間,可是內核模式的操做系統和驅動都是使用同一個虛擬地址空間。

系統空間中的頁面只有在內核模式下能夠訪問,用戶空間中的頁面在用戶模式下均可以訪問。

內核模式下運行的代碼能夠訪問全部系統空間中的內存。

由於進入內核模式就缺乏保護,因此第三方設備驅動程序加載時要當心。

當用戶模式調用系統服務的時候,會切換到內核模式下,當要將cpu控制權返回給用戶的時候要先切換到用戶模式。

1.2.6 終端服務及多個會話

1.2.7 對象和句柄

內核對象是某一個靜態定義的對象類型的單個運行時的實例。對象類型包含了一個系統定義的數據類型,在該對象上可用的函數,及一組對象屬性。如全部的進程是進程對象類型的一個實例。

對象和普通數據結構的區別是,對象的內部結構是被隱藏的。必需要調用對象服務才能讀寫對象內部數據。

對象技術的實現了操做系統4個系統任務:

n  提供了可供人讀的名稱

n  進程間共享資源和數據

n  保護資源,避免未受權訪問

n  引用跟蹤,若是再也不使用能夠釋放掉。

1.2.8 安全性

Windows的核心安全功能包含:針對全部可共享對象的自主保護,安全審計,登陸時密碼認證,以及一個資源被一個進程釋放後,其餘進程看不到上一個進程留下的資源。

1.2.9 註冊表

註冊表是系統數據庫,包含了引道和配置系統全部的信息。也反映了內存中易失的數據窗口,好比當前的硬件狀態,性能計數器。

1.2.10 UNICODE

1.3 挖掘Windows內部機理

主要介紹了一些調試工具,和Windows SDK

 

 

 深刻解析Windows操做系統筆記——CH2系統結構

2.系統結構

本章主要介紹系統的整體結構,關鍵部件之間的交互,以及運行在什麼環境。

2.系統結構

2.1 需求和設計目標

2.2 操做系統模型

2.3 整體結構

2.3.1 可移植性

2.3.2 對稱多處理

2.3.3 可伸縮性()

2.3.4 客戶和服務器版本的區別

2.3.5 版本檢查

2.4 關鍵的系統組件

2.4.1 環境子系統和子系統dll

2.4.1.1 Windows子系統

2.4.1.2 POSIX子系統

2.4.1.3 OS/2子系統

2.4.2 NTDLL.DLL

2.4.3 執行體

2.4.4 內核

2.4.5 內核對象

2.4.6 硬件支持

2.4.7 硬件抽象層(HAL)

2.4.8 設備驅動程序

2.4.9 系統進程

2.4.9.1 空閒進程

2.4.9.2 中斷和DPC

2.4.9.3 system進程和系統進程

2.4.9.4 會話管理器

2.4.9.5 Winlogon,lsass和Userinit

2.4.9.6 服務控制器管理

2.5 總結

 

2.1 需求和設計目標

2.2 操做系統模型

在大多數用戶操做系統中,應用程序與操做系統自己是隔離的:操做系統代碼在內核模式下執行,能夠訪問系統數據和硬件,應用程序代碼運行在用戶模式下,只有有限的接口可使用,對系統數據訪問受限,沒法直接訪問硬件。

 

和unix同樣,windows系統大部分代碼和驅動程序都是共享相同的受保護的內核模式空間。意味着操做系統任何組件,均可以破壞其餘組件的數據。

 

固然用戶程序和操做系統全部組件是隔離的。應用程序沒法直接訪問系統中特權部分的數據和代碼。

 

windows內核模式組件也體現了基本的面向對象設計原則。如他們不會直接進入另外一個組件的數據結構來訪問該組件維護的數據。相反是利用正式的接口來傳遞參數,訪問和修改相應的數據接口。

 

可是嚴格上來講windows並非一個面向對象系統。windows內部使用c語言,並非面向對象系統,c語言對象實現,只是借用了面嚮對象語言的特性。

2.3 整體結構

本節介紹windows的設計目標和包裝方式,以下圖windows整體結構中的關鍵系統組件。

 

 

 

有4中用戶模式進程:

1.固定的系統支持進程,如登錄進程,會話管理器進程。

2.服務進程,宿納了windows服務,如進程管理器和假脫機服務。

3.用戶應用程序,有6個類型:windows32位,windows64位,windows3.1 16位,ms-dos 16位,posix32位或者OS/2 32位。

4.環境子系統服務進程,實現了操做系統環境的部分支持。這裏的環境是指操做系統展現給用戶或者程序員的個性化部分。

在windows下,用戶程序不能直接訪問原始的windows服務,要經過一個或者多個子系統動態連接庫。

 

windows內核組件包含:

1.windows執行體,包含基本的操做系統服務,如內存管理,進程和線程管理,安全性,I/O,網絡,跨進程通訊。

2.windows內核,是由一組底層的操做系統功能構成,如線程調度,終端和異常處理分發。以及處理器同步。提供了一組例程和基礎對象。執行體的其餘部分利用這些例程和對象實現更高層次的功能。

3.設備驅動程序,硬件設備驅動程序,也包含文件系統和網絡驅動程序。其中硬件設備驅動程序將用戶的I/O函數調用轉化爲特定的硬件設備請求。

4.硬件抽象層,指一層特殊代碼,它把內核,設備驅動程序和windows執行體其餘部分跟與平臺相關的硬件差別隔離開來。

5.窗口和圖形系統:實現了圖形用戶界面函數。

文件名

組件

Ntoskrnl.exe

執行體和內核

Ntkrnlpa.exe

執行體和內核,支持物理地址擴展,是的系統可尋址64GB物理內存

Hal.dll

硬件抽象層

Win32k.sys

Windows子系統的內核模式部分

Ntdll.dll

內部支持函數,以及執行體函數和系統服務分發存根(stub)

Kernerl32.dll,Advapi32.dll,User32.dll,Gdi32.dll

Windows的核心子系統DLL

2.3.1 可移植性

windows的一個設計目標是要可以運行在各類不一樣的硬件體系結構上。

windows有2中方式支持可移植性以支持多種硬件體系結構和平臺:

1.windows有一個分層設計,系統底層部分與處理器體系結構相關,或與平臺相關的,這些部分被隔離到獨立的模塊中,因此搞成不須要考慮體系結構的區別。有2個組件爲系統提供了可移植性:內核和硬件抽象層。

2.windows的絕大多數代碼是由c語言編寫的,少部分是使用c++編寫的,只有那些須要直接與系統硬件通訊的部分或者對性能極端敏感的操做系統部分,纔是用匯編語言編寫的。

2.3.2 對稱多處理

多任務是值多個執行線程之間共享同一個處理器的操做技術。

 

可以很好的在多處理器運行是windows 的設計目標。windows是一個對稱多處理(SMP)操做系統。沒有主處理器,操做系統和用戶線程能夠被調度到任何一個處理器上運行,並且全部的處理器共享惟一的內存空間。

 

對稱處理和非對稱處理不一樣,操做系統選一個處理器運行系統內核代碼。而其餘處理器運行用戶代碼。

 

 

 

xp和2003支持2中新的多處理器系統:超線程(hyperthreading),NUMA(非一致性的內存結構)。

超線程是intel一個技術,能夠一個物理處理器上有多個邏輯處理器,是的一個邏輯cpu能夠在其餘邏輯cpu正在忙着的時候繼續運行。

 

在非一致性內存結構NUMA系統中,處理器被組織成更小的單元,成爲node,每一個結點都有本身的處理器和內存,並同一個一個緩存一致(cache-cohernet)的互聯總線鏈接到更大的系統上。NUMA系統上的windows仍然做爲一個smp系統運行。全部的處理器能夠訪問全部內存。不過本地結點比其餘節點速度要快,系統想要提升性能作法是,根據現場用到的內存所在的節點,講現場調度到同一個處理器上。

 

在windows的最初設計上32位最多隻支持32個cpu,64位支持64個cpu。並無本質的因素來限制處理器個數。註冊表LocensedProcessors能夠限制處理器個數。

 

考慮到性能問題內核和HAL分爲2個版本,單處理器和多處理器版本。

在系統磁盤上的文件名

在發佈介質上單處理器版本的名稱

在發佈介質上多處理器版本的名稱

Ntoskrnl.exe

Ntoskrnl.exe

Ntkrnlmp.exe

Ntkrnlpa.exe

Ntkrnlpa.exe in \windows\<arch>\Driver.cab

Ntkrpamp.exe in \windows\<arch>\Driver.cab

Hal.dll

取決於系統類型

取決於系統類型

如下只針對2000系統

 

 

Win32.sys

\I386\UNIPROC\Win32k.sys

\I386\Driver.cab中Win32.sys

Ntdll.dll

\I386\UNIPROC\Ntdll.dll

\I386\Ntdll.dll

Kernel32.dll

\I386\UNIPROC\Kernel32.dll

\I386\Kernel32.dll

2.3.3 可伸縮性()

多處理器系統下,管家你的問題是可伸縮性。windows有如下功能這些功能對windows做爲一個多處理器起到關鍵性的做用:

1.能一個處理器上運行系統代碼,也能夠在多個處理器上運行。

2.在單個進程內執行多個線程,這些線程能夠在不一樣的處理器上運行。

3.內核內部(如自旋鎖,排隊自旋鎖以及壓棧鎖)以及設備驅動程序和服務器進程內部的細粒度同步,是的多個組件能夠並行在多個處理器上運行。

4.如I/O完成端口之類的編程機制,是的能夠實現高效的多線程進程,而且這樣的程序再多處理系統上有很好的伸縮性。

2.3.4 客戶和服務器版本的區別

客戶版和服務器版主要區別是有:

支持的處理器個數不一樣。

支持的物理內存不一樣。

所支持的併發網絡鏈接數不一樣。

2.3.5 版本檢查

2.4 關鍵的系統組件

已經看過上面的簡易的結構圖,瞭解了高層的結構體系。

以後都會圍繞這個圖展開,第三章解釋windows使用的主要控制機制(如中斷,對象管理器)。第五章啓動和關閉windows的過程。第四章介紹各個管理機制(註冊表,服務進程,WMI)。剩餘的章節更加詳細的討論各個關鍵區域內存結構和操做(進程,線程,內存管理,安全性,I/O,存儲管理,高速緩存管理器,windos文件系統和網絡)。

 

2.4.1 環境子系統和子系統dll

如上圖,最初windows有3個子系統,os/2,posix,wondows。os/2最後一次發佈和Windows2000。到了xp posix也不發佈了。3個子系統中windows子系統比較特別,是必須啓動的。

查看註冊表HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems下面有子系統的信息。

 

其中Required值表示了啓動要加載的子系統,如上圖,值爲Debug和Windows。Window值包含了windows子系統的文件規範,csrss.exe它表明了客戶/服務器運行時的子系統。Debug爲空。Optional值爲Os2,Posix表示這2個子系統,被按需啓動。Kmode表示windows子系統的內核環境下運行的部分爲win32k.sys。

 

環境子系統角色是將windows基礎系統服務暴露給應用程序。每一個子系統都提供了對於windows原生服務不一樣部分的訪問能力。也就是說創建在某個子系統上的應用程序能夠作到的,是另外一個創建在不一樣子系統的應用程序沒法作到的。如posix的fork。

 

每一個exe能夠執行映像被綁定到一個子系統上,如VC++ link命令/SUBSYSTEM能夠指定類型代碼,可使用Exetype工具查看此類型代碼。

 

用戶程序不能直接調用windows服務而是經過dll來調用如windows子系統dll(kernel32.dll,advapi32.dll,user32.dll,Gdi32.dll),POSIX子系統DLL(psxdll.dll)。當一個應用程序調用子系統可能會發生3中狀況:

1.函數徹底在該子系統dll中實現的,在用戶模式下運行。

2.該函數要求調用windows執行一次或屢次。

3.改函數要求在環境子系統中完成某個工做。

2.4.1.1 Windows子系統

Windows子系統有一下幾個主要組件構成:

1.環境子系統進程(Csrss.exe),包含下列支持:

         a.控制檯(文本)窗口

         b.建立或刪除進程和線程

         c.對16爲虛擬DOS機(VDM)進程的一部分支持。

d.其餘一些函數,好比GetTempFile,DefineDosDevice,ExitWindowsEx,以及幾個天然語言函數支持。

2.內核模式驅動程序(win32k.sys)包含:

a.窗口管理器,它控制窗口顯示管理屏幕輸出,採集來自鍵盤,鼠標,和其餘設別的輸入,同時也負責將用戶的消息傳遞給應用程序。

         b.圖形設備接口,他是專門正對圖形輸出設備的函數庫。

3.子系統dll

子系統dll,如Kernel32.dll,Advapi32.dll,User32.dll,Gdi32.dll,將windows api文檔化,對應到Ntoskrnl.exe和Win32k.sys大多數未文檔化的系統服務調用。

4.圖形設備驅動

         指硬件香瓜你的圖形顯示器驅動程序,答應及驅動程序和視頻微端口驅動程序。

2.4.1.2 POSIX子系統

posix能夠當作是一個基於unix的可移植的操做系統接口。值的是正對unix風格的操做系統接口的一組國際標準。posix鼓勵廠商實現unix風格,編譯在系統之間遷移。

須要使用posix子系統,要求使用platform sdk中使用posix的頭文件和庫文件。posix是按需啓動的當第一次啓動posix,psxss.exe要運行起來。posix的映像文件不是直接運行的。一個特殊的稱爲posix.exe的支持映像文件被啓動起來,而後再建立一個子程序來運行posix應用程序。

2.4.1.3 OS/2子系統

和posix同樣,有用性頗有限,並且OS/2已經不在適用於windows了。

2.4.2 NTDLL.DLL

NTDLL.DLL是一個特殊的系統支持庫,主要用於子系統DLL。包含兩個類型函數:

1.系統服務分發存根(stubs),他們會調用Windows執行體系服務。

2.內部支持函數,供子系統,子系統DLL以及其餘的原生映像文件使用。

 

第一組函數是爲windows執行體系服務提供接口,在用戶模式下能夠經過接口函數調用windows執行體的系統服務,如(NtCreatefile,NtSetEvent)

 

對於每一個這樣的函數,ntdll包含了一個同名入口,函數內部的代碼包含了與處理器體系接口相關的模式切換指令,經過該指令可轉換到內核模式下,從而調用系統服務分發器。分發器檢查某些參數後,再調用真正的內核模式系統服務,其中包含ntoskrnl.exe內部實現代碼。

 

NTDLL.DLL也包含了許多支持函數,好比映像文件加載器(以ldr開頭的函數)、對管理器、Windows子系統進程通訊函數(Csr開頭的函數)、以及通常運行庫(Rtl開頭的函數)、也包含了異步調用(APC)分發器和異常分發器。

2.4.3 執行體

Windows執行體是Ntoskrnl.exe中的上層,內核是其下層。執行體包含如下幾類函數:

1.可在用戶模式下調用的導出函數。這些函數成爲(系統服務)並經過ntdll導出。還有一些未文檔化的如LPC、NtQueryInformationProcess

2.可經過DeviceIoControl函數調用設備驅動器函數。

3.只能在內核模式下導出的函數,而且這兒寫函數在Windows DDK或者Windows IFS Kit已經文檔化。

4.在內核模式下調用,未在Windows DDK或者IFS Kit中文檔化的導出函數。

5.定義爲全局符號,可是未被導出的函數。如以Iop或者Mi開頭的函數(分別是內部IO管理器支持函數和內部內存管理器支持函數)。

6.未定義爲全局符號,而是在一個模塊內容的函數。

 

Windows執行體還包含如下組件:

1.配置管理器,複製系統註冊表的實現和管理

2.進程和線程管理器,建立或者終止進程和線程。

3.安全應用監視器,強制在本地計算機上實行安全策略,它守護着系統資源執行對運行時對象的保護和審計。

4.I/O管理器:實現了設備無關的I/O,負責將這些操做分發到恰當的設備驅動程序作進一步處理。

5.即插即用(pnp)管理器:爲了支持一個特定的設備,肯定驅動,並加載這些驅動。

6.電源管理器:負責協調事件,而且向設備驅動程序產生電源管理I/O通知。如電源管理器設備爲系統空間,經過將cpu置於睡眠來下降電源電耗。

7.WDM Windows管理規範例程:容許設備驅動發佈有關性能和配置信息以及接受來自用戶模式的WMI服務命令。

8.高速緩存管理器:提升了以文件爲基礎的I/O操做的性能,其作法是讓最近引用過磁盤數據留在主內存中以便快速訪問。(而且延遲了寫操做,在將更新數據發送到磁盤前先在內存中停留一小段時間。)

9.內存管理器:實現了虛擬內存

10.邏輯預取器:加速系統和進程啓動過程

 

另外Windows執行提還包含了4組主要支持函數:

1.對象管理器,建立,管理,刪除Windows執行體對象和抽象數據類型,這些對象和數據類型表明了操做系統資源。

2.LPC設施,在同一臺機器上用戶進程和服務器進程之間傳遞消息。

3.公共運行庫,字符串處理,算術操做等函數。

4.執行體支持例程:如系統內存分配,互鎖的內存訪問,以及2中特殊的同步對象:資源和快速互斥體。

2.4.4 內核

內核是由Ntoskrnl.exe中的一組函數以及對硬件體系結構的低層支持構成的。Ntoskrnl.exe中的這組函數提供了一些最基本的機制。內核代碼使用C編寫,並不容易在C中訪問的任務,則保留使用匯編。大部分函數都已經文檔化,以Ke開頭。

2.4.5 內核對象

內核給高層作支持。內核實現了操做系統最基本的機制(調度,分發)。把各類策略決定留給了執行體。

內核外看來,執行體將線程和其餘可共享資源都表示爲對象。這些對象要求一些策略開銷。這些開銷在內核中不存在,內核實現了一組更簡單的對象,稱爲內核對象,幫助內核控制好中心處理過程,而且支持執行體對象的建立工做。執行體層的絕大多數對象包裝了一個或者多個內核對象,把他們的內核屬性合併起來。

一組內核對象創建了有關控制各類操做系統功能叫作控制對象,另外一組內核對象融合了同步的能力,改變或者影響線程調度叫分發器對象。分發器對象包含了內核線程,互斥體,事件,內核事件對,信號量,定時器,等待定時器。

執行體經過內核函數建立內核對象實例,維護對象實例。構建更加複雜的對象提供給用戶。

2.4.6 硬件支持

內核的另外一個主要功能是將執行體和設備驅動程序從windows所支持的各類硬件體系結構中抽象出來,或者隔離出來變化的差別。

在內核設計是竟可能的使用公共代碼最大化。內核支持的可移植性接口,在不一樣的體系結構上是等同的。並且實現這組接口的大部分代碼,在不一樣的結構體系上也是相同的。可是有些代碼和體系結構有關,如上下文切換。

從高層看線程選擇和上下文切換可使用相同的算法(上一個線程的執行上下文被保存起來,新線程的環境被加載進來),但在不一樣的處理器上,實現仍是有差別的。執行上下文是由處理器的寄存器來描述的,因此要保存和加載哪些數據仍是有差異的。

2.4.7 硬件抽象層(HAL)

硬件抽象層是系統可移植的關鍵。HAL是一個可加載的,內模式模塊提供了windows當前運行平臺的低層接口。它隱藏了與硬件相關的細節,如I/O接口,中斷控制器,以及多處理器通訊機制等,體系結構或者機器相關的功能。

windows內部組件以及用戶編寫的設備驅動並不直接訪問硬件,當它們須要得到與平臺相關的信息時,它們能夠經過調用HAL例程來保存可移植性。DDK中能找到不少有關HAL在驅動中的用法。

雖然windows帶了幾個HAL,可是安裝時只能有一個被選中,而且copy到系統磁盤,其文件名爲hal.dll。

2.4.8 設備驅動程序

設備驅動程序是可加載的內核模式(以.sys結尾),他們在I/O管理器和相應的硬件之間創建連接。驅動在內核模式下,位於如下3個環境之一:

1.在發起I/O功能的用戶線程環境中

2.在內核模式系統線程的環境中

3.做爲一箇中斷的結果(所以不存在任何特定的進程或者線程執行環境中)

驅動也是調用HAL,所以驅動程序能夠在windows支持的cpu體系結構上代碼級移植,在同一個體系結構族內是二進制可移植的。

設備驅動有如下幾類:

1.硬件設備驅動程序,經過HAL操做硬件,從而輸出到設備或者網絡,或者從設備或者網絡中輸入。硬件設備驅動也有不少類型如,總線驅動,人機界面驅動等。

2.文件系統驅動程序是指能夠接受面向文件的I/O請求,並將這些請求轉化成針對某一特定設備的I/O請求。

3.文件系統過濾器驅動程序:如截取了I/O請求而且執行某些增值處理以後再傳遞給下一層驅動(執行磁盤鏡像,加密的驅動程序)。

4.網絡重定向器和服務器指文件系統I/O請求傳遞給網絡上的某一臺機器。或者從網絡上接收此類請求的文件系統驅動程序。

5.協議驅動程序,如TCP/IP,NetBEUI,IPX/SPX之類的網絡協議

6.內核流式過濾器驅動程序:這樣的驅動被串接起來,以便對流數據進行信號處理。

驅動程序是內核模式中添加代碼的惟一方式。

2.4.9 系統進程

如下系統進程會出如今每一個windows系統中(其中空閒進程,system進程並非完整的過程,由於它們不是運行在用戶模式的可執行文件):

1.空閒進程

2.system進程

3.會話管理器(smss.exe)

4.windows子系統(csrss.exe)

5.登錄進程(winlogon.exe)

6.服務控制管理器(services.exe)和它建立的子服務進程(如系統提供通用服務宿主進程svrhost.exe)

7.本地安全認證服務器(lsass.exe)

2.4.9.1 空閒進程

空閒進程是第一個進程,並無在用戶模式下的實際映像文件。

2.4.9.2 中斷和DPC

標記爲中斷和DPC(分發過程調用)用於中斷和延遲過程調用的時間,他們並非進程,列在這裏是由於他們都會消耗cpu,並無計算在任何一個進程中,而是被算在系統空閒中。

2.4.9.3 system進程和系統進程

system進程是一種特殊線程的母體。這些特殊線程只能運行在內核模式哦。系統線程有普通線程全部屬性和環境,可是隻運行系統空間中加載的代碼。系統線程沒有地址空間,所以動態存儲空間,都必須從系統中內存堆分配,好比換頁或者非換頁池。

系統線程是由PsCreateSystemThread來建立的,這個函數只能在內核環境下才能被調用。

內核會建立一個稱爲平衡集管理器的系統線程,每秒沒喚醒一次,可能發出調度和內存管理相關事件。告訴緩存管理器也使用系統線程來實現「預讀」和」延遲寫」功能。

在排查問題是,知道系統線程映射到某個驅動程序中,甚至映射到包含改代碼的子例程中,必定很是有用。

因此若是system進程中的線程正在運行,首先要肯定哪些線程在運行。經過線程看哪一個驅動開始的或者檢查調用棧,得知在運行到哪裏了。

2.4.9.4 會話管理器

會話管理器(smss.exe)是系統中第一個建立的用戶模式進程,由負責完成執行體和內核初始化工做的內核模式系統線程最後建立實際的smss.exe進程。

在windows啓動過程當中,會話管理器負責許多比較重要的步驟,如打開頁面文件,執行延遲文件更名,刪除操做,建立環境變量。將子系統程序(csrss.exe)和winlogon.exe啓動起來。winlogon進程依次啓動其餘系統進程。

smss.exe的主線程執行以上步驟後,一直在csrss.exe和winlogon的進程上等待。若是這2個進程中任何一個非正常終止了,則ssms.exe讓系統崩潰,(崩潰代碼:status_system_process_terminated或0xc000021a)由於windows依賴這2個進程才能運行。

 

smss等待加載子系統的請求,調式事件,以建立新的終端服務器會話的請求。

終端服務會話是由smss來完成的。當smss接到一個建立會話的請求時,先調用NtSetSystemInformation,請求創建內核模式數據結構。又調用內部的內存管理函數MmSessionCreate該函數創建起會話虛擬地址空間,改地址空間包含會話中的換頁池以及由win32子系統的內核模式部分和其餘的會話空間設備驅動程序所分配,屬於某個會話的數據結構,而後會爲該會話建立winlogon和csrss實例。

 

2.4.9.5 Winlogon,lsass和Userinit

winlogon登錄進程處理交互式用戶的登錄和註銷,當sas被按下(ctrl+atl+del),winlogon接到一個用戶登錄請求。

登錄過程的身份識別和認證是在一個名爲GINA(圖形識別和認證)的可替換DLL中,windows的標準爲GINA爲Msgina.dll實現了默認的windows登錄界面。然而開發人員能夠提供他們本身的GINA DLL來實現其餘的身份識別和認證機制如:基於聲波的方法。

一旦用戶名和口令捕捉到了就能夠送到本地安全認證服務器進程(lsass.exe)進行認證。lsass調用適當的認證包,以執行實際的驗證操做,好比口令是否符合存儲在活動目錄或者sam中的口令信息。

在成功完成驗證後,lsass調用安全引用監視器中的一個函數(如:NtCreateToken)建立一個訪問令牌對象。對象包含當前用戶的安全範圍。winlogon利用此訪問令牌來建立該用戶會話中的初始進程默認爲userinit.exe。

userinit執行該用戶環境的一些初始化工做,而後再查找註冊表winlogon下的shell而且建立一個進程來運行系統定義的外殼程序(默認explorer.exe)

而後userinit退出,這就是explorer.exe沒有父進程的緣由。winlogon在註銷,登錄,sas winlogon是活動的。關於登錄過程各個步驟的完整秒死能夠看第5章。有關安全認證能夠查看第八章。

2.4.9.6 服務控制器管理

windows中的服務能夠自一個服務器進程,也能夠是一個驅動程序。這一指的是用戶模式進程(如:unix的守護進程),這些進程能夠在系統引導是自動啓動起來,而無需交互式的登錄過程。也能夠被配置爲手動啓動。

服務控制器是一個特殊的系統進程,用於啓動,中止服務進程也複製服務進程之間的交互。服務有3個民粹:運行中進程名,註冊表內名稱以及管理器的顯示名。

在服務進程和所運行的服務之間並非一一對應的,由於有些服務和其餘共享一個進程。註冊表服務類型代碼指明瞭共享仍是獨佔進程。

許多windows組件使用系統服務實現如Spooler,event log,Task Scheduler和多個網絡組件。

2.5 總結

本章主要歸納的介紹了一遍windows體系結構,檢查了一遍關鍵的組件,他們之間是如何聯繫起來的。

深刻解析Windows操做系統筆記——CH3系統機制

3.系統機制

微軟提供了一些基本組件讓內核模式的組件使用:

1.陷阱分發,包括終端,延遲的過程調用(DPC),異步過程調用(APC),異常分發以及系統服務分發

2.執行體對象管理器

3.同步,包括自旋鎖,內核分發器對象,以及等待是如何實現的。

4.系統輔助線程

5.其餘的機制,好比Windows全局標記

6.本地過程調用

7.內核事件跟蹤

8.Wow64

3.系統機制

3.1陷阱分發

3.1.1 中斷分發

3.1.1.1 硬件中斷

3.1.1.2 軟中斷請求級別(IRQL)

3.1.1.3 軟中斷

3.1.2 異常分發

3.1.3 系統服務分發

3.1.3.1 32位系統服務分發

3.1.3.2 64位系統服務分發

3.1.3.3 內核模式的系統服務分發

3.1.3.4 服務描述符表

3.2 對象管理器

3.2.1 執行體對象

3.2.2 對象結構

3.2.2.1 對象頭和對象體

3.2.2.2 對象類型

3.2.2.3 對象方法

3.2.2.4 對象句柄和進程句柄表

3.2.2.5 對象安全性

3.2.2.6 對象保持力

3.2.2.7 資源記帳

3.2.2.8 對象名稱

3.2.2.9 會話名稱空間

3.3 同步

3.3.1 高IRQL的同步

3.3.1.1 互鎖操做

3.3.1.2 自旋鎖

3.3.1.3 排隊自旋鎖

3.3.1.4 棧內排隊自旋鎖

3.3.1.5 執行體的互鎖操做

3.3.2 低IRQL的同步

3.3.2.1 內核分發對象

3.3.2.2 快速互斥體和受限互斥體

3.3.2.3 執行體資源

3.3.2.4 壓棧鎖

3.4 系統輔助線程

3.5 windows全局標誌

3.6 本地過程調用(LPC)

3.7 內核事件跟蹤

3.8 Wow64

3.8.1 Wow64進程地址空間佈局結構

3.8.2 系統調用

3.8.3 異常分發

3.8.4 用戶回調

3.8.5 文件系統重定向

3.8.6 註冊表重定向和反射

3.8.7 I/O請求

3.9總結

 

3.1陷阱分發

中斷和異常是致使處理器轉向正常控制流以外代碼的兩種系統條件。陷阱(trap)是指當異常或者中斷髮生時,處理器捕捉到一個執行線程,並將控制權轉移到操做系統中某處固定地址處的機制。

在Windows中處理器將控制權轉給一個陷阱處理器 (trap handle)。所謂陷阱處理器是指與某個特殊的中斷或者一場相關的一個函數

 

 

 

內核對待中斷和異常是有區別的,中斷是異步事件,而且與當前正在運行的任務毫無關係。中斷主要由I/O設備,處理器時鐘,定時器產生。中斷能夠容許和禁止。異常是一個同步過程,它是一個特殊指令執行的結果。

異常能夠在一樣數據在一個程序裏重現。異常的例子:內存訪問違例,特定的調試器指令,以及除0錯誤。內核把系統服務調用異常(從技術上講,他們是系統陷阱(trap))。

當一個硬件異常或者中斷產生的時候,處理器在被中斷的線程的內核棧中記錄機器狀態信息,當它能夠回到控制流中該點處繼續執行。若是該線程在用戶模式下執行,那麼windows就切換到該線程的內核模式棧。而後windows在被中斷的線程的內核棧上建立一個陷阱幀(trap frame),並把線程的執行狀態保存在陷阱幀裏。在內核調試器中輸入dtnt!_ktrap_frame就能夠看到陷阱定義。

 

多數狀況下內核安裝了前端陷阱處理函數,在內核將控制權交給與改陷阱香瓜的其餘函數以後或者以前,由這些前段陷阱來執行一些常規的陷阱任務。

如陷阱條件是一個設備中斷,則內核硬件中斷陷阱處理器將控制權轉交給一個由設備驅動程序提供給改中斷設備的中斷服務例程(ISR)。

若陷阱條件是由於調用了一個系統服務引起,那麼通用的系統服務陷阱處理器將控制前交給執行體中指定的系統服務。內核不會爲不處理的陷阱安裝陷阱處理器。陷阱處理器通常使用KeBugCheckEx,當內核檢測到可能致使數據被破壞的行爲時,改函數會中止計算機。

3.1.1 中斷分發

硬件產生的中斷每每是有I/O設置激發的。當設備須要服務就會以中斷的方式通知處理器。中斷驅動的設置能夠一步的進行I/O處理。

系統能夠產生軟中斷,如內核可能觸發一個軟中斷,觸發線程分發過程,同時也以異步的方式打斷一個線程的執行。

內核安裝了中斷陷阱處理器來響應設備中斷,中斷陷阱處理器將控制權遞給一個負責該中斷的外部例程(ISR)或者傳遞給一個響應中斷的內部內核例程。

下面介紹硬件如何向處理器通知中斷,內核支持中斷類型,設備驅動如何與內核交互,以及內核如何識別軟中斷。

3.1.1.1 硬件中斷

在windows鎖支持的平臺上,外部I/O中斷進入中斷控制器的一個引腳,該控制器在cpu的引腳上中斷cpu。中斷控制器將IRQ(中斷請求)翻譯成中斷號,利用該中斷號做爲中斷分發表的索引。並將控制權傳遞給恰當的中斷分發例程。

在引導時,windows填充IDT(中斷分發表),其中包含了指向內核中負責處理每一箇中斷和異常的指針。

windows將硬件IRQ映射到IDT上,同時它利用IDT來爲異常配置陷阱處理器。雖然windows支持最多256個IDT項,可是支持的IRQ數據量由中斷控制機設計決定。

 

3.1.1.2 軟中斷請求級別(IRQL)

雖然中斷控制器已經實現一層中斷優先級,可是windows仍然強迫使用它本身的中斷優先級方案,稱爲中斷請求級別(IRQL)。

X86,X64,IA64中斷請求級別:

 

 

 

中斷是按優先級別來處理的高優先會搶佔低優先級中斷的執行權,當一個高優先級中斷髮送,處理器會把中斷線程上下文保存起來,並調用與中斷相關的陷阱分發器,陷阱分發器提高IRQL,並調用中斷服務例程,調用完成後下降IRQL,回到中斷髮送前,被中斷線程運行。可是當有其餘,低優先級中斷時,當IRQL下降,低優先級中斷出現。這樣,內核會恢復到上述過程來處理中斷。

 

線程優先是線程的屬性,IRQL是中斷源的屬性。每一個處理器的IRQL設置能夠隨系統代碼的執行變化。

每一個處理器的IRQL設置決定了該處理器能夠接收哪些中斷。當一個內核模式線程運行時,能夠經過KeRaiseIrql和KeLowerIrql來提高和下降處理器IRQL或經過調用內核同步對象的函數間接提升或者下降IRQL。當處理器的IRQL高於中斷源則被屏蔽,不然被中斷打斷。

訪問。

由於訪問PIC(中斷控制器)比較慢因此引入了優化技術延遲IRQL以免訪問PIC。當IRQL被提高,HAL記下新的IRQL而不是去修改中斷屏蔽值。當一個較低中斷髮生則HAL將中斷屏蔽值設置爲對於第一個中斷正常的值。這樣當IRQL被提高的時候沒有更低優先級中斷,則HAL須要修改PIC。

一個內核模式線程根據請求,來下降和升高處理器IRQL。當中斷髮生時,陷阱處理器(或處理器自己)將改處理器的IRQL提高到中斷源的IRQL.這樣會把等於或者低於它的全部中斷都屏蔽。保證了不被低級中斷截掉。被屏蔽的中斷由其餘處理器處理或者被保存下來知道IRQL降低。

所以系統組件包括內核和設備驅動,都試圖讓IRQL保持在被動級別。這樣能夠提升設備啓動能夠更加及時的響應硬件中斷。

每一箇中斷級別都有特定的目的,如內核發出一個處理器間的中斷,以請求另一個處理器執行一個動做。

將中斷映射到IRQL:IRQL級別和中斷控制器定義的中斷請求並不相同,在hal中決定一箇中斷分配給那個IRQL。而後調用HAL函數HalGetSystemInterruptVector把中斷映射到對應的IRQL。

預約義的IRQL:如下介紹一下預約義的IRQL

1.只有當內核在KeBugCheckEx中中止了系統並屏蔽全部中斷的時候,內核纔會使用高級別的IRQL。

2.電源失敗,出如今NT文檔中,可是歷來沒有使用過。

3.處理器間的中斷,用於向另一個處理器請求執行一個動做。

4.時鐘,主要用於系統時鐘,內核利用該黃總段級別來跟蹤具體時刻,以及現場測量或者分配cpu時間。

5.性能剖析(Profile),當內核的性能剖析功能被打開的時候,內核性能剖析陷阱處理器會記錄下中斷髮生時被執行的代碼的地址。(性能剖析器Kernrate)

6.設備IRQL,用來對設別中斷優先級分區

7.DPC/Dispath級別和APC級別是由內核和設備驅動程序產生的軟中斷。

8.被動級別,最低的IRQL優先級別,它不是一箇中斷級別,它是普通線程運行時設置的,容許全部中斷髮生。

對於DPC/Dispatch級別或者更高級別上的代碼,一個重要的限制是它不能等待一個對象。另一個限制DPC/Dispatch或者更高級別的IRQL只能訪問非換出頁內存。若2個限制都違反了系統會崩潰,代碼爲IRQL_NOT_LESS_OR_EQUAL。在驅動上違反限制是一種常見的錯誤。在驅動上違反限制上一種建立的錯誤。

中斷對象,內核提供了一種可移植的機制使得設備驅動程序能夠爲它們的設備註冊ISR。這是一個稱爲中斷對象的內核控制對象。

中斷對象包含了全部「供內核將一個設別的ISR與一個特定級別的中斷關聯起來的全部信息」,包含該ISR的地址,該設備中斷時所在的IRQL級別,以及內核中該ISR關聯的IDT項。

駐留在中斷對象中的代碼調用了實際的中斷分發器,通用是內核的KiInterruptDispatch或者KiChainedDispatch例程,並將指向中斷對象的指針傳遞給它。

下圖顯示了中斷控制流:

 

 

 

將ISR與特定中斷級別關聯起來的稱爲鏈接一箇中斷對象,將ISR與IDT項斷開關聯稱爲斷開一箇中斷對象。這些操做經過內核函數IoconnectInterrupt和IoDisconnectInterrupt完成。

3.1.1.3 軟中斷

雖然大多數中斷都是硬件產生,可是windows內核也爲各類各樣的任務產生軟中斷。包括:

1.激發線程分發

2.非時間緊急中斷處理

3.處理器定時到期

4.特定線程的環境中異步執行一個過程

5.支持異步I/O操做

分發或者延遲過程調用(DPC)中斷,當一個線程不能繼續執行的時候,好比由於線程已經終止了或者主動進入等待狀態,內核就會直接調用分發器,從而當即致使一個環境切換。可是有時檢測到線程已深刻到許多層代碼中,這時應該進行從新調度,這種狀況下內核請求分發,可是將它推遲到完成了當前的行爲以後再進行。

當齧合對共享的內核數據訪問,會把IRQL拉到DPC/Dispatch級別當內核檢查到須要分發的時候,請求一個DPC/Dispatch中斷。因此只有當內核完成了當前的活動,把IRQL拉低,分發中斷才能處理。

延遲事務也在這個IRQL上運行,DPC是完成一項系統任務,可是不是那麼緊迫,這些函數被稱爲延遲的,是由於不會了當即執行。

DPC賦予操做系統一種能力,產生一箇中斷而且在內核模式下執行系統函數。內核利用dpc來處理定時到期,以及一個線程的時限到期之後從新調度處理器。爲了給硬件中斷提供及時的服務,windows視圖把IRQL保持在低於設備IRQL之下。爲了達到這個目的,讓設備驅動程序ISR執行最少必要的工做來響應他們的設備,將異變的中斷狀態保存起來,並將數據傳輸非時間緊迫的中斷處理推遲到 DPC/Dispatch IRQL級別上的DPC中在執行。

DPC是經過DPC對象來表示的,DPC對象是內核控制對象,對於用戶模式不可見,對於設備驅動和內核代碼是可見的。DPC對象包含最重要的信息是DPC中斷將要調用哪一個系統函數地址。正在等待的DPC被存放在隊列中,每一個處理器都有一個隊列稱爲DPC隊列。要想請求一個DPC,系統會初始化DPC對象,而後放入DPC隊列中。

默認狀況下內核把DPC對象放在發生該DPC請求的處理器的DPC隊列末尾。在設備驅動程序只需指定一個DPC優先級別和指定特定CPU,就能夠改變這種默認方式。指定在某個CPU上叫定向DPC。若是一個DPC的優先級爲低級或者中級則放入隊列尾,不然放入隊列頭部。

當處理器的IRQL從DPC/Dispatch或更高降到某個更低的級別時,內核處理DPC。在處理DPC是IRQL在DPC/Dispatch級別上,而且將DPC來出來運行直到隊列爲空。當隊列爲空內核才讓IRQL下降到DPC/Dispatch如下。讓正常的線程執行過程繼續執行。

 

 

 

DPC優先級能夠以另外一種方式影響到系統行爲。內核一般經過一個DPC/Dispatch級別的中斷來激發隊列「抽乾」的動做。只有當一個DPC被定爲在ISR所在的處理器上,且改DPC的優先級是高級或者中級時,內核才產生一箇中斷,若爲低級只有當DPC請求到一個閥值或一段時間後,內核纔會請求中斷。

若DPC被定爲在一個不一樣於其ISR運行的CPU上,並DPC爲高級。內核當即用一個信號通知CPU,以便」抽乾」它的DPC隊列。若優先級爲中級或者低級則DPC數據超過閥值,內核纔會激發一個DPC/Dispatch中斷。

DPC中斷產生的規則:

DPC優先級別

DPC被定爲在ISR的處理器上

DPC被定爲在另外一個處理器上

低級

DPC隊列長度超過最大的DPC隊列長度值,或者DPC請求率小於最小的DPC請求率。

DPC隊列長度超過最大的DPC隊列長度或者系統空閒

中級

老是激發

DPC隊列長度超過最大的DPC隊列長度或者系統空閒

高級

老是激發

老是激發

DPC主要爲設備驅動提供的,可是內核也使用DPC,內核使用DPC來處理限時到期事件。在系統時鐘每一個」嘀嗒」點上,就發生一個時鐘IRQL級別的中斷。時鐘中斷處理器對系統時間進行更新,將一個記錄了當前線程運行多長時間的計數器遞減。當計數器減到0,線程到期,內核可能須要從新調度該處理器,這個任務在DPC/Dispatch IRQL上完成。

時鐘中斷處理器將一個DPC插入到隊列中以便激發分發過程。而後結束他的工做而且下降IRQL,由於DPC中斷級別較低,因此在時鐘中斷完成前出現還沒有處理的設備中斷,都在DPC中斷以前被處理。

APC異步調用,異步過程調用提供了一種在特定用戶線程環境中執行用戶程序和系統代碼的途徑。APC通過排隊以便在特定線程的環境中執行。

APC是由一個內核控制對象(APC對象)來描述的,正在等待執行的APC駐留在一個由內核管理的APC隊列中。APC隊列是特定線程相關的,即每一個線程有它本身的APC隊列,當內核請求要將APC排隊時,它將一個APC排隊,她將APC插入到未來執行此APC例程的那個線程的隊列中。當內核請求APC級別中斷,當該線程最終開始執行的時候,會執行此APC。

有2種APC:內核和用戶模式。內核模式的APC並不要求從目標獲取許可就能夠運行在改線程的環境中,而用戶模式必須先獲取許可。內核模式的APC有普通和特別2種,將IRQL提高到APC級別或調用KeEnterGuardRegion,就能夠靜止這兩種類型的內核模式APC。

執行體使用內核模式的APC來完成那些必需要在特定線程的地址空間(執行環境)中才能完成的操做系統任務。它能夠利用特殊的內核模式APC來指示某個線程中止執行一個可中斷的系統服務。

用戶模式APC(ReadFileEX,WriteFileEx和QueueUserApc),如ReadfileEx,WritefileEx容許調用者指定一個完成例程,當I/O完成是例程就會被調用。I/O完成機制是經過I/O的線程插入一個APC來實現的。內核APC運行在APC級別上,用戶模式APC運行在被動級別上。

APC交付會致使等跌隊列從新排序,如APC用來把等待資源的線程掛起,那麼該線程就會進入等待訪問這個資源隊列的末尾。

3.1.2 異常分發

中斷能夠在任什麼時候候發生,異常則是直接由當前正在運行的程序產生。windows引入了一種稱爲結構化異常處理的設施,應用程序能夠在異常發生時得到控制,而後應用程序能夠修正條件,並返回到異常發生處,將棧展開(使引起異常的子例程執行過程當中止),或想系統報告,改異常不可識別,由於系統應該繼續搜索一個有可能處理此異常的異常處理器。

x86上全部異常都在預約義的中斷號,這些中斷號對應IDT項。每一個項指向了某個特定異常的陷阱處理器。

全部異常,除了簡單的經過陷阱處理器,能夠解決的以外,其餘都由異常分發器的內核模塊服務。異常分發器就是找到一個異常處理器,處理要處理的異常。

異常處理對用戶來講都是透明的,有些異常也容許原封不動的回到用戶模式。如內存訪問違例,算法溢出,操做系統不對他們處理。環境子系統能夠創建起基於幀的異常處理器來處理異常。

基於幀是將一個異常處理與一個特定的過程激活動做關聯起來。當一個過程被調用,表明該過程的幀被壓到棧中。一個棧幀能夠關聯多個異常處理器,每一個異常處理器保護源程序中一塊特定代碼。當發生一個異常時,內核查找與當前幀關聯在一塊兒的某個異常處理器。若是沒有找到內核繼續查找與上一個棧幀關聯在一塊兒的某個處理。若是最終仍是沒有找到異常處理器,內核會調用本身默認的異常處理器。

異常發生,CPU硬件將控制權遞交給內核陷阱處理器,內核陷阱處理器建立一個陷阱幀。正因爲陷阱幀處理完異常後,系統能夠從中止的地方恢復。

若是在內核模式下的異常,異常分發器調用一個例程來找到一個基於幀的異常處理器。由它來處理異常。

在用戶模式下,windows子系統有一個調試器端口和異常端口,經過它們來接收windows進程中用戶模式異常的通知。內核在它默認的異常處理器中用了這些端口。

 

 

 

調試器端口是最多見的異常來源,所以異常分發器採起動做,

1.查看引起該異常的進程是否有一個相關的調試器進程。若存在異常分發器發送一個調試器對象信息到調試對象相關的進程。

2.若該進程沒有附載的調試器進程或調試器並無處理該異常,那麼異常分發器切換到用戶模式下。將陷阱幀按照Context數據結構的格式拷貝到用戶棧中,並調用一個例程來找到一個基於幀的異常處理器。

3.若是沒有找到或者雖然找到了可是它不處理該異常,則異常分發器切換到內核模式下,而且再次調用調試器,以便讓用戶作更多的調試。

4.若調試器不在運行,並無找到基於幀的處理器,那麼內核向與該線程的進程關聯在一塊兒的異常端口發送一個信息。該異常端口若是存在的話,則必定是由控制該線程的環境子系統註冊的。環境子系統監聽該端口,在恰當的時機把一個異常轉化爲一個與環境相關的信號或異常。客戶/服務器運行時子系統(CSRSS)簡單的彈出一個消息框來通知用戶發生了錯誤,而且終止進程。

5.當POSIX從內核收到一個消息,指定的一個線程產生了異常,當內核在處理異常過程走得比較深了,而子系統並無處理該異常,那麼內核執行一個默認的異常處理器,它只是簡單的將引起該異常的線程所在的進程終止掉。

未處理的異常

全部windows線程都有一個異常處理器來處理未被處理的異常。該異常處理器是在windows內部的進程啓動函數或線程啓動函數中聲明。如:

 

 

 

若是一個線程的異常沒有被處理,則windows的未處理異常過濾器將會被調用。這個函數目的是,當一個異常未被處理時,能夠提供一種系通通一的行爲和方法。

3.1.3 系統服務分發

內核陷阱處理器分發中斷,異常和系統服務調用

3.1.3.1 32位系統服務分發

在x86 Pentium II處理器以上,使用windows使用sysenter執行觸發一個陷阱,這個是intel特別爲快速系統服務定義的。爲了支持這一指令,windows在引導時刻把內核的服務分發器的地址保存與該指令相關的寄存器中。

執行該指令會致使變化到內核模式下,而且執行系統服務分發器,爲了返回到用戶模式,系統服務分發器一般執行sysexit執行(當處理器單步標記被打開,系統分發器改而使用iretd指令。)

在K6和更高的32位AMD處理器上,windows使用syscall相似於sysenter,系統嗲用號也在EAX上,而調用者參數則保存在棧中。在完成了分發以後,內核執行sysret指令。

3.1.3.2 64位系統服務分發

在64位體系結構上,windows使用syscall指令進行系統分發(和AMD處理器上syscall相似),系統調用號存在EAX寄存器,前4個參數存放在寄存器彙總其餘參數存放在棧中。

在IA64上使用EPC指令,前8個系統調用參數經過寄存器來傳遞,其餘參數經過棧傳遞。

3.1.3.3 內核模式的系統服務分發

內核利用傳遞進來的參數找到系統分發表中的服務信息(相似IDT表)。

 

 

 

系統服務分發器KiSystemService將調用的參數從用戶模式棧中複製到內核模式,而後執行服務。若是換地給一個系統服務的參數指向了用戶空間中的緩衝區,那麼在內核模式代碼複製到緩衝區或從緩衝區讀前先要查明緩衝區是否能夠訪問。

每一個線程都有一個指針指向它的系統服務表,windows有2個系統服務表,最多能夠支持4個。系統服務分發器肯定哪一個表包含了全部請求的服務,它將32位系統服務號中的其中2個位解釋成一個索引表。系統服務號低12位被用在該表索引所指定的表中進行的索引。

 

3.1.3.4 服務描述符表

一個主要的默認數組表(KeDescriptorTable)定義了Ntosrknl.exe中實現的核心執行體系統服務。另外一個默認數組表(KeserviceDeseriptorTableShadow)包含了在windows子系統的內核模式部分win32.sys中實現的windows user和GDI服務。

當windows線程第一次調用一個windows user和GDI服務,該線程的系統服務表的地址被指向一個包含windows user和GDI服務的表格。KeAddSystemSericeTable可讓win32.sys加入到系統服務表中。

針對windows執行體服務的系統服務分發指令位於NTdll.dll中。子系統調用Ntdll.dll來實現。windows user和GDI函數,在這些函數中,系統分發指令是直接在user32.dll和GDI.dll中實現,沒有涉及ntdll.dll。

 

3.2 對象管理器

windows實現了一個對象模型,以便爲執行體的實現各類內部服務提供了一致的,安全的訪問路徑。執行體內部複製建立,刪除,保護和跟蹤對象的組件(windows對象管理器)。

對象管理器把本來可能散落在整個系統各處的資源控制操做集中在一塊兒。對象管理器的設計意圖是爲了實現本章稍後列出的一些功能。

1.提供一種公共,同一個的機制來使用系統資源

2.將對象保護隔離到操做系通通一的區域中,從而能夠作到c2安全等級

3.提供一種來記錄進程使用對象數量的機制,從而能夠對系統資源的使用上加限制。

4.簡歷一套對象命名方案,能夠很方便的融合現有對象。

5.支持各類操做系統環境的須要

6.簡歷統一的規則來維護對象的保持力。

windows內部有兩種類型的對象:執行體對象和內核對象。

執行體對象是指執行體的各類組件所實現的對象(如,進程管理器,內存管理器,I/O子系統)內核對象是指windows內核實現的一組更爲基本的對象。這些對象在執行體內部被建立和使用。

 

3.2.1 執行體對象

每一個windows環境子系統老是把操做系統的不一樣面貌呈現給它的應用程序。執行體對象和對象服務是環境子系統用於構建其本身版本的對象和其餘資源基礎。

執行體對象每每由在用戶應用程序中通常的環境子系統或由操做系統的組件做爲他們常規操做的一部分而建立。如爲了建立一個文件,windows應用程序調用windows的createfile函數,該函數在windows子系統DLL kernel32.dll中現實中實現的,在通過了一些驗證和初始化工做之後,createfile會調用原生的windows服務ntcreatefile來建立一個執行體文件對象。

windows子系統使用執行體對象來導出它本身對象集合,其中許多對象直接對應於執行體對象。

暴露給windows api的執行體對象:

對象類型

所表明的含義

符號連接(Symbolic link)

間接的引用一個對象名字的機制

進程(Process)

虛擬地址空間,以及爲了執行一組線程對象而必需的控制信息

線程(Thread)

進程內部的一個可執行實體

做業(Job)

指一組進程,經過做業機制,能夠像單個實體那樣來管理他們

內存區(section)

共享內存的一個區域(在windows中也稱爲文件映射對象)

文件(File)

一個已打開的文件或者I/O設備的實例

訪問令牌(Access token)

一個進程或者線程的安全輪廓(安全ID,用戶權限等)

事件(Event)

一個具備持久狀態(有信號,或者無信號的)的對象,可被用於同步或者通知。

信號量(Semaphore)

信號量是一個計數器,它提供了資源門控能力,對該信號量所保護的資源只容許某個最大數目的線程來訪問它。

互斥體(Mutex)

用於順序訪問一個資源的一種同步機制

定時器(Timer)

這是一種當固定長時間過去時,通知一個線程的機制

IO完成(IoCompletion)

使線程可以將」I/O操做完成通知」進出隊列的一種方法,在windows中稱爲IO完成端口。

鍵(Key)

這是一種引用註冊表中數據的機制。

窗口站(WindowStation)

該對象包含了一個剪貼板,一組全局原子和一組桌面對象

桌面(Desktop)

這是一個被包含在窗口站內部的對象。桌面對象有一個邏輯顯示器表面,其中包含了窗口,菜單和鉤子。

3.2.2 對象結構

每一個對象都有一個對象頭和對象體,對象管理器控制了對象頭,而執行體組件則控制了由它們建立的對象類型的對象體。每一個對象頭指向一個進程列表,類表中每一個進程都打開了此對象。對象類型指向了稱爲類型對象的特殊對象。

 

 

 

3.2.2.1 對象頭和對象體

對象管理器使用對象頭中保存的數據來管理這些對象,而無須關係它們的類型。

標準對象頭的屬性:

屬性

用途

對象名稱

使一個對象對於其餘的進程也是可見的,以便於共享

對象目錄

提供了一個層次結構來存儲對象名稱

安全描述符

決定誰可使用該對象,以及容許它們如何使用它(注:對於沒有名稱的對象來講,安全描述符是空[null])

配額花費

列出了當一個進程打開一個指向該對象的句柄時,針對該進程收取的資源花費額

已打開句柄的計數

記錄了「打開一個句柄來指向該對象」的次數

已打開句柄的列表

指向一個進程列表,其中每一個進程都打開了指向該對象的句柄。

對象類型

指向一個類型對象,該對象包含了正對這個類型的對象都是公共屬性

引用計數

記錄了一個內核模式組件引用該對象地址的次數

除了對象頭之外,每一個對象也有一個對象體,而且其格式和內容只有這種對象類型纔有,同一類型的全部對象共享一樣的對象體格式。一個執行體組件經過建立一個對象類型,而且爲它提供一些服務,就能夠控制和維護全部這個類型的對象體中的數據。

對象管理器提供了少許經過服務,經過這些服務能夠對一個對象頭中保存的屬性進行操做,經過服務能夠用再任何類型的對象上。

雖然通用的對象服務都支持全部對象類型,可是每一個對象都有它本身的建立,打開和查詢服務。

3.2.2.2 對象類型

對象頭中包含的數據對於全部對象都是公共的,可是每一個對象實例能夠取不一樣的值。

爲了節省內存,對象管理器只在建立一個新的對象類型時纔會存儲靜態的,特定於對象類型的屬性。

進程對象和進程類型對象:

 

 

 

類型對象的屬性

屬性

用途

類型名稱

此種類型的對象名稱(「process」,」event」,」port」)

池類型

指明瞭這種類型的對象是從換頁的仍是非換頁的內存中分配

默認的配額花費

默認從進程配額中扣除的換頁內存池值和非換頁內存池值

訪問類型

當一個線程打開某個指向該類型的對象時能夠請求的訪問類型(「讀」,」寫」,」終止」,」掛起」)

通用訪問權限的映射關係

在4種通用的訪問權限和屬於該類型的訪問權限之間的映射關係。

同步

指明瞭一個線程是否能夠等待這種的對象

方法

在一個對象的生命週期的特定點上,對象管理器自動調用的一個或者多個例程。

一個對象可否支持同步,取決於該對象是否包含了一個內嵌的分發器對象,在「低IRQL的同步」中有介紹。

3.2.2.3 對象方法

上面的表中,最後一個屬性就是方法。方法是由一組內部例程構成的,這些例程相似構造和解析函數(在建立和銷燬時被使用)。

當一個執行體組件建立了一個新的對象類型時,它能夠像對象管理器註冊一個或多個方法,對象管理器在此種類型的對象生命週期中,某些明肯定義的點上調用這些方法。

對象方法:

方法

什麼時候調用

Open

當一個對象句柄被打開

Close

當一個對象句柄被關閉

Delete

在對象管理器中刪除一個對象以前

Query name

當一個線程在一個從屬名字空間中查詢一個對象的名稱時

Parse

當對象管理器在一個從屬名字空間中搜索一個對象名稱時

Security

當一個進程讀寫(如文件)在其從屬名字空間中的保護屬性時。

3.2.2.3.1 Open函數

對象管理器建立一個指向對象的句柄時會調用open方法,在對象被建立或者打開時候運行。只有一個對象類型(windowstation)定義了open方法。這樣win32.sys可以與服務於桌面相關內存池的進程共享內存。

3.2.2.3.2 Close函數

close方法的例子是IO中,對象管理器關閉一個句柄使用close方法。close方法先檢查看正在關閉該文件句柄進程是否有任務用於該文件而且未完成的鎖,若是有則除去鎖。

3.2.2.3.3 Delete函數

對象管理器在內存中刪除臨時對象之前,調用delete方法。內存管理器爲內存區對象類型註冊了delete方法,它會釋放該內存區使用的物理頁面。並在刪除內存區對象前驗證一下內存管理器爲該內存區所分配的任何內部數據結構已被刪除了。

3.2.2.3.4 Parse函數(相似於Query name)

若發現對象存在於對象管理器名字空間外,容許對象管理器把查找一個對象的控制權交給一個從屬的對象管理器。若在搜索路徑上碰到一個關聯了parse的對象,會暫停搜索。對象管理器調用parse方法。將正在搜索的對象名稱的剩餘部分傳給parse方法。除了對象管理器方法外在windows中還有註冊表名字空間和文件系統名字空間。例如打開一個名爲\Device\Floppy0\docs\resume.doc的文件句柄,對象管理器遍歷它的名稱樹,直到到達Floppy0。調用parse,把\docs\resume.doc傳入。I/O管理器的parse例程接受名稱,而且傳給文件系統,文件系統找到文件並打開。

3.2.2.3.5 Security方法

Security也是I/O系統使用方法,相似parse。一旦一個線程視圖查詢或改變那些用於保護一個文件的安全信息時,該方法就會被調用。安全信息是存儲在文件對象中,而不是內存,所以必須調用I/O系統才能找到安全信息,並將它們讀出來或進行修改。

3.2.2.4 對象句柄和進程句柄表

當進程根據名稱來建立或者打開一個對象時,它會接受到一個句柄,經過句柄來訪問一個對象,要比使用名稱訪問快得多。由於對象管理器能夠跳過名稱查找過程,直接找到目標對象。進程也能夠在其建立時刻經過繼承句柄的方式得到句柄或從另外一個進程接收一個複製的句柄。

全部的用戶模式進程在其線程使用一個對象之前,必須先擁有一個指向該對象的句柄。句柄被用作指向系統資源的間接指針,這樣可讓應用程序不與系統數據結構直接交互。

對象句柄仍是提供了額外的一些好處:第一,不一樣句柄沒有什麼區別可使用統一的接口來引用。第二,對象管理器有獨立的權利來建立句柄,查找句柄。也就是對象管理器能夠仔細地審查每一個可能會影響對象的用戶模式動做。

對象句柄是索引與進程相關的句柄表中的項相關。執行體進程(EPROCESS)塊中一個域指向句柄表。句柄表實現方式是3層和虛擬地址到物理地址映射相似。

當進程被建立對象管理器分配了句柄表的最高層結構,其中包含了指向中間層表的指針;同時也建立了中間層,其中包含了第一個指向子句柄表的指針數組,還分配了最底層,其中包含了第一個子句柄表。

 

 

 

把低24位當作3個8位,分別索引到3層結構中的一層。在xp,2003在進程建立時,最底層句柄表被分配,其餘的都會被按需分配。在windows 2000中一個子句柄表是255個可用表項。在xp,2003表項=(頁大小/表項大小)-1。在windows xp,2003上句柄表項:

 

 

 

P:說明了調用者是否容許關閉句柄。I:該進程建立的子進程是否在它們句柄表中有一份該句柄的拷貝。A:關閉該對象時是否應該產生一個升級信息(對象管理器內部使用該標記)。

系統組件和設備驅動程序一般須要打開一些不該該讓用戶訪問的對象。能夠經過內核句柄表來表示。內核句柄表只有在內核模式下能夠飛昂文,能夠在任何進程環境下。

對象管理器看到一個句柄的高位被設置時,就會將它識別爲內核句柄表中的句柄。也就是說內核句柄表中的句柄的引用值大於0x80000000。在windwos 2000中內核句柄表是一張獨立的句柄表,可是在xp和2003中,內核句柄表也被用作system進程的句柄表。

3.2.2.5 對象安全性

當一個進程打開一個句柄,對象管理器調用安全引用監視器,監視該對象描述符是否容許該進程所請求的訪問類型,若容許,引用監視器返回一組准許的訪問權限,同時對象管理器放入它建立的對象句柄中。

當下次進程要使用句柄時能夠快速的檢查這一組句柄中的准許訪問權限。

3.2.2.6 對象保持力

對象保持力,分爲暫時和永久的。暫時是當須要的時候使用,不須要的時候釋放。永久是一直保持知道被顯式釋放。

對象管理器經過兩個階段來實現對象保持力。第一階段稱爲名稱保持力,第二個階段,再也不有用時,中止保留對象自己(也就是刪除)。

名稱保持力:當一個進程打開一個對象的句柄。會在該對象頭信息中的已打開句柄計數器+1。當用完關閉句柄,對象管理器已打開句柄-1,。當計數器爲0,對象管理器從全局名字空間中刪除該對象名稱。

再也不有用時刪除:對象專門提供一個引用計數來記錄。

已打開句柄計數器:當進程打開一個對象句柄+1,關閉句柄-1

引用計數:提供一個對象指針+1,用完了-1

當已打開計數器爲0,引用計數大於0.表示對象還在使用。當引用計數爲0,對象管理器會從內存中將它刪除。

 

進程A,進程B和內核結構引用了一個對象,所以handlecount=2,referencecount=3。

3.2.2.7 資源記帳

windows對象管理器提供了一箇中心設施來實現資源記帳。每一個對象頭都包含了配額花費。

windows每一個進程都指向一個配額的數據結構,配額爲0表示不限制。

3.2.2.8 對象名稱

對象名稱能夠知足1.區分對象之間的方法。2.找到並得到特定對象的方法。3.容許程序間共享。

只有2種狀況會使用名稱進行查找,1.建立一個命名對象時,會經過名稱查找,驗證全局名稱空間中不存在。2.當打開一個句柄,句柄指向一個命名對象時,對象管理器查找該名稱並返回一個對象句柄。

對象的名稱存儲位置取決於對象類型

目錄

所存儲對象名稱的類型

\GLOBAL??

Ms-dos設備名(\DosDevices是指向此目錄的符號連接)

\BaseNameObjects

互斥體,時間,信號量,可等待的定時器和內存區對象

\Callback

回調對象

\Device

設備對象

\Driver

驅動程序對象

\FileSystem

文件系統驅動程序對象和文件系統識別器對象

\KnowDlls

已知DLL(在啓動時候由系統映射的DLL)的內存區名稱和路徑

\Nls

已映射的國家語言支持表的內存區名稱

\ObjectTyoes

對象類型名稱

\RPC Control

遠程過程調用(RPC)所使用的端口對象

\Security

與安全子系統相關的對象的名稱

\Windows

Windows子系統的端口和窗口站

對象的名稱相對於一臺計算機而言是全局的,可是他們的跨越網絡是不可見的。可是對象管理器解析名稱的方法使得有可能訪問其餘機器上的命名對象。

對象目錄是對象管理器支持這種層次型命名結構手段。對象目錄解析對象名稱爲指向對象的指針。對象管理器利用指針來構建對應的句柄,將這些對象句柄返回給用戶模式的調用者。

符號連接,在某些文件系統中,經過符號連接,用戶能夠建立一個文件名或一個目錄名,當被使用的時候,實際上被操做系統轉譯成另一個不一樣的文件或文件名。使用符號連接,是一種讓用戶間接的共享一個文件或目錄的內容。

符號連接對象,完成的功能相似於對象名稱的功能同樣。當對象名稱中有符號連接,對象管理器遍歷它的對象名稱空間,找到該符號連接對象,並找到一個取代該符號連接名的字符串。

3.2.2.9 會話名稱空間

一個登錄到控制檯會話上,用戶能夠訪問全局名稱空間,另外會話能夠得到該名稱空間的私有名稱空間實例。\DosDevices,\Windows,\BaseNamedObjects屬於會話局部的名稱空間,都會被放在私有名稱空間中。將名稱空間中相同部分複製,來初始化名稱空間。

對象管理器在\session\X下建立私有版本,對象管理器以透明的方法,將對象的名稱從\BaseNameObjects重定向到\session\2\BaseNamedObjects。

windows子系統DLL將windows應用程序傳過來的位於\DosDevice中對象引用加上\??前綴(c:\windows變成\??\c:\windows)。依賴於EPROCESS中DeviceMap。DeviceMap結構中DosDevicesDirectory域所指的對象目錄管理器表明了進程的局部DosDevices。

在windows 2003和xp上,系統沒有將全局對象拷貝到局部DosDevices目錄中,當看到\??會經過DeviceMap中DosDevicesDirectory找到該進程局部\DosDevices目錄。若在局部中沒有,而且DeviceMap有效,則會在GlobalDosDevicesDirectory查找對象。

當會話中的應用程序要與其餘會話的實例同步在任何對象名稱前加入\Global\ApplicationInitialized被重定向到\BasedNameObjects\ApplicationInitized而不是\Sessions\2\BaseNamedObjects\ApplicationInitialized。

在2003和xp中應用程序只要在\DosDevices中沒有這樣的對象就會訪問全局,不須要使用\Global。

3.3 同步

當一個資源不容許共享訪問,或共享訪問致使不可預測的後果則須要互斥。若一段代碼訪問了一個不可共享的資源,則這樣的代碼區成爲臨界區。

3.3.1 高IRQL的同步

在內核執行的各個階段,內核必須保證,在臨界區內部同一時刻只有一個處理器在執行。

在中斷髮生,內核可能在更新一個全局數據結構,而中斷的處理例程可能也要修改此數據結構。在單處理器,能夠用如下方式來避免。如,當線程修改全局數據結構時,禁止全部中斷。windows的做法是執行臨界區時,把IRQL拉高會用到該數據結構的最高IRQL。

3.3.1.1 互鎖操做

這個最簡單的同步方式,依賴於支持多處理器硬件,操做一個整型值來進行比較。

3.3.1.2 自旋鎖

自旋鎖是內核用來實現多處理器互斥的機制

 

在windows中,全部內核模式自旋鎖都有一個與之關聯的IRQL。當運行自旋鎖就會拉高IRQL。

3.3.1.3 排隊自旋鎖

工做方式:當一個處理器要得到已被其餘處理器持有的隊列自旋鎖鎖時,把本身的標示符放入一個與該自旋鎖關聯的一個隊列中。

當自旋鎖被釋放,將鎖交給隊列中第一個標示符對於的cpu。

在同時處理器等待一個較忙的自旋鎖不是檢查自旋鎖自己而是每一個處理器的標誌。在隊列中位於它以前的處理器會對它設置,代表輪到這個等待的處理器了。

排隊的自旋鎖的天然結果是,他們在每一個處理器標識符上旋轉,而不是全局自旋鎖上旋轉有2個效果:

1.多處理器總線不會由於處理器之間的同步招致繁重的流量。

2.排隊增強了先進先出的順序,處理器之間性能更加一致。

在windows中定義了不少全局隊列自旋鎖,而且在每一個處理器的「處理器控制區域(PCR)」包含了一組數組(保存了指向這些全局隊列的自旋鎖指針)。當調用KeAcquireQueueSpinLock的時候將一個PCR的索引傳進去,能夠得到對應的全局自旋鎖。

3.3.1.4 棧內排隊自旋鎖

除了使用全局定義的靜態排隊自旋鎖,xp和2003還提供了KeAcquireInstackQueuedSpinlock和KeReleaseInstackQueuedSpinlock。來支持動態分配的排隊自旋鎖。

3.3.1.5 執行體的互鎖操做

內核提供了不少簡單的創建在自旋鎖基礎上的同步函數。

3.3.2 低IRQL的同步

自旋鎖使用有嚴格的限制:

1.對於受保護的資源,必須快速訪問,不要與其餘代碼有複雜的交互關係

2.臨界區代碼的內存頁不能換出去,不能引用可被換頁的數據,不能調用外部過程,不能中斷或異常。

在自旋鎖不適合是可用:內核分發器對象,快速互斥體和受限互斥體,壓棧鎖,執行體資源。

 

是否暴露給設備驅動程式使用

禁止常規的內核模式APC

禁止特殊的內核模式APC

支持遞歸獲取操做

支持共享的和獨佔的獲取操做

內核分發器互斥體

內核分發器信號量

快速互斥體

受限互斥體

壓棧鎖

執行體資源

3.3.2.1 內核分發對象

內核之內核對象的形式,向執行體提供了額外的同步機制,這些內核對象合起來統稱爲分發器對象。每一個支持同步的用戶可見對象都封裝了至少一個內核分發器對象。

 

3.3.2.1.1 等待分發器對象

一個用戶模式的線程等待一個事件對象的句柄。

內核將該線程的調度狀態從就緒狀態改變成等待狀態,而後將該線程加入到正在等待該事件的線程列表中。

另一個線程設置了該事件,內核沿着該事件的等待線程隊列向前搜索。如有一個線程等待條件知足將線程狀態從等待改成就緒。如果一個可變優先級的線程,則內核可能也要提高它的執行優先級。

由於一個新線程已經變成就緒執行狀態,因此進行從新調度。若是它找到一個正在運行的線程。其優先級低於就緒線程的優先級。那麼會搶佔此低優先級的線程,而且發出一個軟中斷,以便激發一個環境切換,切換到高優先級的線程中。

若是沒有處理器能夠搶佔的話,則分發器將該就緒線程放到分發器就緒隊列中,之後再被調度。

3.3.2.1.2 若是Signals一個對象

3.3.2.1.3 數據結構

typedef struct _DISPATCHER_HEADER {

UCHAR Type;

UCHAR Absolute;

UCHAR Size;

UCHAR Inserted;

LONG SignalState;

LIST_ENTRY WaitListHead;

} DISPATCHER_HEADER;

typedef struct _KWAIT_BLOCK {

LIST_ENTRY WaitListEntry;

struct _KTHREAD *RESTRICTED_POINTER Thread;

PVOID Object;

struct _KWAIT_BLOCK *RESTRICTED_POINTER NextWaitBlock;

USHORT WaitKey;

USHORT WaitType;

} KWAIT_BLOCK, *PKWAIT_BLOCK, *RESTRICTED_POINTER PRKWAIT_BLOCK;

每一個分發器對象都有一個等待列表,列表中一項表明一個等待該對象的線程。因此當線程向一個分發器對象發出信號,內核能夠很快的肯定誰在等待對象。

等待快結構WaitListEntry指向被等待對象,Thread指向等待線程,NextWaitBlock指向下一個等待塊。

 

 

 

3.3.2.2 快速互斥體和受限互斥體

快速互斥體也成爲執行體互斥體,比互斥體對象提供了更好的性能。儘管他們也是創建在分發器事件對象基礎上的,可是若是對於快速互斥體沒有競爭的話,他們無須等待事件對象。

受限互斥體,本質上它與快速互斥體是相同的。使用了KGATE同步對象,經過調用KeEnterGuardedRegion來進制全部內核模式APC的事務,主要用戶內存管理器。

3.3.2.3 執行體資源

執行體資源是一種支持共享和獨佔訪問的同步機制,要求APC事務禁止,若是一個線程正在等待得到一個共享訪問權,則它應該等待一個與該資源相關聯的信號量,若是一個線程正在等待得到一個資源的獨佔訪問權,則應該等待一個事件。

當一個獨佔持有者經過給信號量髮型號來釋放一個資源喚醒共享訪問者。

當一個線程在等待獨佔訪問一個資源,而該資源正在被其餘線程擁有,該線程等待一個同步事件對象。

3.3.2.4 壓棧鎖

壓棧鎖是創建在KGATE同步對象基礎之上,相比快速互斥體好處是能夠按照共享的方式獨佔的模式來得到。

有兩種類型壓棧鎖:普通壓棧鎖和能感知緩存的壓棧鎖。

普通壓棧鎖:當一個線程想要得到一個普通的壓棧鎖,若還沒有被使用則壓棧鎖代碼標記爲已被佔用。若已被佔有(共享,獨佔),線程在本身棧上分配一個等待塊,將初始化等待塊中的事件對象,等待塊加入到與壓棧鎖相關聯的等待列表中。向該等待着的等待塊中的事件發出信號。

能感知緩存的壓棧鎖簡歷在基本壓棧鎖之上。爲每一個處理器分配一個壓棧鎖,而後將這些壓棧鎖和處理器關聯起來。當一個線程但願以共享方式得到壓棧鎖時,簡單的得到對應於當前處理器的那個壓棧鎖以獨佔方式得到獨佔鎖時,以獨佔模式得到每一個處理器的壓棧鎖。

壓棧鎖的使用範圍包括對象管理器和內存管理器,對象管理器中,能夠保護全局對象管理器結構和對象安全描述符,在內存管理器,他們能夠保護awe數據結構。

3.4 系統輔助線程

windows在system進程中建立了幾個線程,這些線程稱爲系統輔助線程它們表明其餘線程來完成一些工做。如DPC級別的IRQL不能運行更低IRQL級別才能執行的函數,必須將這樣的處理過程傳遞給一個低於DPC級別的IRQL的執行線程上。

設備驅動程序或執行體組件經過ExQueueWorkItem和IoQueueWorkItem把工做放到一個隊列分發器對象上,系統複製線程在該對象上尋找工做。工做包含一個例程以及一個參數,當輔助線程處理該工做,會把參數傳遞給例程。

系統輔助線程有如下三類:

延遲型輔助線程:優先級12上,處理器非緊急工做項目,當它在等待工做項目時容許棧頁面被換出到頁面文件中。

緊急型輔助線程:優先級13,處理一些緊急工做項目,始終在內存上

超緊急型輔助線程:優先級15,總在內存中。

執行體函數ExpWorkerThreadBalanceManager肯定是否建立新的緊急型輔助線程,新的線程被稱爲動態的輔助線程。建立時必須知足下列條件:

1.在緊急工做隊列下有工做項目

2.不活動的緊急型輔助線程的數目必須少於系統處理器個數

3.動態輔助線程數據少於16個。

3.5 windows全局標誌

3.6 本地過程調用(LPC)

LPC用於進程間通訊,LPC爲了如下3中方式通訊而設計:

1.短於256字節的信息能夠經過LPC發送。從發送進程拷貝到系統地址空間中,再從系統地址空間中拷貝到接收進程地址空間中。

2.若多於256字節則複製到共享內存區。

3.若超過了內存共享區,能夠直接在地址空間中讀取或寫入。

LPC有多種端口:服務器鏈接端口,服務器通訊端口,客戶通訊端口,未命名的通訊端口

 

 

 

3.7 內核事件跟蹤

一個公共的基礎設施,向內核和ETW提供痕跡數據應用程序要使用到ETW,要屬於如下3類:

1.控制器,啓動或中止,也管理緩衝區

2.提供者,爲它所能產生的事件類定義GUID,並註冊到ETW以上,並接受控制器命令,啓動,中止它所負責的事件類跟蹤。

3.消費者,選擇一個或多個會話,讀取數據。

控制器啓動內核記錄器(ETW庫)向WMI發送一個IO請求說明要開始跟蹤哪些事件類。當WMI接受到已啓動跟蹤源接收到數據就會寫入buffer,每隔一秒觸發一次寫入日誌文件。

3.8 Wow64

64位windows上win32仿真,也就是能夠在64位上執行32位,x86應用程序。以DLL形式來實現。

wow64.dll實現了文件系統重定向,以及註冊表重定向和反射

wow64cpu.dll實現了cpu從32到64,從64到32之間的切換

wow64win.dll截取了win32k.sys導出GUI系統調用

 

 

 

3.8.1 Wow64進程地址空間佈局結構

wow64進程能夠是2G,也能夠是4G虛擬空間。若沒有設置大地址空間感知標誌則最多保留2G,若開啓大地之空間感知標誌最多保留4G。

3.8.2 系統調用

Wow64.dll鉤住從32位代碼變值原生64爲系統代碼路徑,也鉤住64位原生系統須要調用至32位用戶模式代碼的全部代碼路徑。

啓動應用程序,64位ntdll.dll映射到地址空間,初始化判斷映像頭爲32位x86則加載wow64.dll映射32位ntdll.dll,創建ntdll內部啓動環境切換到32位,執行32位加載器。

64位和32位間經過wow64在之間轉換。

3.8.3 異常分發

經過wow64來轉化異常分發。

3.8.4 用戶回調

經過wow64來轉化

3.8.5 文件系統重定向

爲了下降應用程序移植代價,全部相關API將windows\system32替換爲windows\syswow64。使用文件系統重定向來實現。

線程使用wow64enable,wow64FsRedirection函數進制文件系統重定向。

3.8.6 註冊表重定向和反射

註冊表也使用重定向在註冊表上建立原生和wow642中,視圖爲了容許32和64位com組件互操做,在註冊表中某些特定部分被更新,wow64也會將這些更新映射到迎來一個視圖。

3.8.7 I/O請求

IO除了讀寫硬盤還能夠用於程序通訊,驅動程序通IoIs32bitProcess來檢測是否從一個wow64進程發出的。

3.9總結

主要介紹執行體創建起來的基本系統機制。

相關文章
相關標籤/搜索