1. 程式人生 > >淺談作業系統之虛擬記憶體

淺談作業系統之虛擬記憶體

我們把記憶體可以看成一個一維陣列,那麼這個陣列的下標就是記憶體的實體地址,CPU用記憶體的實體地址來定位他想獲取的記憶體塊(陣列中的內容),我們把這種方式稱為物理定址
如下圖:
這裡寫圖片描述
我們都知道,我們寫的程式經過編譯器編譯成機器級語言後會被儲存到檔案中,當我們要執行它的時候,作業系統會將其載入到記憶體中並交給CPU去處理,CPU只處理一條條的指令。設想一下,如果記憶體中有一個程式,CPU通過系統匯流排去和記憶體中的指令和資料進行互動時,採用物理定址將非常自然、方便,但是如果是兩個程式或者多個程式會出現怎樣的情況?
這裡寫圖片描述
我們會看到兩個程式中都有一條指令 mov eax (100),注意,這裡的100是相對於正在執行的程序而言(單核),如果直接使用實體地址,那麼就得分析每一個程序中的每一條指令,看看哪一個指令是操作記憶體的,並且要知道該程序的基值地址,然後把該指令中的位置(偏移量)加上該程序的基地址,分析指令是非常麻煩的,不容易實現,所以,我們引入了虛擬定址(邏輯地址),如下圖:
這裡寫圖片描述

我們從圖中可以看到,在使用虛擬定址時(用邏輯地址),CPU會生成一個虛擬地址(邏輯地址),用這個虛擬地址來訪問主存時需要經過一個MMU(記憶體管理單元)來對這個虛擬地址進行翻譯,把這個虛擬地址變為真正的實體地址,對於每一個程序而言,它在執行的時候基址暫存器中的值是不一樣的,比如上面的程式1,它的基址暫存器中的值為0,而對於程式2 暫存器中的值1000,這樣一來CPU就不用分析當前程序中的指令了,當CPU執行一個指令的時候,它就認為所有關於記憶體地址的地址都是虛擬地址,然後發給MMU,經過MMU後就會將其翻譯成真實的地址,最後,記憶體通過系統匯流排把資料給CPU傳了過去。這裡注意一個問題:MMU怎麼知道當前程序的基地址?這是因為作業系統知道每一個程序的基地址,MMU(記憶體管理單元)硬體會利用放在主存中的查詢表來動態地翻譯虛擬地址,該表的內容是由作業系統管理的,也就是說,在程序進行切換的時候,這個基值暫存器中的值是會發生改變的。
那虛擬地址到底長什麼樣?請看下圖:
這裡寫圖片描述

每一個程序都有一個虛擬地址空間,而且結構非常相似
這樣看起來一切順利,但事實並非如此,因為我們的電腦記憶體很是有限,有些應用程式它需要很大的記憶體來執行它,這樣一來,有時記憶體就不夠用了,那應該怎樣解決呢?
我們想到了區域性性原理(上帝的法則),區域性性原理有兩個:
① 時間區域性性: 意思是說,我電腦中的程式某一條指令在使用完之後,在不久的將來有很大可能再次地使用它
② 空間區域性性: 這個是說,我電腦中的某一塊記憶體在使用時,在不久的將來會使用記憶體地址相近的一塊記憶體區域
所以我們決定,我們把應用程式程式碼不全部載入到記憶體中去,只是載入一小部分
接下來我們瞭解幾個新的概念:
虛擬頁和物理頁
虛擬儲存器系統把虛擬儲存器分割成大小固定的塊,這一塊一塊的儲存器中的內容我們稱為虛擬頁
[虛擬頁不是真實存在的,而是邏輯上的],同樣的道理,我們把物理儲存器分割成物理頁(記憶體中)
擁有虛擬頁地址和物理頁地址資訊的頁表
頁表就是一個存放頁表條目(Page Table Entry,PTE)的陣列,裡面存放了若干個頁表條目,那麼什麼是頁表條目呢?頁表條目其實就是描述虛擬頁資訊的一塊記憶體[物理](也可以說成資料結構[邏輯])如下圖
這裡寫圖片描述
我們可以簡單地認為頁表條目是由一個有效位和一個n位地址欄位組成,有效位表明了該虛擬頁當前是否被快取到記憶體中了
瞭解了頁表,我們再來看看物理頁、虛擬頁和頁表之間的一個關係,虛擬頁是虛擬儲存系統把一個程式的虛擬地址空間劃分了若干個虛擬頁,(注意,這個虛擬頁不是真正存在的東西),虛擬頁有三種情況,一種是未分配的,不佔用記憶體空間,第二種是未快取的,也就是以儲存在磁碟上的形式存在,還有一種是快取的,也就是以儲存在記憶體中的形式存在,接下來我門來看一個圖
這裡寫圖片描述
從這個圖中我們可以看到,頁表條目其實就是一個虛擬頁的描述,它描述了虛擬頁是否被快取在記憶體中(有效位),以及虛擬頁的儲存位置(未分配的為null,快取了的指向記憶體中物理頁的地址,未快取的指向磁碟中虛擬頁的位置)
下來我們看看這個邏輯地址是如何工作的
在頁面命中時,CPU硬體執行的步驟為:
第一步:處理器生成一個虛擬地址(VA),並把它傳送給MMU
第二步:MMU生成頁表條目的地址(PTEA),請求記憶體中的頁表,讓它給自己返回一個頁表條目(PTE)
第三步:MMU構造實體地址(PA),然後把這這個實體地址傳給記憶體(這時候是真實的實體地址),請求實體記憶體中的資料
第四步:記憶體返回所請求的資料給處理器
過程如下圖:
這裡寫圖片描述
這裡我們不討論頁面不命中的時候
我們來看一個總圖,來總結一下今天所提到的知識,看看到底在整個計算機中虛擬儲存技術是如何工作的
這裡寫圖片描述
到這裡,我們可以發現,虛擬記憶體技術的核心就是利用了局部性原理,把所要執行的程序中的資料不全部載入到記憶體中執行,而是載入一部分,當CPU在請求頁表時,發現頁表中的頁表條目中的有效位為0但是被虛擬儲存系統分配了的虛擬頁時,就會把這個虛擬頁從磁碟中排程到記憶體中(往往磁碟中的資料不常用,而在記憶體中的物理頁的資料是頻繁使用的資料),這樣一來,我們就實現了多個程序同時載入到記憶體中並且還佔用不是很多的記憶體的效果了

相關推薦

作業系統虛擬記憶體

我們把記憶體可以看成一個一維陣列,那麼這個陣列的下標就是記憶體的實體地址,CPU用記憶體的實體地址來定位他想獲取的記憶體塊(陣列中的內容),我們把這種方式稱為物理定址。 如下圖: 我們都知道,我們寫的程式經過編譯器編譯成機器級語言後會被儲存到檔案中,當我們要執行它的時候,作業系統會將其載入到記憶體中並

讀懂作業系統虛擬記憶體(一)

前言 由於個人對虛擬記憶體這塊特別感興趣,所以就直接暫且跳過其他,接下來將通過幾篇文章進行詳細講解,當然其他基礎內容後續在我進行相應整體學習後也會同步輸出文章,比如作業系統概念、程式連結、程序管理、頁面置換演算法、流水線、浮點指令、記憶體管理、磁碟管理等內容。不管周遭的環境如何,畢竟還很菜,堅持每天讓自己進步

讀懂作業系統虛擬記憶體地址翻譯原理分析篇(二)

前言 上一節我們整體概括通過MMU將虛擬地址翻譯為實體地址的轉換,這個過程都是按序就班的進行,一切都是基於已提前建立、分配虛擬頁、物理頁以及命中的前提,只是給和我一樣沒怎麼系統學習作業系統的童鞋首先在腦海裡有個大概的印象,本節我們從源頭開始分析為程式建立程序到對映到主存上整個詳細過程,本文將通過大量圖解來分析

讀懂作業系統虛擬記憶體TLB與快取(cache)關係篇(四)

前言 前面我們講到通過TLB快取頁表加快地址翻譯,通過上一節快取原理的講解為本節做鋪墊引入TLB和快取的關係,同時我們來完整梳理下從CPU產生虛擬地址最終對映為實體地址獲取資料的整個過程是怎樣的,若有錯誤之處,還請批評指正。 TLB和快取序列訪問(Serial TLB & Cache Access)

讀懂作業系統虛擬記憶體頁表(五)

前言 在一個擁有32位的地址空間,4KB的頁面(212),並且每個PTE為4個位元組,那麼頁表大小為4MB(4 * 232 / 212),但若為64位地址空間,4KB的頁面(212)且每個PTE為4位元組,那麼頁表大小為16TB(4 * 264 / 212),由於頁表常駐記憶體,佔用記憶體

作業系統記憶體的管理

簡介     記憶體是計算機中最重要的資源之一,通常情況下,實體記憶體無法容納下所有的程序。雖然實體記憶體的增長現在達到了N個GB,但比實體記憶體增長還快的是程式,所以無論實體記憶體如何增長,都趕不上程式增長的速度,所以作業系統如何有效的管理記憶體便顯得尤為重要。本文講述作業系統對於記憶體的管理的過去和現在

soaRESTful

let net ado soap 業務 淺談 網絡資源 ado.net 面向服務 今晚打算花點時間整理一下面向服務的架構oap。1傳統中小型項目架構一般是這樣的:(java)html+servlet+jdbc.和(.net)html+handler+ado.net都是在一臺

MYSQL日誌文件系統

mysql日誌文件系統 同大多數關系型數據庫一樣,日誌文件是MySQL數據庫的重要組成部分。MySQL有幾種不同的日誌文件,通常包括錯誤日誌文件,二進制日誌,通用日誌,慢查詢日誌,等等。這些日誌可以幫助我們定位mysqld內部發生的事件,數據庫性能故障,記錄數據的變更歷史,用戶恢復數據庫等等 MySQL

jqueryon()綁定事件和off()解除綁定事件

span syntax num this code value 自己 冒泡 屬性 off()函數用於移除元素上綁定的一個或多個事件的事件處理函數。 off()函數主要用於解除由on()函數綁定的事件處理函數。 該函數屬於jQuery對象(實例)。 語法 jQuery

架構路:單點登錄 SSO

用戶體驗 們的 建設 驗證機制 一個 簡單的 用戶登錄 集中 不同 前言:SSO 單點登錄   “半吊子”的全棧工程師又來了,技術類的文章才發表了兩篇,本來想先將主攻的幾個系列都開個頭(Nodejs、Java、前端、架構、全棧等等),無奈博客起步太晚,寫博文的時間又沒有很多

【JavaScript系列】JavaScript函數(一)

php 面向過程 .com func fun 面向對象編程 quest ice bbf 在編程語言中,無論是面向過程的C,兼備面過程和對象的c++,還是面向對象的編程語言,如java,.net,php等,函數均扮演著重要的角色。當然,在面向對象編程語言JavaScript中

go介面、執行緒、通道,純屬個人看法

淺談go介面、通道、執行緒 golang 接 口 Go 是靜態型別的。每一個變數有一個靜態的型別,也就是說,有一個已知型別並且在編譯時就確定下來了 type MyInt int var i int var j MyInt 那麼 i 的型別為 int 而 j 的型別為 MyInt。即使

MySQL EXPLAIN

在NoSQL橫行的時代,傳統關係型資料庫也還是有佔據它的一席之位。MySQL 的市場份額還是很大的。 據瞭解到的MySQL版本已經到5.7.20+了。目前本人伺服器上的還沒有這麼高。只在5.5+的版本上 說到MySQL免不了要提到的是 它的執行計劃,EXPLAIN 關鍵字可以模擬優化器執行S

nodeTCP

node之TCP 構建TCP伺服器 建立TCP伺服器端 TCP服務的事件 1.伺服器事件 2.連線事件

JavaScriptEvent

一  簡述JavaScript及其在瀏覽器中的地位 (一)  瀏覽器主要構成 雖然不同瀏覽器之間存在差異(如Google Chrome,Firefox,Safari和IE等),但單從瀏覽器構成來說,大同小異,大致可歸結為如下幾類: 1.User Interface

作業系統虛擬儲存管理

  虛擬儲存器 邏輯上擴充記憶體 1. 虛擬儲存器的基本概念    所謂“虛擬儲存器”,是指具有請求調入功能和置換功能,能從邏輯上對記憶體容量加以擴充的一種儲存器系統。          (1) 虛擬儲存管理下 &nbs

qmakepro、pri、prf、prl檔案

儘管每次和cmake對比起來,我們總是說 qmake 簡單、功能少。但是qmake仍然是一個非常複雜的東西,我想大多人應該和我一樣吧: 不是太清楚CONFIG等變數到底如何起作用的 用過的qmake內建變數和函式不超過20個 看Qt Creator原始碼或者

ES6promise 實際開發中的使用(一)

一:promise是個什麼鬼?   1.1:說起promise這個玩意,首先呢,我們來討論一下什麼叫做"非同步"而於此相反的呢就是"同步"呢,好,那下面讓寡人給大家舉個例子來講明白什麼是同步什麼是非同步.                 1.1.1:同步     同步就

【JavaScript系列】JavaScript函式(一)

       在程式語言中,無論是面向過程的C,兼備面過程和物件的c++,還是面向物件的程式語言,如java,.net,php等,函式均扮演著重要的角色。當然,在面向物件程式語言JavaScript中(嚴格來說,JS屬於弱面向物件程式語言),函式(function)更扮演著極其重要的角色和佔有極其重要的地位。

架構路:前後端分離模式》

前言:分離模式   對前後端分離研究了一段時間,恰逢公司有一個大專案決定嘗試使用前後端分離模式進行,便參與其中。該專案從2016年初立項至今,平平穩穩得度過,但也湧現出越來越多的問題,絕對不是說前後端分離模式不好,而是很多公司在嘗試前後端分離的時候沒有做好充分得