深入理解記憶體(2):發展曆史,記憶體位址

來源:互聯網
上載者:User
文章目錄
  • 簡單的曆史故事
  • 記憶體配置
  •  

事物的發展總是從簡單到複雜,當然我們學習應該是先從簡單到複雜學習,然後慢慢思考融匯貫通,最後又把複雜化為簡單.

我們先來看看在電腦剛出來不久記憶體是怎麼被使用,然後隨著技術的發展又是怎麼演化的.當然這裡的描述只是簡單化的體現下那種思想,很多細節未必準確.

 

簡單的曆史故事

1.單使用者使用記憶體

剛開始的時候電腦功能相當簡單,而且用電腦的也都是些高手專家,對硬體相當的瞭解.此時也沒有啥作業系統,(實際上可能顯示器也可以不需要),電腦磁碟上除了儲存一些供你調用的標準庫函數外啥都沒有.開機後CPU仍然靜靜的獃著不幹嘛,記憶體裡也是空的啥東東都沒有(現在我們用的電腦一開機,記憶體至少會載入作業系統代碼,所以永遠不可能是空的).

此時你要做啥操作就敲入些命令,然後就調用儲存的庫函數,自然是先把庫函數載入到記憶體,然後再在CPU上面跑,跑完了可能就是列印些啥資訊出來(此時還沒檔案的概念,磁碟上不會儲存你的結果資料).然後接下來CPU就休息去了,記憶體也空了.你不去調用庫函數時,電腦就傻傻的呆了啥都不幹.

 

2.批處理

像上面說的你敲入些命令時電腦才給你幹活,這樣效率太低了.於是做了些改進,首先是出現了作業系統的雛形,開啟電腦後會載入一些作業系統的代碼常駐在記憶體中.此時出現了檔案,可以把很多待操作的命令事先寫好,然後儲存成一個個的檔案.然後電腦可以按順序給你從頭跑到尾,就就是你啟動一個操作後就可以走人了,然後電腦會全部給你按順序處理完,一次處理一大批嘛.所以叫批處理.

此時記憶體會被分為兩塊,一小塊給常駐記憶體的作業系統.其他的給使用者程式跑(記憶體和CPU只能給單個使用者程式用)

 

3.儲存,切換

批處理只能從頭到尾按順序跑,如果中間某個程式要跑太久太久,後面的就沒法跑了.一個程式一當跑起來你如果把它停了下次只能重新再跑.於是有人琢磨著如果程式在記憶體中跑了一段時間還沒完,可以把記憶體中所有的資訊切換出來儲存到磁碟上.等下次再跑時可以不用從頭跑,而是再把磁碟上的資訊切換進記憶體接著上次的跑.

 

4.分時,多進程

前面說的三種情況都是一次只能一個使用者程式在跑,此時有多少記憶體就用多少,不夠用就報錯唄,很簡單,沒涉及啥太複雜的技術.但是這樣顯然不能充分利用CPU,記憶體資源.因為記憶體變得越來越大,而一個程式可能只用佔一點點記憶體,這樣會空出一大片.而且CPU也是跑得賊快的.一眨眼就跑完了,只有你進行那些IO操作時可能就慢的像蝸牛了.於是有人就琢磨著,應該可以讓幾個程式同時跑,一個程式對應一個進程,都同時在記憶體中佔一片地盤.然後就通過分時輪流使用CPU.

此時作業系統做的事就多很多了啊.首先是要保證每個進程的獨立,不能讓一個進程輕易使用別的進程的記憶體了.然後有時還得實現進程間的通訊,要防止死結之類的麻煩事.

 

記憶體配置

當出現了多進程的概念後.自然就需要想出很多花樣出合理的分配和利用記憶體這個寶貴的東東.作業系統記憶體管理中涉及到的術語可能看得人頭大.實際上用通俗點的話歸納下就做兩方面的事

 

1.合理的給每個進程分配一塊記憶體.當記憶體滿了時把一部分進程的記憶體切換出去放硬碟上.恰當的時候再從硬碟切換回記憶體

2.虛擬記憶體技術.實際上就是把硬碟也當記憶體用,只不過要多做些切換罷了,在硬碟和記憶體之間切換.

 

記憶體位址

先不管記憶體怎麼分塊.我們首先會想到要用記憶體該怎麼去訪問? 你可能說肯定是通過地址嘛.硬碟訪問就是通過一個地址,然後用磁頭去讀寫嘛.

 

記憶體與硬碟間來回切換,會導致記憶體位址變化

如果只讓一個進程在記憶體中,開始跑時全部載入,然後跑完了再釋放記憶體.這樣像硬碟一樣直接通過記憶體的實際地址訪問是沒太多問題的. 但如果是多進程共用記憶體,並且還會在硬碟和記憶體間切換.此時就會有問題.假如你的程式跑了一部分,然後全部切換到硬碟,那些儲存的資訊裡面有涉及到記憶體位址.等再切換到記憶體中時,你之前占的那記憶體可能被別的進程佔用了,而系統分給你的是另外一塊記憶體.那樣的話你根據之前那些記憶體位址資訊再讀寫資料時就會出錯.咋整呢?

 

記憶體物理地址與邏輯地址

像在C,C++中我們一般用指標來指向記憶體位址.那你可能會問指標指的記憶體位址是記憶體的物理地址嗎 ? 

如果是實際地址的話就出現上面說的問題了. 指標指向的實際上是一個邏輯地址.你可以這樣想,在一個進程內我們先把所有指標指定一些固定的值(也就是邏輯地址),比如從0開始遞增,然後實際上載入到記憶體中時(每次載入時的起始地址可能不一樣),再用邏輯地址做位移量加上記憶體中的實際起始地址就是實際的記憶體位址了. 你可能會奇怪那麼每個進程的記憶體塊的起始位置放哪裡啊? 那個起始地址值是放在寄存器中.寄存器實際上可以看成一個速度更快的記憶體,在CPU呆一起,所以劃分模組時我們一般分到CPU那一塊去了.

當然從邏輯地址映射到物理地址肯定不止一種方法的,如果用到了分頁技術,我們還可以把每個邏輯地址映射到物理地址中的不同頁面(page)

不過上面說的也不是太準確,我們只能說我們用的絕大部分應用程式中涉及到的指標指向的記憶體位址是指向邏輯地址的.實際上也有些特殊的情況指標會指向記憶體物理地址,比如在嵌入式系統中,可能就一個進程用那記憶體,不用做啥切換,我們就可以用指標直接指向實際的實體記憶體地址.另外一般的案頭電腦中,記憶體中會劃分出一塊固定的記憶體來載入作業系統代碼.作業系統中一部分核心程式會常駐記憶體,一直呆一個固定的地方,不會被切換到硬碟上去.此時指標也可以直接指向實體記憶體.

 虛擬位址空間

 

虛擬位址與邏輯地址關係

毫無疑問除了物理地址是真實存在的記憶體位址外.其他地址都是我們虛構出來的.我們知道作業系統把硬體封裝抽象了,我們編程時基本不會直接面對硬體.那我們可以把虛擬位址空間看成是抽象出來的記憶體.當每個程式運行時(在windows中,linux或其他系統我還不確定)系統會給程式分配一個虛擬位址空間,就相當於給你一個記憶體,你盡量去用就是,不用管其他的事了.當你申請一塊記憶體後會返回記憶體位址,這個就是邏輯地址,邏輯地址就是指向虛擬位址空間中某塊地址

 

虛擬位址空間大小

在32位windows系統中,可用的虛擬位址空間是2的32次方,也就是4G. 你可能會奇怪這是怎麼算出來的啊.因為32位系統顧名思義是因為處理器一次只能處理32位bit的資訊,這樣一來地址匯流排傳的記憶體位址最多隻能用32個bit來表示,所以只能表示4G的記憶體位址了.不過我們會把其中的2G分給系統空間,只留下2G給使用者空間.所以任何一個win32應用程式運行時系統會給分配2G的虛擬位址空間.
不過你可以指定讓使用者空間超過2G,最大可增至3G,不過這樣系統空間就僅有1G了.

在64們的windows系統中,可用的虛擬位址空間是2的64次方,貌似是40多億G.但顯然我們用不了這麼多,用了也沒意義.所以我們只用到這些虛擬位址空間的一部分.8T使用者空間, 248T系統空間.所以任何一個win64應用程式運行時系統會給分配8T的虛擬位址空間

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.