之前學習記憶體方面的都太關注於細節,就有些知其然而不知其所以然的感覺。所以這篇文章拋開細節實現,將linux記憶體管理的大概思路整理一下。
linux作業系統支援多工系統,即(看上去)支援多工併發處理。實際上,系統同時執行的程序數不會超過cpu數目,因此核心會在很短的時間間隔在不同的程序之間切換(使用者是注意不到),從而產生同時處理多程序的假象。
linux對於每乙個任務有分配乙個虛擬位址空間,而cpu的字長決定了虛擬位址空間的大小,如32位cpu即
那麼,現在問題就有來了,給每個任務分配乙個這麼大的虛擬位址空間是否實際記憶體會不夠用,虛擬位址空間又如何跟實際記憶體關聯起來的?
在解釋這個問題前,先釐清下一些特殊的情況。
linux又將虛擬位址空間劃分為兩部分,分別是核心空間和使用者空間。如下圖所示,0~task_size為使用者空間,task_size~
那麼,又有問題了。核心空間既然對每個任務是相同的,那麼豈不是違反了設計虛擬位址空間的初衷(即每個任務跑在自己位址空間,相互不打擾)?
每個使用者態任務是無法直接訪問核心空間內容的,而是通過系統呼叫間接訪問。大致flow是這樣的,使用者態任務發起系統呼叫後,會引發exception,對於arm晶元架構就是由user mode->irq mode->svc mode,從而進入核心態,核心態的介面將核心空間的資料copy至使用者態程序的使用者空間,最後再恢復狀態,從而讓使用者態任務能夠拿到想要的資料。
這裡還介紹乙個核心態任務。與使用者態任務不同,核心態任務只會訪問核心空間,且所有核心態任務共用核心空間。
在回到之前的問題,給每個任務分配乙個這麼大的虛擬位址空間是否實際記憶體會不夠用,虛擬位址空間又如何跟實際記憶體關聯起來的?
那麼這邊要介紹三個概念,頁,頁表,頁幀
每個虛擬位址空間都會被核心分為等長的部分,這每個部分,被稱為頁。而實際記憶體也被分為等長的部分,被稱為頁幀。下圖為兩個虛擬位址空間與實際記憶體的對映圖。而用於儲存該對映關係的,被稱為頁表。
乙個程序是用多少頁,才會對應申請多少頁幀。所以實際記憶體不會因虛擬位址為
現在算一筆賬,一頁一般是4kb,以
好吧,現在看這個讀者肯定有各種思路的要反駁我,不著急,我們先介紹一下,以已說明的這種方式是如何找到實際記憶體的。
首先,使用者態程序有儲存頁表項首位址(實際位址)。程序想訪問虛擬位址011..011(32位),那麼會將虛擬位址除以4k(實際記憶體位址一定是連續的,如果不連續,難道還要再建乙個表去儲存對應頁表項的實際位址,得不償失。
那麼建立頁這個概念,將記憶體分為等大的頁的 意義也呼之欲出。儲存記憶體為4gb的頁表項記憶體都需要4m,那麼每乙個位元組都有自己對映,所需的表項記憶體為
那麼,再回到上面頁表項佔據一定記憶體,記憶體浪費問題。是否可以將頁的大小變大一些。其實從上面的介紹,可以看出,頁的大小是申請實際記憶體的最小單位,如果將頁的大小調的過大,那麼在實際使用中,會造成申請一頁中,只使用了其中一部分,造成更多浪費,術語是內碎片。
換個思路,我們是否可以根據用多少頁再建立多長的頁表。這是可行的,不過由於要求實際記憶體位址連續,所以當頁表超過當前可存放的位置時,就需要搬移到其他位置。而仍然會用使用實際記憶體較多的程序,由於頁表實際位址需要連續,作業系統的記憶體仍然會因此變得緊張。
那麼,怎麼樣可以破壞這種連續性呢?其實頁的引入,就是將原本連續的一整塊大的記憶體切割成很多小塊。以同樣的思路,也可以對頁表生效。4gb的虛擬記憶體需要1m個頁表項,那麼以1k個頁表項(4k大小)為乙個單位進行儲存,需要1k頁目錄(4k大小)去儲存頁表項單位的位址。
那麼這種方式是如何找到實際記憶體的呢?首先使用者態程序儲存頁目錄的首位址,程序想訪問虛擬位址011..011(32位),那麼會將該虛擬位址除以
這樣的做法好處是,將頁表原本連續的實際實體地址切分開,從而達到提高實際記憶體的效率的作用。這樣的方法被稱為多級頁表。上述描述的為二級頁表的流程,目前作業系統多用**頁表和四級頁表。
多級頁表有沒有問題呢?是有的,由於每次訪問記憶體都需要訪問多次陣列,才能將虛擬位址轉換實際位址。試圖用下面兩種方法加速該過程。
(1) cpu中有乙個專門的部分稱為mmu(memory management unit,記憶體管理單元),該單元優化了記憶體訪問操作。
(2) 位址轉換**現最頻繁的那些位址,儲存到稱為位址轉換後備緩衝器(translation lookasidebuffer,tlb)的cpu快取記憶體中。無需訪問記憶體中的頁表即可從快取記憶體直接獲得位址資料,因而大大加速了位址轉換。
Linux記憶體管理
本文首先介紹一下linux記憶體管理方式,著重說明一下使用者空間的記憶體管理,包括linux虛擬對映以及glibc中malloc的實現 然後簡要介紹單程序多執行緒的記憶體管理方式,主要涉及各執行緒堆疊空間的分配 linux 採用兩級保護機制,隔離核心空間和使用者程式空間,使使用者程式無法直接訪問核心...
Linux記憶體管理
本文首先介紹一下linux記憶體管理方式,著重說明一下使用者空間的記憶體管理,包括linux虛擬對映以及glibc中malloc的實現 然後簡要介紹單程序多執行緒的記憶體管理方式,主要涉及各執行緒堆疊空間的分配 linux採用兩級保護機制,隔離核心空間和使用者程式空間,使使用者程式無法直接訪問核心,...
Linux記憶體管理
首先我要說,我這是轉貼,轉的cu論壇上 nonameboy 的帖子,你可以連線過去看看。今天因為要解釋系統中可用記憶體的大小,用google看了半天,還有在cu上找了關天,竞然沒有發現有比較好的章,估計很多人都沒有注意到,懂了以後又沒有整理出來。在cu上看了很多文章說什麼memory leak和li...