天天看點

Linux核心記憶體管理-記憶體通路與缺頁中斷【轉】

摘要: 簡單描述了x86 32位體系結構下Linux核心的使用者程序和核心線程的線性位址空間和實體記憶體的聯系,分析了高端記憶體的引入與缺頁中斷的具體處理流程。先介紹了使用者态程序的執行流程,然後對比了核心線程,引入高端記憶體的概念,最後分析了缺頁中斷的流程。 使用者程序 fork之後的使用者态進...

簡單描述了x86 32位體系結構下Linux核心的使用者程序和核心線程的線性位址空間和實體記憶體的聯系,分析了高端記憶體的引入與缺頁中斷的具體處理流程。先介紹了使用者态程序的執行流程,然後對比了核心線程,引入高端記憶體的概念,最後分析了缺頁中斷的流程。

使用者程序 

fork之後的使用者态程序已經建立好了所需的資料結構,比如task struct,thread info,mm struct等,将編譯連結好的可執行程式的位址區域與程序結構中記憶體區域做好映射,等開始執行的時候,通路并未經過映射的使用者位址空間,會發生缺頁中斷,然後核心态的對應中斷處理程式負責配置設定page,并将使用者程序空間導緻缺頁的位址與page關聯,然後檢查是否有相同程式檔案的buffer,因為可能其他程序執行同一個程式檔案,已經将程式讀到buffer裡邊了,如果沒有,則将磁盤上的程式部分讀到buffer,而buffer head通常是與配置設定的頁面相關聯的,是以實際上會讀到對應頁面代表的實體記憶體之中,傳回到使用者态導緻缺頁的位址繼續執行,此時經過mmu的翻譯,使用者态位址成功映射到對應頁面和實體位址,然後讀取指令執行。在上述過程中,如果由于記憶體耗盡或者權限的問題,可能會傳回-NOMEM或segment fault錯誤給使用者态程序。

核心線程 

沒有獨立的mm結構,所有核心線程共享一個核心位址空間與核心頁表,由于為了友善系統調用等,在使用者态程序規定了核心的位址空間是高1G的線性位址,而低3G線性位址空間供使用者态使用。注意這部分是和使用者态程序的線性位址是重合的,經過mmu的翻譯,會轉換到相同的實體位址,即前1G的實體位址(準确來講後128M某些部分的實體位址可能會變化),核心線程通路記憶體也是要經過mmu的,是以借助使用者态程序的頁表,雖然核心有自己的核心頁表,但不直接使用(為了減少使用者态和核心态頁表切換的消耗?),使用者程序頁表的高1G部分實際上是共享核心頁表的映射的,通路高1G的線性位址時能通路到低1G的實體位址。而且,由于從使用者程序角度看,核心位址空間隻有3G-4G這一段(核心是無法直接通路0-3G的線性位址空間的,因為這一段是使用者程序所有,一方面如果核心直接讀寫0-3G的線性位址可能會毀壞程序資料結構,另一方面,不同使用者态程序線性位址空間實際映射到不同的實體記憶體位址,是以可能此刻核心線程借助這個使用者态程序的頁表成功映射到某個實體位址,但是到下一刻,借助下一個使用者态程序的頁表,相同的線性位址就可能映射到不同的實體記憶體位址了)。

高端記憶體 

那麼,如何讓核心通路到大于1G的實體記憶體?由此引入高端記憶體的概念,基本思路就是将3G-4G這1G的核心線性位址空間(從使用者程序的角度看,從核心線程的角度看是0-1G)取出一部分挪作他用,而不是固定映射,即重用部分核心線性位址空間,映射到1G之上的實體記憶體。是以,對于x86 32位體系上的Linux核心将3G-4G的線性位址空間分為0-896m和896m-1G的部分,前面部分使用固定映射,當核心使用程序頁表通路3G-3G+896m的線性位址時,不會發生缺頁中斷,但是當通路3G+896m以上的線性位址時,可能由于核心頁表被更新,而程序頁表還未和核心頁表同步,此時會發生核心位址空間的缺頁中斷,進而将核心頁表同步到目前程序頁表。注意,使用vmalloc配置設定記憶體的時候,可能已經設定好了核心頁表,等到下一次借助程序頁表通路核心空間位址發生缺頁時才會觸發核心頁表和目前頁表的同步。 

Linux x86 32位下的線性位址空間與實體位址空間 

(圖檔出自《understanding the linux virtual memory manager》) 

Linux核心記憶體管理-記憶體通路與缺頁中斷【轉】

缺頁 

page fault的處理過程如下:在使用者空間上下文和核心上下文下都可能通路缺頁的線性位址導緻缺頁中斷,但有些情況沒有實際意義。

如果缺頁位址位于核心線性位址空間 

如果在vmalloc區,則同步核心頁表和使用者程序頁表,否則挂掉。注意此處未分具體上下文

如果發生在中斷上下文或者!mm,則檢查exception table,如果沒有則挂掉。

如果缺頁位址發生在使用者程序線性位址空間 

如果在核心上下文,則查exception table,如果沒有,則挂掉。這種情況沒多大實際意義

如果在使用者程序上下文 

查找vma,找到,先判斷是否需要棧擴張,否則進入通常的處理流程

查找vma,未找到,bad area,通常傳回segment fault

具體的缺頁中斷流程圖及代碼如下: 

Linux核心記憶體管理-記憶體通路與缺頁中斷【轉】
Linux核心記憶體管理-記憶體通路與缺頁中斷【轉】

掃我,和雲栖線上交流

【新浪微網誌】 張昺華--sky

【twitter】 @sky2030_

【facebook】 張昺華 zhangbinghua

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利.