內(nèi)存是什么?
內(nèi)存對(duì)于用戶來說就是一個(gè)字節(jié)數(shù)組,我們可以根據(jù)地址來訪問到某個(gè)字節(jié)或者某些字節(jié):

很久之前的內(nèi)存
很久很久之前,一臺(tái)機(jī)器上只放置一個(gè)程序,操作系統(tǒng)僅僅作為一個(gè)函數(shù)庫(kù)存在。對(duì)于內(nèi)存來說,除去操作系統(tǒng)的代碼和數(shù)據(jù)占用的一些空間外,其余空間全部分配給正在運(yùn)行的那個(gè)程序,畫個(gè)圖就是這樣:

我們把運(yùn)行著的程序稱之為進(jìn)程。
同時(shí)運(yùn)行多個(gè)程序的內(nèi)存
后來人們覺得同時(shí)在一臺(tái)計(jì)算機(jī)上只運(yùn)行一個(gè)程序太虧了,就設(shè)計(jì)了一個(gè)可以同時(shí)運(yùn)行多個(gè)程序的機(jī)制。不過內(nèi)存條只有一個(gè),所以這些用戶程序只能共享同一個(gè)內(nèi)存條,只能把內(nèi)存的不同部分劃分給不同的用戶程序,畫個(gè)圖就像是這樣:

這樣子的話也有一些問題:
- 不同用戶程序只能使用給他們規(guī)定好的那部分內(nèi)存,也就是程序員在敲代碼的時(shí)候就應(yīng)該小心翼翼的計(jì)算自己使用的內(nèi)存有沒有占到別人家的地兒,這樣對(duì)碼農(nóng)很不友好有木有。
- 如果哪個(gè)心眼兒壞的家伙故意去讀取別人家的程序使用的內(nèi)存,這不就暴露了么,更嚴(yán)重的,這個(gè)壞家伙直接把別人家程序正在使用的內(nèi)存的某些字節(jié)給更新掉,這就是天坑了~
- 能使用的內(nèi)存空間都給規(guī)定好了,太少了有木有~
虛擬內(nèi)存
操作系統(tǒng)是個(gè)老好人,使命就是解決所有用戶感到麻煩的事情。設(shè)計(jì)操作系統(tǒng)的大叔覺得,如果讓用戶直接去操作內(nèi)存的話,用戶也不知道其他人到底使用了內(nèi)存的哪些字節(jié),自己可以使用哪些字節(jié),如果要做到這一點(diǎn)的話人們?cè)陂_發(fā)程序的時(shí)候還要聚到一起開個(gè)會(huì),把每個(gè)人該用哪塊內(nèi)存都規(guī)定好,即使規(guī)定好了用戶還得小心翼翼的避免使用了不屬于自己的那部分內(nèi)存。干脆,干脆就不讓用戶直接操作內(nèi)存了,讓用戶在編程序的時(shí)候直接把內(nèi)存想象成一個(gè)非常非常大的字節(jié)數(shù)組就好了,,自己在這個(gè)字節(jié)數(shù)組上可以隨便折騰,他們把這個(gè)非常大的字節(jié)數(shù)組稱之為虛擬內(nèi)存,由操作系統(tǒng)完成從虛擬內(nèi)存的虛擬地址到真實(shí)內(nèi)存的真實(shí)地址之間的映射工作。畫個(gè)圖就像這樣:

這樣還有問題,用戶越來越多,即使每個(gè)用戶都使用非常少的內(nèi)存空間,那加起來占用的內(nèi)存空間都可能超過了真實(shí)內(nèi)存的大小,更何況某些喪心病狂的程序員寫的程序里本身就使用了超過真正內(nèi)存大小的空間,這可怎么辦。這難不倒設(shè)計(jì)操作系統(tǒng)的大叔們,他們機(jī)智的把硬盤也拉了進(jìn)來。

操作系統(tǒng)完成由虛擬內(nèi)存地址到真實(shí)內(nèi)存地址或者磁盤地址之間的映射工作,這樣子給用戶提供的虛擬內(nèi)存的地址空間就可以非常非常大,用戶程序中那些很久都用不到的內(nèi)存空間可以被操作系統(tǒng)給搞到磁盤上邊存儲(chǔ),什么時(shí)候需要用了,又從磁盤中加載到真實(shí)內(nèi)存中,重要的是這個(gè)過程全部是操作系統(tǒng)自動(dòng)完成的,對(duì)于我們這些碼農(nóng)來說,編寫程序就像是在一個(gè)炒雞大的字節(jié)數(shù)組上將某個(gè)地方的數(shù)據(jù)搬到另一個(gè)地方,或者將某個(gè)地方的數(shù)據(jù)經(jīng)過CPU的某種加工之后再放到某個(gè)字節(jié)數(shù)組的某個(gè)地方,整個(gè)過程so easy,完全不用擔(dān)心有沒有讀取/覆蓋掉別人正在使用的內(nèi)存空間。
對(duì)于windows操作系統(tǒng)來說,虛擬內(nèi)存所需的磁盤空間從系統(tǒng)盤,一般是C盤分配,當(dāng)你的C盤剩余空間很少時(shí)就會(huì)導(dǎo)致很卡~
虛擬內(nèi)存結(jié)構(gòu)
我們說對(duì)于敲代碼的碼農(nóng)來說,虛擬內(nèi)存就是一個(gè)超級(jí)大的字節(jié)數(shù)組,不過這個(gè)字節(jié)數(shù)組也是被劃分為多個(gè)部分的,并不是每個(gè)地方用戶都可以訪問,一般的虛擬內(nèi)存結(jié)構(gòu)長(zhǎng)這樣:

用戶需要調(diào)用函數(shù)的時(shí)候,一般都會(huì)生成一個(gè)稱之為棧幀的結(jié)構(gòu),從而導(dǎo)致虛擬內(nèi)存中的棧空間增長(zhǎng)。
用戶需要單獨(dú)申請(qǐng)內(nèi)存空間時(shí),就會(huì)從堆空間分配,從而導(dǎo)致虛擬內(nèi)存中的堆空間增長(zhǎng)。
這里需要強(qiáng)調(diào)的一點(diǎn)是,我們平時(shí)所說的操作系統(tǒng)內(nèi)核不是一個(gè)進(jìn)程,而是指操作系統(tǒng)的代碼。