CPU是如何訪問內(nèi)存的?
在之前的《Linux內(nèi)存管理》文章中,我們大致講解了Linux內(nèi)存管理的體系架構(gòu)和映射過程。當(dāng)然內(nèi)存管理是一個(gè)復(fù)雜的模塊。它涉及到硬件的交互和復(fù)雜的軟件算法。本片文章我們就來講解下硬件原理和分頁管理。
CPU如果訪問內(nèi)存?
答案很簡單,通過內(nèi)存管理單元(MMU),我們先看一張很簡單的CPU訪問內(nèi)存的流程圖:
TLB:轉(zhuǎn)換lookaside 緩存,有了它可以讓虛擬地址到物理地址轉(zhuǎn)換速度大增。
從上圖中我們可以清楚的知道了,CPU,DDR,MMU它們?nèi)咧g的關(guān)系。CPU在MMU開啟的情況下,訪問的都是虛擬地址。首先通過MMU將虛擬地址轉(zhuǎn)換為物理地址,然后再通過總線上去訪問內(nèi)存(我們都知道內(nèi)存是掛在總線上的)。
那MMU是怎么將虛擬地址轉(zhuǎn)換為物理地址呢?當(dāng)然之前的文章也講過了,是通過頁表的方式。MMU從頁表中查出虛擬地址對應(yīng)的物理地址是什么,然后就去訪問物理內(nèi)存了。
所以搞懂了上面的問題,也就解決了標(biāo)題的問題:《CPU如何訪問內(nèi)存的?》
頁表是什么?頁表就是一種特殊的數(shù)據(jù)結(jié)構(gòu),它保存的是邏輯頁和物理頁幀的映射關(guān)系,而且每一個(gè)進(jìn)程都各自擁有自己的頁表。
虛擬地址在我們看來是一個(gè)整體,其實(shí)不然,它是可以拆分的??梢苑譃椋?/p>
- p(頁號),它可以存儲(chǔ)頁表的索引;
- d(偏移),可以在頁內(nèi)進(jìn)行地址偏移
我們假設(shè)頁大小為4KB,而且頁表只有一級,也就是一級頁表。那虛擬地址的拆分后的樣子是這樣的:
下面我們來看下CPU,虛擬地址,頁表和物理地址之間的關(guān)系??聪聢D:
很簡單的吧,應(yīng)該看懂了吧。我們可以發(fā)現(xiàn)如果采用一級頁表的話,每個(gè)進(jìn)程需要維護(hù)一個(gè)4MB大小的頁表(我們可以算下,如果是32位平臺,地址空間大小為4GB,頁面大小為4KB,每個(gè)頁表項(xiàng)占用4字節(jié),所以4GB/4KB*4=4MB)。
因?yàn)槊總€(gè)進(jìn)程都有自己的頁表,所以在多進(jìn)程的情況下,內(nèi)存消耗簡直驚人。所以一級頁表是不合理的。那有沒有優(yōu)化的辦法呢?答案是有的,就是利用多級頁表,可以節(jié)省內(nèi)存。
二級頁表就是將頁表再次分頁。再次舉例,將邏輯地址分為10位頁碼p1+10位頁碼p2+12位頁偏移。我們直接看圖吧。
訪問過程如下圖: