通過Linux理解作業系統(五):記憶體管理(下)

來源:互聯網
上載者:User

1、分頁和頁表

首先,分頁的概念相信很多人都不陌生,我這裡想說的是“分”的思想,學習電腦兩年多,我最大的感受是電腦就是在利用有限的資源幹無限的事,而這很多時候都是基於“分而治之”的思想實現的。問題規模太大,太複雜怎麼辦?就是要分解,分就意味著更簡單,更靈活,更容易處理,我這裡並不只是指演算法設計,而是指解決很多實際的複雜問題,就像現在很火的大資料處理,一台機器根本無法完成這麼大量的儲存和計算工作,就是需要通過“分”,把資料分到多台機器上存,把計算任務也分到多台機器上完成,才有了問題解決的可能。好吧,扯遠了~其實我只是想說作為程式員一定要理解分治的思想。回到正題,我們已經知道每個進程都有4G的地址空間,但是程式在啟動並執行時候並不需要程式中所有的內容,需要的只是當前正在執行的一部分和相關的資料就可以,因此可以將整個地址空間分成一個個連續的大小固定的塊(比如4KB),只要那些需要的塊在記憶體中即可,這一個個的塊就是page),好處就是當程式運行或者停止時,系統不用把整個進程的內容移進移出,而只要移動一個個頁就可以,這樣既提高了效率又節省了空間,才使得多個進程能夠同時存在於記憶體中。注意,這裡的頁是指虛擬位址空間裡連續的一段,而實體記憶體中這樣連續的段則稱為page frame,它們的大小相同,進程的頁放進記憶體中時就放到一個個的page frame中。

有了page的概念後,我們再來看系統是如何?邏輯地址到物理地址的轉換的。Linux為每個進程維護了一個page table,這個表裡的每一條記錄表示一個page,儲存了以下資訊:

 page frame number,系統就是由此得到的該頁在實際記憶體中的位置。在32位的機器上,一個邏輯地址有32位,它可以分成兩部分,一部分用於表示頁號,用於在page table中尋找該page的記錄,從而得到page frame number,也就是這個page在實體記憶體的起始位置,還有一部分是頁內位移量,這兩者相加就得到了我們實際要訪問的物理地址。通過這種方式系統可以實現邏輯地址到物理地址的轉換,但是又帶來一個問題,由於在程式運行期間需要對page table進行尋找,也就是說page table也要存在於記憶體中,假設一個頁有4KB,對於32位的機器,page table中剛好有2^20(1M)條的記錄,似乎還可以接受,但是對於64位的機器,則需要2^52條記錄,如果光是存個page table就用掉這麼多記憶體,那程式也不用跑了,為瞭解決這個問題,Linux使用了多級索引技術:

Linux不是直接把整個page table放到記憶體中,而是根據頁的大小將整個page table 又分成一個個小的page table,然後通過索引的方式來進行訪問。具體方式如,虛擬位址被分成了5個部分,global|upper|middle directory, page和offset,首先根據global directory在global目錄裡進行尋找,global目錄裡每一條記錄儲存了一個指向下一級目錄的指標,在取得一個指標後,根據這個指標定位到一個下一級的upper目錄,然後根據upper directory 又可以在upper目錄裡得到一個指標來得到一個middle目錄,而middle目錄裡得到的指標才是指向真正的page table,此時再根據page域取得一條page table中的記錄。那為什麼這樣能省記憶體?假設一個page目錄裡有n條記錄,那麼根據gloabl目錄可以索引到n個upper目錄,而每個upper目錄又可以索引到n個middle目錄,以此類推,原來一個大的page table分成了n^3個小的page table,通過三級目錄一級級往下索引就可以得到我們最終需要的那個page table,而需要放進記憶體的就只有在尋找過程中需要的三個目錄和最終的1個page table即可,這樣當然就省了很多記憶體咯。

2、頁的回收

在系統運行期間,隨著越來越多的程式的啟動和運行,越來越多的實體記憶體會被佔用,而系統必須保證有閒置記憶體來維持正常的運行,Linux使用了一種叫PFRA(page frame reclaiming algorithm) 的演算法將一些暫時沒用的page frame釋放來騰出空間,的目標就是從記憶體中選出要釋放的page frame。首先linux將所有的page frame分為四類:unreclaimable, swappable, syncable, discardable。unreclaimable表示該頁的內容不能被取出,即新的page不能放到這裡;swappable表示該頁的內容可以被取出記憶體但需要寫到磁碟,而syncable也表示可以取出記憶體但是只有當這個頁的內容被標記為已修改過的才需要寫會磁碟,discardable則表示該頁的內容可以直接被覆蓋而不需要儲存到磁碟。這四個類代表了需要完成頁的置換操作的難易程度,在發生頁的置換時,系統會優先選擇容易完成頁進行置換。

linux在啟動的過程中會開啟一個後台進程,這個進程在系統運行過程中每隔一段時間就會對記憶體的使用方式進行檢查,如果它判斷當前的記憶體已經快要不過用了,就會開始運行PFRA演算法。

linux將記憶體中所有page frame組織成兩個鏈表,active list和inactive list,這兩個鏈表也叫做LRU  list,active list裡的頁是最近被訪問過的,而inactive裡的則是最近沒被問的,所以系統可以從inactive list裡選擇page frame釋放。如所示,每個page有2個標識位,編碼了4個狀態,這四個狀態之間可以進行轉換,從而導致了一個page會在active list和inactive list之間移動。觀察這個圖可以發現,當PG_active為0時,頁在inactive list上,當PG_active為1時,頁在active list上。對於一個在inactive list的頁,如果一開始處於狀態1,麼該頁被訪問過一次後,它的referenced標識位會變為1,變成狀態2,而再被訪問一次後,它的active就變成1,referenced變為0(狀態3),這樣才從inactive 變成了 active,而如果在狀態2的時候,在經過一段特定的時間後還沒有再被訪問一次,則它又會自動回到狀態1,也就是說一個頁要從inactive變成active,中間需要經過一個中間狀態。為什麼需要這個中間狀態呢,主要是考慮到下面這種情況,有些程式可能會周期性的訪問一個記憶體頁,比如說1小時訪問一次,那麼在這1小時內,它是不需要再被訪問到的,如果沒有這個中間狀態的話,它會直接變成active,所以會一直儲存在記憶體中,而有了這個中間狀態,如果這個也在一定時間內沒有再被訪問一次,它就仍然是inactive的,也就可以被取出記憶體。當然,有些時候系統可能會急需更多的記憶體,所以即使是存在active list裡的頁,有時候也需要被取出記憶體,圖中的refill箭頭就表示了直接從active到inactive的狀態轉換。linux系統通過維護這些狀態變換,就可以選擇出合適的頁來將其取出記憶體,從而盡量減少發生page fault的機會。

 

 

相關文章

聯繫我們

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