Linux kernel 記憶體子系統

2021-07-11 15:17:41 字數 2102 閱讀 5272

理論概述:

核心把物理頁作為記憶體管理的基本單位;使用struct page結構來描述當前機器上的每乙個物理頁;比如核心支援4kb的頁大小,機器上有1gb物理記憶體,那麼意味著會有262144個struct page;

核心把物理頁劃分為不同的區;同一區內的記憶體具有相似的特徵;一般會有zone_dma/zone_normal/zone_highem;比如x86上會有三個區來劃分物理記憶體;但arm就沒有那麼多;

每個區都是用一些策略來管理區內的物理頁,linux使用buddy system來管理區內的物理頁,buddy的策略就是將區內所有的物理頁劃分為1,2,4,8,16,32,64,128,256,512,1024個連續頁塊;每個區都採取這樣的方式管理內部的物理頁;這種方式可以解決外碎片問題;

再上一級,就是zoned page frame allocator;也就是提供alloc_page()系列介面部分;

再上一級,就是slab/slob/slub部分,這塊就是快取記憶體,比如我們常用的kmalloc()介面,就是使用的快取記憶體,它是由

32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072個位元組的快取記憶體組成的,每個位元組塊乙個快取記憶體描述符;這個是用來解決內碎片

再上一級,就是kmalloc;

再有一點,就是記憶體分配和建立對映,是兩個概念,只是我們常用的分配函式已經完成了兩個過程;再有就是kmalloc屬於核心分配記憶體的函式,它返回的虛擬位址肯定是在核心空間;

再提一下vmalloc函式,它也是用在核心中用來分配記憶體的函式,它與kmalloc的主要區別就是,它分配的記憶體空間在虛擬位址空間上是連續的,而在實體地址空間不一定是連續的;這塊理解呢,也可以按照記憶體分配和建立對映兩塊來分析;首先分配多個不連續的struct page,然後乙個乙個的建立到乙個連續的位址空間的對映;

再說說高階記憶體,也就是zone_highem區內的物理記憶體,由於處理器的記憶體空間的限制,這部分區域不能夠像zone_normal區內的物理記憶體那樣,直接對映到核心的虛擬位址空間(說白了就是3gb~4gb這一段虛擬位址空間不夠用了,因為soc上的很多外設控制器也要直接對映一部分實體地址到這1g的範圍內,還有一些預留的部分,比如vmalloc_start-vmalloc_end區間,永久對映區間,固定對映區間等,這塊理解需要將物理記憶體和核心的虛擬位址空間區分開發,不可混為一談),但並不意味著不能對映到其他其他地方,比如說對映到程序的位址空間,因為你可以非常容易的從高階記憶體分配物理記憶體,然後建立到程序位址空間的對映;這裡強調一下,高階記憶體的劃分依據是核心不方便使用,僅此而已;如果要使用高階記憶體,那麼就意味著需要分別的從zone_highem區內分配物理頁,以及建立對映,這塊,處理器的記憶體空間會保留一塊小區域來建立這種對映;當然,不用的時候是需要取消對映的;

以上說的都是核心空間的記憶體概念;接著聊程序位址空間的記憶體問題;

struct page、zone_*、buddy system概念應該都是一樣的,因為這個是基礎;然後使用alloc_page來分配物理頁,然後就是程序位址空間的對映問題,對映完成後,程序在自己的位址空間內就可以直接訪問這塊物理記憶體了;這塊可能引出其他問題,就是比如程序想分配1mb物理記憶體並對映進它的位址空間,核心裡邊不會這麼傻,它可能只分配4kb,也就是1頁物理記憶體,然後在程序位址空間內中建立1mb有效區域struct vm_area_struct,然後只建立這4kb的對映;然後當需要用到超過著個4kb時,mmu一轉,發現沒有頁表指定,那麼就使用缺頁來處理唄;

在聊到程序位址空間問題時,我突然想到,從程序使用者空間,切換到核心空間,這塊位址怎麼處理?這個問題就是個腦子一時短路問題;程序的位址空間中,就說32bit,0~3gb是使用者空間,3gb~4gb是核心空間,首先位址上不衝突,其次,是否表示程序的位址空間中,已經包含了3gb~4gb的對映,只是訪問許可權不夠而已,我想,是這樣的;

再說說malloc函式,它呼叫的最終結果就是在程序的位址空間建乙個有效區域struct vm_area_struct,這個表明程序對這個區域的訪問時合法的,但是有可能不存在物理記憶體的對映,這時就得靠缺頁機制了;

這些都只是理論知識,還麼有涉及到建立對映用的頁表,很多具體東西都需要分析**,但是,這些問題是可以一覽記憶體子系統的概況;

**分析:

未完待續。。。

Linux kernel 記憶體損壞漏洞

漏洞名稱 linux kernel 記憶體損壞漏洞 cnnvd編號 cnnvd 201310 143 2013 10 11 2013 10 11 危害等級 中危漏洞型別 緩衝區溢位 威脅型別 遠端 本地 cve編號 cve 2013 4387 linux kernel是美國linux 會發布的一款作...

Linux Kernel 記憶體分配方式

頁分配unsigned long get free pages gfp t gfp mask,unsigned int order 直接從buddy系統中獲得原始頁。最原始的分配方式。slab分配器1.通用 cache void kmalloc size t size gfp t flags kma...

Linux kernel 記憶體屏障在RCU上的應用

記憶體屏障主要解決的問題是編譯器的優化和cpu的亂序執行。編譯器在優化的時候,生成的彙編指令可能和c語言程式的執行順序不一樣,在需要程式嚴格按照c語言順序執行時,需要顯式的告訴編譯不需要優化,這在linux下是通過barrier 巨集完成的,它依靠volidate關鍵字和memory關鍵字,前者告訴...