您好,登錄后才能下訂單哦!
Linux中使用全局框架怎么實現內存管理,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
一. 地址劃分。
1. CPU地址。
CPU地址是指CPU的地址總線能尋址的范圍,32bit-CPU尋址范圍為4G, 這個地址是虛擬的,實際上外部物理內存是不會使用這么大的內存。
CPU虛擬地址的4G空間,通常劃分為兩部分,一部分為內核虛擬地址,通常為3G-4G之間,另一部分為用戶虛擬地址,通常為0G-3G之間,顯然,用戶進程能使用的虛擬地址范圍遠大于內核可以使用的虛擬地址空間,但是,物理內存只有局限性的幾M,幾G,內核虛擬地址如何使用物理內存,用戶空間如何使用物理內存,這些問題正是linux內存管理的關鍵。
2. 物理內存
物理內存是指外部存儲數據的設備,有可以被CPU尋址到的地址總線,受到CPU的Cache 和TLB/MMU管理尋址。
需要澄清一個概念:任何代碼是在CPU上運行的,而不是在物理內存上,物理內存是個設備,用于存放用戶進程空間的可執行代碼或者內核關鍵數據結構,這些代碼或結構終將是要受到CPU通過MMU尋址,Cache***指令數據來獲取的。
NUMA的全稱是非一致性內存訪問,它通常是多核訪問的概念,每一個CPU核都會有一個節點對應使用一部分物理內存,對這些節點的管理附加這些數據結構:perCPU變量,list表串聯各節點遍歷,zone的劃分,zonelist的管理等等。為了使問題更加簡單化,我們只分析UMA的一個節點的情況,當然它也包含NUMA的一些數據結構特征,這個后面會有所簡述。
下圖是NUMA的一個簡略圖抽象如圖2-1所示。
圖2-1 NUMA多核物理內存zone示意圖
3. 內核虛擬地址空間劃分。
如果讀者僅僅了解一些皮毛,必然認為內核的虛擬地址空間僅有邏輯地址這一說,其實這只是內存內核虛擬地址劃分的一個特例,并非全部的完整表述,現在我劃出完整的圖形,并且改變改變對內核虛擬地址空間名稱的叫法,如圖2-2
圖2-2 內核虛擬地址空間劃分及其對物理內存的映射
下面來改改名字咯,直接映射的地址我們可以叫為內核物理直接映射地址或者邏輯地址。linux原則上只能使用虛擬空間1G中的896M,剩下的128M留作它用,所以直接映射之外的物理內存稱為高端內存。128M之間的空間又劃分為多個gap安全間隙,虛擬地址,固定映射和持久映射,注意這里的虛擬地址叫法通常和前述的內核虛擬地址有些混雜,后者是指CPU內核虛擬地址,是更廣的概念。由于直接映射的部分有了名字叫邏輯地址,那么這里的虛擬地址空間常專指這個部分。
虛擬地址有以下用途,使用vm_struct結構體經內核管理高端內存,它可以使用kmap方式獲取高端物理內存的空間;也可以不映射物理高端內存,將這段地址直接作為外部物理設備的ioremap地址,從而可以直接操縱設備,當然這也將外部設備地址空間暴露出來并且容易造成干擾,所以通常不能直接訪問ioremap映射的地址而是用readb/writeb讀寫,而且要做好優化屏障設置并且用iounmap釋放,因為映射了的設備常具有’邊際效應’.
如果沒有高端內存,(當然32bit的嵌入式系統通常不會使用高端內存,至少我見過的那么多關于ARM,powerPC,MIPS32的嵌入式應用都是沒有使用高端內存的), 那么固定映射和持久映射也多半不會用到。固定映射可以指定長期持有物理內存某些地址頁的占用,這個映射關系可以在初始階段進行配置,而持久映射在啟用時就建立了同高端內存物理頁的映射關系,它在其他階段都不會被解除。
強調的是,我這里不關心高端內存,內核的直接映射邏輯地址就可以涵蓋全部物理內存。
4. 用戶虛擬地址空間的劃分
用戶虛擬地址空間圖構并不復雜,復雜的是它在虛擬內存空間中的應用,如何映射文件,如何組織區間映射,關聯的進程是誰,對應的內存結構體實例是什么等等問題才是用戶虛擬映射最難的地方,下面僅僅劃出圖示,對用戶虛擬內存空間可以先有一個大了解,如圖2-3。
圖2-3用戶空間虛擬內存布局
既然用戶空間是虛擬的,那么它是怎么訪問物理內存的呢,當然就是PGD,PUD,PMD,PTE,OFFSET及其TLB快表查詢了,上層目錄入口PUD和中間目錄入口一般不考慮,考慮二級目錄就可以了。從網上摘的圖2-4:
圖2-4 用戶進程空間訪問物理內存的方法
二. 伙伴系統
伙伴系統是按階管理外界物理內存的方法,***有11階,每一階有一個或者多個頁合并的集合并使用指針串聯起來,同時在同一階中的一個或多個頁集合中形成各自的伙伴,要強調的是各個階的伙伴都是等頁個數的,用下圖2-5是比較好理解的。
圖2-5 伙伴系統在內存中的大致模型
當內核申請一段按頁卻并非按照階數分配的內存時候,通常會使用伙伴系統原理將其按照該申請空間的***階數分配,多出來的頁按照伙伴系統算法歸并到其他階的鏈表當中形成其他階的新伙伴。釋放該內存空間的時候,釋放的空間會嘗試找到能以它為伙伴的那個階進行連接,如果大小超過,則劈開,多余的再尋找其他可以以它為伙伴的階。夠拗口的,但還是很容易理解的,后面會有源代碼呈現出來以實例詳細分析。
三. 反碎片技術:
反碎片機制其實還在伙伴系統之前,它主要是將各個zone區域的物理內存分成可回收reclaimable但不可移動unmovable,可移動movable,不可移動unmovable. 這些標記按照一定得list串聯起來管理,當外部條件申請物理內存導致許多碎片的時候,它可以按照這些數據結構的標志,來從新組織歸類物理內存,從而減少碎片頁或者孤獨頁。反碎片技術在嵌入式系統當中少用,絕大部分由伙伴系統占據江山了,因此不會對此做具體分析,簡略過之。
四. Slab分配機制。
眾所周知,操作系統使用伙伴系統管理內存,不僅會造成大量的內存碎片,同時處理效率也較低下。SLAB是一種內存管理機制,其擁有較高的處理效率,同時也有效的避免內存碎片的產生,其核心思想是預分配。其按照SIZE對內存進行分類管理的,當申請一塊大小為SIZE的內存時,分配器就從SIZE集合中分配一個內存塊(BLOCK)出去,當釋放一個大小為SIZE的內存時,則將該內存塊放回到原有集合,而不是釋放給操作系統。當又要申請相同大小的內存時,可以復用之前被回收的內存塊(BLOCK),從而避免了內存碎片的產生。[注:因SLAB處理過程的細節較多,在此只是做一個原理上的講解
1. 總體結構
圖1 SLAB內存結構
2.處理流程
如圖1中所示:SLAB管理機制將內存大體上分為SLAB頭、SLOT數組、PAGES數組、可分配空間、被浪費空間等模塊進行分別管理,其中各模塊的功能和作用:
SLAB頭:包含SLAB管理的匯總信息,如最小分配單元(min_size)、最小分配單元對應的位移(min_shift)、頁數組地址(pages)、空閑頁鏈表(free)、可分配空間的起始地址(start)、內存塊結束地址(end)等等信息(如代碼1所示),在內存的管理過程中,內存的分配、回收、定位等等操作都依賴于這些數據。
SLOT數組:SLOT數組各成員分別負責固定大小的內存塊(BLOCK)的分配和回收。在nginx中SLOT[0]~SLOT[7]分別負責區間在[1~8]、[9~16]、[17~32]、[33~64]、[65~128]、[129~256]、[257~512]、[513~1024]字節大小內存的分配,但為方便內存塊(BLOCK)的分配和回收,每個內存塊(BLOCK)的大小為各區間的上限(8、16、32、64、128、256、512、1024)。比如說:假如應用進程請求申請5個字節的空間,因5處在[1~8]的區間內,因此由SLOT[0]負責該內存的分配,但區間[1~8]的上限為8,因此即使申請5個字節,卻依然分配8字節給應用進程。以此類推:假如申請12字節,12處于區間[9~16]之間,取上限16,因此由SLOT[1]分配16個字節給應用進程;假如申請50字節,50處于區間[33~64]之間,取上限64,因此由SLOT[2]分配64個字節給應用進程;假如申請84字節,84處于區間[65~128]之間,取上限128,因此由SLOT[3]分配128個字節;...;假如申請722字節,722處于區間[513~1024]之間,取上限1024,因此由SLOT[7]分配1024字節。
PAGES數組:PAGES數組各成員分別負責可分配空間中各頁的查詢、分配和回收,其處理流程可參考3.2節的說明。
可分配空間:SLAB在邏輯上將可分配空間劃分成M個內存頁,每頁大小為4K。每頁內存與PAGES數組成員一一對應,由PAGES數組各成員負責各內存頁的分配和回收。
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。