Memory
頁面錯誤後會發生什麼?
當 Linux 系統中發生缺頁時,中斷處理程序必須找出缺頁發生的原因。但是如何?
有沒有什麼特別的號碼!?如果是,該號碼記錄在哪裡?
在引發異常之前是否可以知道頁面錯誤的原因?
例如。
- Step-1
通過CPU查找原因- 第 2 步
引發異常
當記憶體訪問失敗時會發生頁面錯誤,因為 MMU 對虛擬地址的查找以無效描述符或指示缺乏權限的描述符(例如,對只讀頁面的寫入嘗試)結束。當發生頁面錯誤時,處理器會執行一些操作;詳細資訊特定於每個處理器架構,但要點是相同的:
- 切換到特權模式(例如核心模式)。
- 設置一些寄存器以至少指示故障的性質,以及故障點的程序計數器和處理器模式。
- 跳轉到記憶體中的特定地址,由寄存器指示或自身查找記憶體中的特定位置:頁面錯誤處理程序的地址。
舉個例子,在(32 位)ARM 處理器上:
- 該
dfsr
寄存器設置為描述故障的值(無論是由於讀取還是寫入,處理器指令或 DMA 等)。- 該
dfar
寄存器設置為導致故障的訪問目標的虛擬地址。- 處理器切換到中止模式(核心級特權模式之一)。
- 該
lr
寄存器在發生故障時設置為程序計數器,並且該spsr
寄存器在發生故障時設置為程序狀態寄存器(cpsr
其中包含模式位的寄存器)。- 和寄存器被儲存:它們從上次在中止模式下設置的值恢復
sp
。cpsr
- 執行跳轉到異常向量之一的異常向量。
頁面錯誤處理程序的程式碼是作業系統核心的一部分。它的工作是分析故障的原因並採取措施。它可以查閱提供有關故障性質資訊的專用寄存器,如果需要,它還可以檢查程序正在執行的指令。它還可以在MMU表中查找描述符;無效的描述符有時可以對資訊進行編碼,例如交換空間中頁面的位置。核心通過查看在每次上下文切換時更新的全域變數或寄存器的值來了解目前正在執行的任務。以下是頁面錯誤的一些常見行為:
- 有關程序的記憶體映射的數據表明該頁面處於交換狀態。核心找到一個備用物理頁面,或者通過刪除包含磁碟記憶體的頁面來獲得一個,或者通過首先將其內容保存到交換來獲得一個。然後它將數據從交換載入到這個物理頁面,並更改 MMU 表,以便導致錯誤的虛擬地址現在附加到程序的 MMU 映射中的該物理頁面。最後,核心安排切換回導致故障的指令點的程序;這次指令將成功執行。
- 有關程序的記憶體映射的數據表明該頁面是一個寫時複製頁面,並且嘗試了寫訪問。與前一種情況非常相似,核心獲得一個備用物理頁面,將數據複製到它(這裡是從只讀頁面),更改 MMU 描述符,並安排程序再次執行指令。
- 有關程序的記憶體映射的數據表明該頁面未映射,或者它沒有必要的權限。在這種情況下,核心向程序傳遞一個 SIGSEGV 信號(分段錯誤):程序的執行在信號處理程序處而不是在原始位置恢復,但原始位置保存在堆棧中。如果程序沒有 SIGSEGV 的處理程序,則終止。
通常不可能確定異常即將發生,除非知道虛擬記憶體配置並在記憶體訪問之前進行檢查。正常的操作流程是當缺頁發生時,處理器會記錄缺頁的原因。