對Linux記憶體管理的思考

來源:互聯網
上載者:User

轉自:http://bbs.chinaunix.net/thread-1925077-1-1.html

經典!看了對低端實體記憶體和高3

 

核心的虛擬記憶體被連續映射到最低端的實體記憶體。這是所有問題的開始。

為什麼要把核心的虛擬位址空間連續地映射到實體記憶體最低端?這個根本不是個問題。開發人員或是出於效率的原因或是出於實現的原因,就是做了這樣的設計。但這種設計卻引發了很多令人困惑的問題。

假設我們使用32位版本核心,系統裝有2G實體記憶體,下面所說的“核心的虛擬記憶體”是指核心前896M虛擬記憶體。

"核心將自己的虛擬記憶體連續映射到低端實體記憶體"到底會產生什麼樣的結果?是說低端那896M實體記憶體已被核心所佔而不能另做它用?昨天討論記憶體的文章裡給出了否定答案,看起來這是個很老的問題了。

書上往往會還有這樣的話語:核心只能使用最低端896M物理;超過896M的記憶體稱之為“高端記憶體”,無法被核心直接使用。初學者讀到這裡,總覺得哪裡不對勁,卻又道不出個所以然來。

既然核心已將自己的虛擬記憶體映射了,核心頁表裡entries是怎樣的呢?在entry中,我們當前感興趣的有兩項:映射地址與Present標誌位。映射地址嘛,肯定安排好了。Present標誌位是不是1呢?不妨認為是1。這樣一來,從核心的頁表上來看,前896M的實體記憶體的的確確被核心所“佔用”,只要核心引用相應的虛擬位址,核心就會訪問到相應的物理地址,不會發生任何意外。但是,如前面所說,進程也是可以使用這塊記憶體的。如果某個進程的某個虛擬位址映射到了前896M中的某一段,那麼核心與進程都可通過各自的頁表訪問到這塊記憶體。這樣會不會發生衝突呢?

描述頁幀的資料結構是page結構體,一個頁幀是否空閑正是取決於對應page結構體中的引用數。那麼核心映射的那896M實體記憶體是否空閑呢?除了核心代碼及待用資料所佔的物理頁外,其它的全是空閑狀態。也就是說《記憶體管理子系統》可以把這些記憶體配置出去。昨天文章裡說的“被核心映射了不等於被核心使用了”就是這麼回事。核心頁表裡的內容是說,前896M實體記憶體處於一種Ready to use的狀態,然而沒有被核心使用的記憶體,進程也可以使用。在896M記憶體中,核心不能使用“被進程使用的記憶體”,即核心不能引用相應的頁表裡的內容,即核心不可使用相應的虛擬位址。

核心是怎麼使用自己的虛擬位址的呢?她怎麼知道哪一段的虛擬位址已經《被自己使用了》或者《因為進程而不能使用》?即核心如何管理自己的虛擬位址。

先看核心如何管理進程的虛擬位址。當進程需要記憶體時,核心首先會為進程分配一段虛擬位址,即所謂的Memory Region。由於進程虛擬位址的使用方式記錄在vm_area_struct中,所有的vm_area_struct都按照順序串連在一個鏈表上,因此尋找某大小的虛擬位址十分簡單,掃描這個鏈表,碰到一塊大於或等於[所申請記憶體大小]的連續地址,便用新的vm_area_struct記錄下來,並插到鏈表的合適位置,這塊虛擬位址便被標記為“已用”了。其實這就是作業系統理論裡所講的first fit。早期的Unix就是這樣管理實體記憶體的,而這裡用之管理進程的虛擬記憶體。核心為進程分配記憶體的步驟如下:
一、找到合適大小的虛擬位址段;
二、向{記憶體管理子系統}申請物理頁幀;
三、在進程頁表中建立兩者的映射關係。

然而核心為<自己>分配記憶體時,只有#第二步#。

沒有第三步,是因為一開始的時候,核心頁表已經做好了映射。那第一步呢?核心為什麼沒有像進程一樣<<尋找合適大小的虛擬位址段>>這一步驟?

核心自己需要記憶體時,總是向Slab層申請(?)。需要建立新的資料結構,需要一個buffer時,Slab便為之分配一塊連續的記憶體。核心不需要對這塊記憶體做映射,只要這塊連續的實體記憶體在前896M之內,它本來就處於一種“預備被核心使用”的狀態。從Slab裡分出來後,它就“正式被核心使用”。那麼說到底,核心怎麼管理虛擬位址呢?核心沒有“額外管理”,具體使用哪一塊虛擬記憶體取決於Slab分配哪塊實體記憶體。Slab分配哪塊實體記憶體又取決了{記憶體管理子系統}。{記憶體管理子系統}={Buddy System}

結論是:Buddy System管理了核心的虛擬記憶體。嚴格來說,Buddy System在管理前896M實體記憶體時隨便把核心的虛擬記憶體也管理了。對進程來說,分配虛擬記憶體與分配實體記憶體是分開的步驟;對於核心來說,分配了實體記憶體就等於分配了虛擬記憶體。核心為自己分配的記憶體究竟在虛擬記憶體的什麼位置取決於分[配到的記憶體的頁幀]在實體記憶體中的哪個位置。進程需要額外的結構體記錄虛擬記憶體的使用的情況;核心虛擬記憶體的使用方式就是前896M實體記憶體的使用方式。換句話說,一旦進程申請到了前896M實體記憶體中的某一塊,就相當於侵佔了核心的虛擬位址空間,就相當於核心對應的虛擬位址段已經被使用。由於所有對實體記憶體的申請都由Buddy System應答,核心為自己申請記憶體時,不可能再獲得被[進程佔用的實體記憶體]所對應的[虛擬位址],也就不可能去[引用相應的頁表],衝突也就避免了。當然,如果核心有BUG,指標使用不慎,很容易破壞進程的記憶體。

這樣一來,問題都解決了。前896M實體記憶體由核心與進程混用。但核心只能使用這896M實體記憶體(因為它的頁表映射是固定的),而進程可以使用任何地方的實體記憶體(因為它的頁表可以隨意設定)。核心高128M留作其它用途,可以隨意映射。核心不能直接使用的記憶體即“高端記憶體”。當核心的線性地址空間大於實體記憶體時,“高端”便不存在了。這種情況實際上有兩種可能:一是核心線性地址空間太大,如使用64位系統;二是系統實體記憶體太小,如機器僅配有512M記憶體。兩者都是{核心線性地址空間大於實體記憶體}的結果。

管理進程虛擬記憶體時,利用分頁,可以把虛擬位址隨意映射到任何物理地址,這才是我們印象中“分頁機制的常規用法”。相反的,核心管理自己的虛擬記憶體時,利用分頁,把“一塊虛擬記憶體固定到一塊實體記憶體”,反倒限制核心能使用的記憶體在實體記憶體中的位置,與我們印象中分頁機制的常規作用相悖。初學者總有種“說不清道不明的不協調感”,大概就是這個原因吧。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.