從物理上須要關注物理架構,RAM的組織管理/分配/頁結構,cache,cpu_cache。內存分配設計到夥伴系統、slab。從邏輯上涉及到虛擬內存,頁表,地址空間。兩者的使用涉及到缺頁,回收,交互,共享內存等內容node
cpu之間走FSB,cpu與NB走FSB。與RAM走NB。
dma->nb->ram
DRAM,FB-DRAM(RAM與nd多條),通常用於主存,SRAM用於cpuchachelinux
=》
NB的mc獨立可多條併發ios
=》算法
mc內置於cpusegmentfault
對稱SMP,NUMA(非統一資源),NUMA因子(遠端內存代價)數組
RAM分三個管理區:
ZONE_DMA:可用做DMA的內存區域。該類型的內存區域在物理內存的低端,主要是ISA設備只能用低端的地址作DMA操做。
ZONE_NORMAL:直接被內核直接映射到本身的虛擬地址空間的地址。
ZONE_HIGHMEM:不能被直接映射到內核的虛擬地址空間的地址。
在分配時的管理區分配器:buddy/slab。還有pre-cpu page。
圖中爲總體架構,進程映射到RAM,RAM的內存結構是memap,每一個頁是一個元素,還可能會映射到swap。三個管理區有本身的管理區分配器。緩存
分配:
1.alloc_pages 整個頁
2.kmalloc 字節 連續內存虛擬地址,物理地址也連續
3.vmalloc 虛擬連續,物理不必定,創建頁表項須要一個一個的映射
4.slab層,防止每一個進程本身單首創建free鏈,不能全局判斷安全
高低度緩衝組。kmem_cache。每一個類型好比task_struct,inode,通用的。3個鏈表empty,full,parti kmem_Cache_alloc.內存緊缺/顯示撤銷才釋放
5.高端內存(頁並不必定永久映射,好比內核1G要訪問8G物理內存,動態映射)數據結構
kmap。可睡眠,永久映射 kmap_atomic 臨時,原子,不睡眠,不阻塞,禁止內核搶佔
6.cpu上數據,alloc_percpu多線程
內存結構最外層是pglist_data,對於一個RAM的就只有一個,SMP的多個RAM是個數組。分爲三個區域來管理,每一個包含不少頁,全部RAM對應mem_map。
zone中有極值:pages_min, pages_low, pages_high;來控制zone中頁面的回收
有等待區隊列,一個區一個,頁hash映射喚醒(每頁一個佔空間,一個zone一個驚羣,因此hash映射喚醒,當有hash衝突時會環境多個進程)
Page有兩個重要字段,address_space爲cache的結構。非cache的private
struct { unsigned long private; struct address_space *mapping; };
每一個物理頁一個結構 4G會佔用20M 被用戶空間進程/動態分配內核數據/靜態內核代碼/頁高速緩存等引用
flag 髒/鎖 ;count引用計數,0空閒 ;*virtual 虛擬地址
cache是對外設或者文件或者其餘的緩存,是RAM的一部分,從分類上大概有buffer /page/swap/硬件,還有Inode/目錄等cache。這些都是在別處有副本的。buffer是針對塊設備,page基本基於與文件或基於其餘page管理的緩存,咱們用free命令能夠看到buff/cache,used。used指的就是非cache RAM的使用量。在mmap不一樣種類時用到的不同,好比共享匿名映射時,這時是從cache中申請內存,在進行匿名私有映射時,並無佔用cache,文件映射,則都是將文件映射到cache中,而後根據共享仍是私有進行不一樣的操做,私有的會再used增長一份;
page cache本質上都是文件的緩存,大多數可清理 這種時候放cache中做爲緩存、那爲什麼好比共享內存映射也在呢,由於他本質上也是特殊文件系統shm中的一個文件,shm的安裝點在交換區上,相似的還有tmp.proc等這種基於內存的文件。對於私有內存映射 非基於文件 的不走cache。至於回收(不管cache與否都同樣):頁框回收算法必須處理多種屬於用戶態進程、磁盤高速緩存和內存高速緩存的頁,並且必須遵守幾條試探法準則只有走緩存的纔有address_space不然就private
fd與磁盤的關聯
fd->file->path->dentry->inode->address_space->page->buffer_head->磁盤塊號
緩存線:64字節長。組關聯(外層查找,內層地址置換mmap) tag-cache set-offset
cpu都有獨立調的1級,共享2/3級等可能有點詫異。l1通常是虛擬地址,其餘是物理地址。sram
主存-l3-l2-l1-cpu。
數據結構:
1.組關聯,段大小,cache size,數據集大小(對不一樣cache的佔用)
2.順序訪問單線程
數據大小,預取(下面圖預取超過緩存,不生效),TLB
3.隨機訪問 無預取,大小,TLB
4.寫入 寫回/寫入合併/不緩存等策略的影響
5.多處理器 MESI
6.多線程
7.超線程
寫入:寫回策略,打開dirty標記,緩存線丟棄時,通知寫回主存,每一個寫通/刪除對FSB壓力大
多處理器一致性:MESI 狀態變動,
If a Modified cache line is read from or written to on the local processor, the instruction can use the current cache content and the state does not change. If a second processor wants to read from the cache line the firs processor has to send the content of its cache to the second processor and then it can change the state to Shared.The data sent to the second processor is also received and processed by the memory controller which stores the content in memory. If this did not happen the cache line could not be marked as Shared. If the second processor wants to write to the cache line the first processor sends the cache line content and marks the cache line locally as Invalid. This is the infamous 「Request For Ownership」 (RFO) operation. Performing this operation in the last level cache, just like the I→M transition is comparatively expensive. For write-through caches we also have to add the time it takes to write the new cache line content to the next higher-level cache or the main memory, further increasing the cost.
互連
內存利用率-》帶條化,自由遷移進程
遷移
一致性
1.不緩存
2.充分利用緩存
行預取
64字節。double能夠8個一讀
對齊 佔盡可能少的緩存行,常常用到的組合在一塊兒
l1級指令。好比inline的取捨
TLB優化。減小頁數/減小頁目錄級數
3.預取
硬件/軟件/單獨線程(超線程/dumber)/directcacheaccess 設置標記讓DMA能夠直接寫入cpucache
4.多線程優化
組讀寫變量,局部變量等 原子、原子運算、cas cpu親和性等
https://people.freebsd.org/~l...
爲了便於頁面的維護,將多個頁面組成內存塊
每一個大小爲2^n。當沒有本身的size到大size拆分
每一個區有本身的buddy
固定2^n這種內存分配會產生碎片化,可是在內存管理這不能隨便有權限像其餘的同樣按期整理,所以採起反碎片化的分配方式,對頁面進行分類,https://blog.csdn.net/goodluc...
發現內核對象初始化代價比分配大,對對象進行緩存
一個cache管理一組大小固定的內存塊(也稱爲對象實體),每一個內存塊均可用做一種數據結構。cache中的內存塊來自一到多個slab。一個slab來自物理內存管理器的一到多個物理頁
每一個緩存結構都包括了兩個重要的成員:
struct kmem_list3 **nodelists:kmem_list3結構中包含了三個鏈表頭,分別對應於徹底用盡的slab鏈表,部分用盡的slab鏈,空閒的slab鏈表,其中部分空閒的在最開始
struct array_cache *array[NR_CPUS + MAX_NUMNODES]:array是一個數組,系統中的每個CPU,每個內存節點都對應該數組中的一個元素。array_cache結構包含了一些特定於該CPU/節點的管理數據以及一個數組,每一個數組元素都指向一個該CPU/節點剛釋放的內存對象。該數組有助於提升高速緩存的利用率。
當釋放內存對象時,首先將內存對象釋放到該數組中對應的元素中
申請內存時,內核假定剛釋放的內存對象仍然處於CPU高速緩存中,於是會先從該數組的對應數組元素中查找,看是否能夠申請。
當特定於CPU/節點的緩存數組是空時,會用slab緩存中的空閒對象填充它
CPU訪問內存時使用哪一個cache line是經過低地址的若干位肯定的,好比cache line大小爲32,那麼是從bit5開始的若干位。所以相距很遠的內存地址,若是這些位的地址相同,仍是會被映射到同一個cache line。Slab cache中存放的是相同大小的對象,若是沒有着色區,那麼同一個cache內,不一樣slab中具備相同slab內部偏移的對象,其低地址的若干位是相同的,映射到同一個cache line。訪問cache line衝突的對象時,就會出現cache miss,經過着色區使對象的slab內偏移各不相同
爲什麼要有虛擬內存?
進程地址空間不隔離=》分段
程序運行的地址不肯定 =》分段
內存使用效率低=》分頁
邏輯地址+段基地址(linux都是0,)=》線性地址
ds值爲0x7b, 轉換成二進制爲 00000000 01111011,TI:0(GDT),GDT:15(用戶數據段描述符)。
線性地址=》物理地址。頁錶轉換
linux啓動分兩個階段:第一個階段(彙編)創建分段機制(忽略),創建一個臨時頁表進入分頁機制。第二個階段(C語言)初始化系統的各類資源(硬件/軟件)。
須要映射進頁表的內存包括:linux內核。臨時頁表(這個不必定須要映射進頁表,可是爲了方便也這麼作了)。128k的臨時內存管理系統(其實就是用的位圖管理1G的低端內存,2^32/4096/8 = 128K)共佔4M內核代碼+其餘 映射8M
linux內核的臨時頁表有兩層。由於0xC和0x0都要訪問內核代碼,外層在512~1024之間須要10位表示,4K的頁須要偏移位12位。剩10位足以表示4M內存(4M/4K=1024頁)。所以外層兩個-》1024個 10-10-12來映射
4M 2級
4G 須要3級
其餘……
隨機化安全 VS 順序性能
優化 TLB 標籤附加擴展並惟一標識其涉及頁表樹的刷入刷出
頁面大 TLB少,裝入多。頁表樹級數少,頁面偏移位部分增大,頁目錄少,內存要連續/對其會形成浪費
這是一個完成的地址空間到物理頁的關係圖。右側爲進程地址空間,在32位中,上部3G-4G位共享的內核空間,下層爲用戶空間。
最外層結構是task_struct中的mm_struct。裏邊包含pgd和mmap。pdg的指針會存在cr3中。mmap由不少vm_are_struct組成,每一個用戶空間分區都是一個vm,堆申請也是一個vm。經過頁表會定位到memap映射的pagge。
分爲直接映射/高端內存
高端內存用於vmalloc。持久映射區域/固定映射區域
虛擬地址中連續,可是物理地址不連續的內存區域能夠從VMALLO區域分配
持久映射區域用於將高端內存中的非持久頁映射到內核中
固定映射用於與物理地址空間中的固定頁關聯的虛擬地址頁,可是物理地址頁即頁幀能夠自由選擇
Linux將內核地址空間劃分爲三部分ZONE_DMA、ZONE_NORMAL和ZONE_HIGHMEM,高端內存HIGH_MEM地址空間範圍爲 0xF8000000 ~ 0xFFFFFFFF(896MB~1024MB)。那麼如內核是如何藉助128MB高端內存地址空間是如何實現訪問能夠全部物理內存?
當內核想訪問高於896MB物理地址內存時,從0xF8000000 ~ 0xFFFFFFFF地址空間範圍內找一段相應大小空閒的邏輯地址空間,借用一會。借用這段邏輯地址空間,創建映射到想訪問的那段物理內存(即填充內核PTE頁面表),臨時用一會,用完後歸還。這樣別人也能夠借用這段地址空間訪問其餘物理內存,實現了使用有限的地址空間,訪問全部全部物理內存。
在講進程時已經詳細講解了。這裏說下vm。以紅黑樹組織
當用戶訪問一個頁時,MMU回去查詢一個操做系統維護的頁表,看看用戶訪問的頁是否存在於內存當中,若是存在,就直接調用;若是沒有,就須要開啓中斷,執行頁錯誤處理程序,在磁盤中找到相應的數據頁,並在內存中找到一塊空閒,將其載入進來,而後中斷返回,執行用戶程序,在去訪問內存中用戶須要的頁。
非映射頁在磁盤上提供備份(磁盤分爲文件/交換/裸設備)
交換子系統的主要功能總結以下:
1) 在磁盤上創建交換區(swap area),用於存放沒有磁盤映像的頁。
2) 管理交換區空間。當需求發生時,分配與釋放頁槽(page slot)。
3) 提供函數用於從RAM 中把頁換出(swap out)到交換區或從交換區換入(swap in)到RAM中。
4) 利用頁表項(現已被換出的換出頁頁表項)中的換出頁標識符跟蹤數據在交換區中的位置。
標識一個換出頁,在swap_info 數組中指定交換區的索引和在交換區內指定頁槽的索引,
當頁被換出時,其標識符就做爲頁的表項插入頁表中
居然看到有人提到本身老師哈哈。可信老師的課件已經難免費了
https://blog.csdn.net/iostrea...
page_min:若是空閒頁數目小於該值,則該zone很是缺頁,頁面回收壓力很大。
page_low: 若是空閒頁數目小於該值,kswapd線程將被喚醒,並開始釋放回收頁面。
page_high: 若是空閒頁面的值大於該值,則該zone的狀態很完美, kswapd線程將從新休眠。
linux的LRU active/inactive
會根據不一樣頁狀況作不一樣的策略。好比:
進程映射的頁:max_mapped爲0 換出
鎖定:調過
髒頁:回寫等
……
解決如何看一個共享頁是否能夠被釋放?
匿名頁:雙向鏈表
文件映射:優先搜索樹
子節點的堆索引都不大於相應父節點的堆索引。任意一個節點的左子節點基索引也都不大於右子節點基索引,若是基索引相等,則按照大小索引排序。
基索引(radix index)和堆索引(heap index)兩個索引來標識。基索引表示區間的起始點而堆索引表示終點
咱們在說共享內存的時候。包含mmap和posix共享內存。要作到共享mmap只能在磁盤建立文件,posix是會在tmpfs上,內核持久性,shm_open+mmap。更多參考https://segmentfault.com/a/11... ,https://segmentfault.com/a/11... 進程調用mmap()時,只是在進程空間內新增了一塊相應大小的緩衝區,並設置了相應的訪問標識,但並無創建進程空間到物理頁面的映射。所以,第一次訪問該空間時,會引起一個缺頁異常對於共享內存映射狀況,缺頁異常處理程序首先在swap cache中尋找目標頁(符合address_space以及偏移量的物理頁),若是找到,則直接返回地址;若是沒有找到,則判斷該頁是否在交換區(swap area),若是在,則執行一個換入操做;若是上述兩種狀況都不知足,處理程序將分配新的物理頁面,並把它插入到page cache中。進程最終將更新進程頁表。 注:對於映射普通文件狀況(非共享映射),缺頁異常處理程序首先會在page cache中根據address_space以及數據偏移量尋找相應的頁面。若是沒有找到,則說明文件數據尚未讀入內存,處理程序會從磁盤讀入相應的頁面,並返回相應地址,同時,進程頁表也會更新。5.全部進程在映射同一個共享內存區域時,狀況都同樣,在創建線性地址與物理地址之間的映射以後,不論進程各自的返回地址如何,實際訪問的必然是同一個共享內存區域對應的物理頁面。注:一個共享內存區域能夠看做是特殊文件系統shm中的一個文件,shm的安裝點在交換區上