CPU瞞著記憶體竟幹出這種事

軒轅之風發表於2020-05-15

還記得我嗎,我是阿Q,CPU一號車間的那個阿Q。

今天忙裡偷閒,來到廠裡地址翻譯部門轉轉,負責這項工作的小黑正忙得滿頭大汗。

看到我的到來,小黑指著旁邊的座椅示意讓我坐下。

坐了好一會兒,小黑才從工位上忙完轉過身來,“實在不好意思阿Q,今天活太多,沒來得及招待你”

“剛忙什麼呢,看你滿頭大汗的”,我問道。

“嗨,別提了,老是發現記憶體頁面錯誤,不停地要通知作業系統那邊去處理,真是懷念以前啊,沒有這麼多破事兒要管”,小黑嘆了口氣。

我一聽來了興趣,“小黑你給我說說你們的工作唄,地址翻譯是怎麼一回事兒,為什麼懷念以前呢?”

小黑調整了下坐姿,咕嚕咕嚕喝了幾口水說道,“這話說來可就話長了”

接下來小黑開始給我講起了歷史故事······

8086

原來我們們的祖先叫8086,小黑還給我看了他的照片

那是一個純真質樸的年代,雖然工作效能不高,不過那個年代的程式都很簡單,我們的祖先一問世就成為了明星,稱得上那個時代的頂流了。

看到照片中的那些金屬針腳了嗎?那是我們CPU和外界打交道的觸角,每一根都有不同的作用。

通過這些觸角,CPU就可以跟記憶體打交道,獲取指令和資料,辛勤的幹活啦。

那個年代,條件比較差,能湊合的就湊合,能共用的就共用。這不,你看祖先CPU的地址匯流排針腳和資料匯流排針腳就共用了。

祖先是一個16位的CPU,資料(Data)匯流排就有16位,一次性可以傳輸16個位元位。和地址(Address)匯流排湊合著一起共用,於是就取名AD0-AD15。

不過祖先的地址匯流排卻不止16個,還多出了A16-A19整整4個呢!這樣有20個地址線,可以定址1MB的記憶體了!

但是祖先的暫存器都是16位的啊,只能存放16位的地址。不過他們很聰明,發明了一個叫分段式儲存管理的方法,把記憶體劃分為最大64KB的小塊,為什麼是64KB呢,因為16位地址最多隻能定址這麼大了。然後又加了幾個叫做段暫存器的東西,指向這些塊的開頭,這樣,通過段地址+段內偏移地址的方式,就能訪問更多的記憶體了。

32位時代

後來啊,祖先的那點計算能力越來越捉襟見肘,實在是跟不上時代了。家族中的年輕一代開始挑大樑,80286和80386CPU相繼問世,尤其是80386,成為了劃時代的存在。

到了80386時代,我們與外界通訊的引腳就更多了,並且變成了32位的CPU,那個時候,生活條件就變好了,地址線和資料線再也不用共享引腳了。

後來,人類變得越來越貪心,想要一邊聽音樂,一邊還要上網,同時還要編輯文件,這就同時需要執行多個程式。

這個時候,有人發現了商機,開發了一個叫作業系統的東西,原來那些程式不再直接和我們CPU打交道了,而是和作業系統打交道,作業系統再和我們打交道,中間商賺差價說的就是他們!

作業系統這玩意兒很聰明啊,通過時間片劃分讓我們CPU來輪流執行多個程式,一會兒讓我們執行音樂播放,一會兒讓我們執行瀏覽器程式,一會兒又讓我們執行文件編輯程式。我們是無所謂啊,給什麼程式碼不是程式碼啊,我們不挑,埋頭苦幹就是了。人類的反應速度跟我們就差得遠了,他們還以為這些程式真的是同時執行的呢。

虛擬記憶體

不過隨之而來出現了一個大問題,這麼多程式都要執行,大家擠在一個記憶體裡,經常發生摩擦,衝突不斷。

先祖們為了此事殫精竭慮,終於想出了一個好辦法,一直沿用至今。

他們提出了一個虛擬地址的東西,所有程式使用的地址都是一個虛擬的地址,在真正和記憶體打交道的時候,我們們CPU內部工作人員再給翻譯成真實的記憶體地址,關於這事兒,記憶體那傢伙一直被我們矇在鼓裡。

這樣一來,每個程式都可以用的是0x00000000到0xffffffff總共4GB這麼大範圍的地址空間,當然不會真的給他們那麼多空間,記憶體那傢伙總共才4GB呢,而是要按需申請分配。分配的單元是按照來進行的,32位的CPU一個頁是4KB。這些分配管理的累活就讓作業系統來幹了,中間商不能光拿好處不幹正事,至於我們CPU,做好地址翻譯的工作就好了。

為此,在我們暫存器內部專門添置了一個新的暫存器CR3,用來指向一個地址翻譯查詢字典,字典劃分了兩級目錄。我們把一個32位的地址劃分了3部分,前面兩部分分別指向兩級目錄中的條目,用來定位這個地址在實體記憶體的哪個頁面,最後一部分就是指向實體記憶體頁面的偏移,這樣就完成了地址的翻譯工作。

每個程式有不同的地址空間,切換程式的時候,把CR3的內容換一下就使用新程式的翻譯字典,特別的方便。

我們把這種記憶體管理方式叫做分頁式記憶體管理

真佩服先祖們的智慧,這樣巧妙的把各個程式隔離開來,後來我們把這種工作模式叫做保護模式,把之前那種直接使用真實記憶體地址的工作模式叫做實地址模式

分頁交換

人類變得越來越貪婪,程式變得越來越多,對記憶體的需求也越來越大。隨著這些程式都不斷申請記憶體頁面,記憶體空間很快就要耗盡了。

我們看在眼裡,急在心裡,後來找作業系統協商,看看這問題該怎麼辦。

作業系統那傢伙也不賴,想出了一個好辦法。記憶體的大小有限,但是硬碟給力啊,硬碟空間大的多,去硬碟上劃一塊區域來,把記憶體里長時間沒有用到的頁面給換到這塊區域裡去,然後做個標記。如果後面誰要訪問那個頁面,我們們CPU就檢查如果有這個標記,就傳送一個頁錯誤的中斷訊號告訴作業系統去把這個頁面換回來。

通過我們之間的配合,解決了記憶體緊張的危機。後來我們把這個技術叫做記憶體分頁交換

現在

時間過得很快,到了我們這一輩,記憶體變得更大了,16GB都是小case,32GB也很常見。

除了記憶體,我們CPU本身也更先進了,別的不說,你光看看我們們現在的引腳數那比先祖們那幾輩就不可同日而語。

我們不僅從32位變成了64位,還從單核變成了多核,像我所在的CPU就有8個車間,8核並行執行,比起先祖那個年代簡直有云泥之別。

彩蛋

和小黑閒談間,我們車間的老K突然出現在了門口。

“阿Q原來你在這裡,讓我好找,趕快回去吧,隔壁二號車間的虎子說我們改了他們的資料,上門來鬧事了······”

預知後事如何,請關注後續精彩······

往期熱門回顧

完了!CPU一味求快出事兒了!

可怕!CPU竟成了黑客的幫凶!

雜湊表哪家強?幾大程式語言吵起來了!

核心地址空間大冒險4:執行緒切換

震撼!全網第一張原始碼分析全景圖揭祕Nginx

一個整數+1引發的災難

一網打盡!每個程式猿都該瞭解的黑客技術大彙總

看過無數Java GC文章,這5個問題你也未必知道!

一個Java物件的回憶錄:垃圾回收

誰動了你的HTTPS流量?

路由器裡的廣告祕密

一個HTTP資料包的奇幻之旅

我是一個流氓軟體執行緒

相關文章