【Windows核心原理與實現】讀書筆記(二)

來源:互聯網
上載者:User

內容:43—51頁

處理器模式

  在Intelx86處理器上,段描述符有一個2位長度的特權級:0表示最高特權級,3表示最低特權級。Windows只使用0和3兩種特權級。特權級0表示CPU處於核心模式,3表示使用者模式。處理器有許多指令只能夠在特權級0的模式下使用,例如I/O指令,操縱內部寄存器(如GDT、IDT、MSR)的指令等。在Windows中,當處理器位於使用者模式下,處理器只能訪問當前進程的地址空間。而在核心模式下,處理器不僅可以訪問當前進程的地址空間,還可以訪問系統地址空間。

  一個指令流(線程)在執行時,出現以下情況會發生模式切換:

    1、使用者模式代碼觸發了異常;

    2、使用者模式代碼在執行時發生了中斷。

    3、執行特殊的模式切換指令。

記憶體管理

         Windows系統中,0~2GB是進程地址空間,2GB~4GB是系統地址空間。為了有效管理2GB的系統地址空間,Windows在初始化時將這2GB劃分為一些固定的地區,各個地區有專門的用途。Windows核心使用了一組全域變數來記錄每個地區的邊界,系統地址初始化實際上是對這些全域變數的初始化,並相應地初始化每個地區。Windows的引導選項和系統配置(位於註冊表)可能會影響到某些地區的位置和大小。

         系統空間中主要區域包括:核心模組鏡像,PFN資料庫、換頁記憶體池、非換頁記憶體池、會話空間、系統緩衝區、系統PTE地區、系統檢視表以及頁表等。

         Windows使用Intelx86的二級或多級頁表機制來訪問虛擬記憶體。翻譯過程涉及查詢頁目錄與頁表。如果頁表項指示的一個頁面未在實體記憶體中,則觸發分頁錯誤(page fault)異常。虛擬記憶體管理器通過分頁錯誤異常將已被換出到磁碟上的資料或代碼重新帶入實體記憶體,以供訪問。Windows利用頁表機制,實現了靈活的頁面交換演算法,可以支援一個或多個頁面分頁檔,同時也實現了記憶體頁面的寫時複製(copy-on-write)特性。

         在系統空間中,不同的地區使用不完全相同的記憶體頁面管理演算法:

    1、非換頁記憶體池:初始化時已經被映射到物理頁面上,做法是按照不同的粒度,將空閑頁面連結起來。申請和釋放頁面的操作實際上是針對空閑鏈表來進行的。

    2、換頁記憶體池:Windows使用位元影像來管理頁面的分配。

    3、系統PTE地區:這部分記憶體地區存放的並非PTE,而只是表示這部分位址範圍是以PTE的形式來管理的,把PTE當成資源來管理。

  Windows執行體在這些系統記憶體地區管理的基礎上,提供了一組更小粒度(8B的倍數)的記憶體池管理,包括執行體換頁記憶體池和執行體非換頁記憶體池。這些記憶體池通過空閑鏈表記錄下每個已申請頁面中的空閑記憶體塊;當釋放記憶體時,自動與相鄰的空閑記憶體塊合并以構成更大的空閑記憶體塊。核心的其他組件通過使用執行體暴露的API函數(例如ExAllocatePoolWithTag和ExFreePoolWithTag)來使用這些記憶體池。

 

  進程地址空間是隨進程一起被建立的,進程地址空間按照其虛擬位址是否被分配或者保留來進行管理,使用者模式代碼通過Windows API函數VirtualAlloc和VirtualFree來申請獲釋放位址範圍,而核心中的虛擬記憶體管理器通過一棵平衡二叉搜尋樹來管理進程地址空間被使用的情況。樹中的每個節點VAD(虛擬位址描述符,Virtual Address Descriptor),描述了一段連續的位址範圍。

         在VAD中,有一種重要的節點類型為記憶體區對象(section object),它是Windows平台上兩個或多個進程之間共用記憶體的一種常見方式。記憶體區對象可以被映射到系統的分頁檔、可執行檔或者其他資料檔案中,也可能被映射到實體記憶體中。記憶體區對象代表了一種實體儲存體資源。

 

         記憶體管理器的另外一個重要功能是管理有效實體記憶體。在Windows的系統地址空間中,保留了一個被稱為PFN(Page frame number database,頁幀編號資料庫)的地區。每個物理頁面都對應PFN資料庫中的一項,此PFN項描述了該頁面的狀態。Windows支援8種狀態:活動、備用、已修改、已修改但不寫出、轉移、空閑、零化、壞狀態。活動是指此正在被某個進程或系統空間所使用,有一個對應的PTE指向該頁面。壞是指該物理頁面已檢測到硬體錯誤。

 

         工作集管理器要解決的是當系統中的進程需要使用大量記憶體時,記憶體管理器如何將有限的物理頁面分配給那些需要使用記憶體的進程。這裡的工作集是指一個進程當前正在使用的物理頁面的集合。每個進程都有一個工作集鏈表,其中每一項不僅記錄了物理頁面的編號,還記錄了其他屬性,包括了它的年齡。工作集管理器可以根據一些策略來選擇要修剪的進程。針對被選中的進程,選擇哪些頁面被換出到磁碟中,從而將物理頁面騰出來。工作集管理器運行在一個成為平衡集管理器的線程中,每隔1s被觸發一次,當可用記憶體太低時,也會被觸發。平衡集管理器也會定期觸發進程/棧交換器(process/stack swapper)。進程/棧交換器是另一個單獨的線程,一旦被喚醒,就會將滿足特定條件的進程和棧換入記憶體或換出記憶體。

 

進程和線程管理

         Windows優先順序分為0-31,0表示系統優先順序,為最低優先順序,僅用於零頁麵線程;1-15為動態優先順序,在某些情形下線程的動態優先順序可以在此範圍內進行微調;16-31為即時優先順序,用於處理一些即時處理任務。

         作業(Job)是一個執行體支援的核心對象,它使得一個或多個進程被當做一個整體來加以管理和控制。

         纖程(fiber)是一種使用者線程,它對於核心是不可見的,由kernel32.dll實現

 

中斷和異常

         中斷是處理器與外部裝置打交道的重要途徑,異常是處理器的正常指令流在執行過程中產生的一些特殊事件,需要緊急處理才能繼續原來的指令流。它們都會打斷一個正常的指令流,但區別在於中斷的發生與當前指令流並無實質聯絡,而異常則是當前指令流執行的直接結果。中斷是非同步,異常是同步的。

         Intelx86採用同一套陷阱機制來處理中斷和異常,它利用IDT,將每個中斷或異常同一個處理該中斷或異常的服務常式聯絡起來。Windows在此硬體機制的基礎上,提供了一種更為靈活的軟體機制,允許驅動裝置程式為特定的中斷向量添加它的插斷服務常式(ISR,Interrupt Service Routine)。一個中斷向量允許串連多個中斷對象(interrupt Object),這裡中斷對象是一種封裝了中斷服務服務常式的核心對象。因此,中斷髮生時,這些中斷對象中的插斷服務常式都有機會處理該中斷。同時,多個硬體裝置也可以共用同樣的硬體中斷向量。

         中斷控制器(如APIC)允許設定每一個硬體中斷的優先順序,但Windows中沒有使用中斷控制器的優先順序,而是規定了一套軟體中斷優先順序,稱為插斷要求層級(IRQL,Interrupt Request Level)。在Intelx86系統中,Windows使用0~31表示IRQL,數值越大,優先順序越高。處理器在運行時總有一個當前IRQL。如果發生中斷,中斷源的IRQL等於或低於當前層級,則該中斷被屏蔽,直到處理器的IRQL降下來為止。IRQL=0表示普通線程,稱為PASSIVE_LEVEL或被動層級,它的優先順序最低,可被其他任何層級的中斷打斷。IRQL=1表示非同步程序呼叫(APC,Asynchronous Procedure Call),稱為APC_LEVEL。在一個線程中插入一個APC對象可以打斷該線程的執行;IRQL=2表示處理器正在做以下兩個事情之一:進行中線程調度;正在處理一個硬體中斷的後半部分(不那麼緊急的部分),這被稱為延遲程序呼叫(DPC)。因此,IRQL=2也被稱為DISPATCH/DPC層級,也即DISPATCH_LEVEL。3~26是裝置IRQL,27~31是一些特殊的硬體中斷,包括時鐘中斷,處理器間中斷等,它們都是硬體中斷。

         DPC是一個重要的概念。它往往用來執行一些相對於當前高優先順序的任務來說不那麼緊急的事情,硬體插斷服務常式可以把一些相遇不緊急的事情放倒一個DPC對象中處理,從而縮短處理器停留在高IRQL的時間。在Windows核心中,DPC一個典型用法是定時器(Timer)的實現,在時鐘插斷服務常式,它負責處理停機時間、系統時間,以及當前線程的時間資訊等,並判斷系統的定時器數組中是否有定時器到期,若有則發出DISPATCH_LEVEL的非強制中斷請求。定時器到期是在DPC交付(deliver)過程中處理的,定時器被當做一種特殊的DPC對象而交付執行。

         APC是線程相關的常式,只能夠在特定的線程環境中被執行,因此也一定在特定的地址空間中被執行。當一個線程獲得執行權時,它的APC常式會被立刻執行。這一特性使得APC非常適合於實現各種非同步通知事件。例如,I/O的完成通知可以用APC來實現。

        

         在Intelx86處理器中,異常也是通過IDT分發的,在IDT表中,0~0x1f之間的中斷向量是Intel保留的,除了2號中斷向量保留給NMI(不可屏蔽中斷)意外,其它已經定義的中斷向量都是針對各種條件所引發的異常的。Windows為所有的異常都提供了異常處理器,有些異常直接由系統核心處理,例如分頁錯誤(0x0e異常),由虛擬記憶體管理器接管,有些異常則需要交給當前線程或Windows子系統的代碼來處理。

         在核心模式下,異常分發器首先將異常交給核心調試器來處理,如果沒有核心調試器或者核心調試器沒有處理該異常,則嘗試分發到一個基於幀的異常處理器,它將異常處理器與“棧幀”關聯了起來,因此當發生異常時,異常分發器根據當前棧中的棧幀來尋找與之關聯的異常處理器。如果未能找到這樣的異常處理器,則異常分發器則會將該異常再次交給核心調試器,如果這次異常扔未被處理,則被認為是一個嚴重錯誤,系統崩潰。

         在使用者模式下,異常分發器首先判斷進程的調試連接埠是否有效,若有效,則發送訊息至調試連接埠,然後等待應答,否則將異常交給核心調試器。如果仍然未得到處理,則將控制轉到使用者模式下,由使用者模式的異常分發器(ntdll中的KeUserExceptionDispatcher函數)尋找一個基於幀的異常處理器。如果未找到,則控制再次回到核心模式下。這一次,核心模式的異常處理器首先嘗試調試連接埠,若異常未被處理,則再嘗試當前進程的異常連接埠。串連進程異常連接埠的是Windows子系統。如果Windows子系統在異常處理的最後時刻仍有機會處理它所屬進程的異常,如果它也不能處理此異常,則該進程被終止。

 

同步

         現代作業系統中,由於多處理器、多核或者中斷等各種並發性因素的存在,同樣的代碼有肯呢過被開發執行,而資料也可能被並發訪問。在這些情況下,對於可能被並發訪問的資料進行必要的同步。根據執行環境中的IRQL大於APC_LEVEL或者等於PASSIVE_LEVEL,可以講同步機制分為“不依賴與線程的同步機制”和“基於線程調度的同步機制”兩大類。

         當IRQL大於APC_LEVEL時,Windows提供的典型的同步機制如下:

  • 提升IRQL
  • 互鎖操作
  • 無鎖單鏈表
  • 自旋鎖(忙等待)

另一類是PASSIVE_LEVEL上的線程之間的同步。Windows定義了統一的機制來支援各種線程同步原語:分發器對象(dispatcher object),其資料結構頭部為DISPATCH_HEADER。Windows Server 2003實現了以下分發器對象:

  • 事件
  • 突變體
  • 訊號量
  • 隊列對象
  • 進程對象
  • 程對象
  • 定時器對象
  • 門對象
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.