為了解決內(nèi)存安全和效率問(wèn)題,現(xiàn)在的計(jì)算機(jī)和操作系統(tǒng)引入了虛擬內(nèi)存和物理內(nèi)存,這里不做詳述。我們主要探討古毛,通過(guò)原理钦购,找到優(yōu)化App的方案檐盟。
虛擬內(nèi)存的工作原理:引用了虛擬內(nèi)存后 , 在我們認(rèn)為進(jìn)程中有一大片連續(xù)的內(nèi)存空間,也就是說(shuō)從 0x000000 ~ 0xffffff
我們是都可以訪問(wèn)的押桃。但是實(shí)際上這個(gè)內(nèi)存地址只是一個(gè)虛擬地址葵萎,而這個(gè)虛擬地址通過(guò)一張映射表映射后才可以獲取到真實(shí)的物理地址。
也就是說(shuō)唱凯,系統(tǒng)對(duì)真實(shí)物理內(nèi)存訪問(wèn)做了一層限制羡忘,只有被寫(xiě)到映射表中的地址才是被認(rèn)可可以訪問(wèn)的。虛擬地址
0x000000 ~ 0xffffff
這個(gè)范圍內(nèi)的任意地址我們都可以訪問(wèn)磕昼,但是這個(gè)虛擬地址對(duì)應(yīng)的實(shí)際物理地址是計(jì)算機(jī)來(lái)隨機(jī)分配到內(nèi)存頁(yè)上的卷雕。
工作原理如下:
顯然 , 引用虛擬內(nèi)存后就不存在通過(guò)偏移可以訪問(wèn)到其他進(jìn)程的地址空間的問(wèn)題了 。
因?yàn)槊總€(gè)進(jìn)程的映射表是單獨(dú)的票从,在你的進(jìn)程中隨便你怎么訪問(wèn)漫雕,這些地址都是受映射表限制的,其真實(shí)物理地址永遠(yuǎn)在規(guī)定范圍內(nèi)峰鄙,也就不存在通過(guò)偏移獲取到其他進(jìn)程的內(nèi)存空間的問(wèn)題了浸间。
而且 , 應(yīng)用每次被加載到內(nèi)存中 , 實(shí)際分配的物理內(nèi)存并不一定是固定或者連續(xù)的,這是因?yàn)閮?nèi)存分頁(yè)以及
懶加載
以及 ASLR 先馆。
Android 4.0
发框、Apple iOS4.3
、OS X Mountain Lion10.8
開(kāi)始全民引入ASLR
技術(shù)煤墙,而實(shí)際上自從引入ASLR
后梅惯,黑客的門(mén)檻也自此被拉高,不再是人人都可做黑客的年代了仿野。
cpu 尋址過(guò)程:通過(guò)虛擬內(nèi)存地址铣减,找到對(duì)應(yīng)進(jìn)程的映射表;通過(guò)映射表找到其對(duì)應(yīng)的真實(shí)物理地址脚作,進(jìn)而找到數(shù)據(jù)葫哗。這個(gè)過(guò)程被稱(chēng)為 地址翻譯缔刹,這個(gè)過(guò)程是由操作系統(tǒng)以及 cpu
上集成的一個(gè) 硬件單元 MMU
協(xié)同來(lái)完成的 。
虛擬內(nèi)存分頁(yè)
剛剛提到虛擬內(nèi)存和物理內(nèi)存通過(guò)映射表進(jìn)行映射劣针,但是這個(gè)映射并不可能是一一對(duì)應(yīng)的校镐,那樣就太過(guò)浪費(fèi)內(nèi)存了。為了解決效率問(wèn)題捺典,實(shí)際上真實(shí)物理內(nèi)存是分頁(yè)的鸟廓。而映射表同樣是以頁(yè)為單位的。換句話(huà)說(shuō)襟己,映射表只會(huì)映射到某一頁(yè)引谜,并不會(huì)映射到具體每一個(gè)地址。
Mac OS
擎浴、linux
內(nèi)存4kb
一頁(yè)员咽,iOS
是16kb
一頁(yè)≈ぃ可以使用PAGESIZE
命令贝室,在終端直接查看。
0 和 1 代表當(dāng)前地址有沒(méi)有在物理內(nèi)存中仿吞。
從上圖我們也可以看出档玻,進(jìn)程的實(shí)際物理內(nèi)存地址并不是連續(xù)的,而是由若干完整的內(nèi)存分頁(yè)組成茫藏。
- 當(dāng)應(yīng)用被加載到內(nèi)存中時(shí) ,并不會(huì)將整個(gè)應(yīng)用加載到內(nèi)存中霹琼。只會(huì)放用到的那一部分务傲。也就是
懶加載
, 換句話(huà)說(shuō)就是應(yīng)用使用多少 , 實(shí)際物理內(nèi)存就分配多少枣申。 - 當(dāng)應(yīng)用訪問(wèn)到某個(gè)地址售葡,映射表中為
0
,也就是說(shuō)它并沒(méi)有被加載到物理內(nèi)存中時(shí) , 系統(tǒng)就會(huì)立刻阻塞整個(gè)進(jìn)程 , 觸發(fā)一個(gè)缺頁(yè)中斷 忠藤,即Page Fault
挟伙。 - 當(dāng)一個(gè)
缺頁(yè)中斷
被觸發(fā),操作系統(tǒng)會(huì)從磁盤(pán)中重新讀取這頁(yè)數(shù)據(jù)到物理內(nèi)存上模孩,然后將映射表中虛擬內(nèi)存指向?qū)?yīng)物理內(nèi)存尖阔。 如果當(dāng)前內(nèi)存已滿(mǎn),操作系統(tǒng)會(huì)通過(guò)置換頁(yè)算法找一頁(yè)數(shù)據(jù)進(jìn)行覆蓋榨咐。這也是為什么開(kāi)再多的應(yīng)用也不會(huì)崩掉介却,但是之前開(kāi)的應(yīng)用再打開(kāi),就會(huì)重新啟動(dòng)的根本原因块茁。
思考:
Page Fault
會(huì)阻塞進(jìn)程齿坷,那么肯定會(huì)對(duì)性能產(chǎn)生影響桂肌,那么我們是不是可以在這里做一些優(yōu)化呢?