幾個(gè)概念
- 程序
存儲(chǔ)在磁盤上的文件手蝎,在執(zhí)行的時(shí)候加載如內(nèi)存 - 內(nèi)存
分為DRAM,和SRAM
DRAM:可以就看成我們買的內(nèi)存條
SRAM:可以就看是CPU中的一二三級(jí)緩存
虛擬內(nèi)存
好處:
- 將主存(DRAM)進(jìn)行抽象,通過(guò)分頁(yè)機(jī)制,實(shí)現(xiàn):主存中保存活動(dòng)的區(qū)域哥纫,并根據(jù)需要(缺頁(yè)異常和正常存取)在主存之間傳送數(shù)據(jù)酌予。高效的使用了主存
- 為進(jìn)城提供一直的地址空間磺箕,簡(jiǎn)化內(nèi)存管理,和程序的鏈接
- 保護(hù)每個(gè)進(jìn)城的地址空間不被其他進(jìn)程破壞抛虫。
程序和DRAM
DRAM可以看做是一個(gè)M個(gè)連續(xù)字節(jié)大小的數(shù)組松靡,每個(gè)字節(jié)都有唯一的地址:物理地址。
CPU直接訪問(wèn)DRAM使用物理地址的方式成為:物理尋址建椰。
早起程序使用物理尋址雕欺,但是目前大多使用虛擬尋址。目前仍有一些特殊的機(jī)器使用物理尋址棉姐。
虛擬尋址
指的是:CPU訪問(wèn)DRAM的地址不是物理地址屠列,稱為虛擬地址。需要由CPU中的內(nèi)存管理單元(MMU)將虛擬地址轉(zhuǎn)換為物理地址伞矩。然后MMU利用轉(zhuǎn)換得到的物理地址發(fā)給DRAM笛洛,DRAM將數(shù)據(jù)直接送給CPU。
虛擬內(nèi)存VM
在物理內(nèi)存上面抽象出的一層成為虛擬內(nèi)存乃坤,主要是用來(lái)管理物理內(nèi)存的苛让。
虛擬內(nèi)存對(duì)應(yīng)一個(gè)虛擬地址空間沟蔑,物理內(nèi)存對(duì)應(yīng)一個(gè)物理地址空間。也就是兩個(gè)M字節(jié)的連續(xù)數(shù)組狱杰。分別兩種尋址方式瘦材。
其中虛擬內(nèi)存中的某個(gè)地址對(duì)應(yīng)物理內(nèi)存中的某個(gè)地址,可以使一對(duì)多的關(guān)系仿畸。
虛擬頁(yè)
VM將內(nèi)存又劃分為很多的小塊食棕,每塊大4K,不固定错沽,可變簿晓,以后用P表示一個(gè)頁(yè)的大小,每個(gè)單位成為虛擬頁(yè)
同時(shí)物理內(nèi)存頁(yè)被分頁(yè)千埃,每個(gè)單位成為頁(yè)幀
虛擬內(nèi)存通過(guò)分頁(yè)機(jī)制達(dá)到將將程序的活動(dòng)部分加載進(jìn)內(nèi)存抢蚀。
可以理解為,將程序也按照每塊P大小分割镰禾,并不全部將程序加載進(jìn)內(nèi)存皿曲,而是在需要那一頁(yè)的時(shí)候,將這一頁(yè)加載進(jìn)內(nèi)存吴侦。(這里涉及到缺頁(yè)異常)
每個(gè)頁(yè)可能有如下三種不想交的狀態(tài)屋休,每個(gè)時(shí)刻只能有一種:
- 未分配
指的是,VM中的一頁(yè)备韧,并沒(méi)有被使用劫樟。所以這一虛擬頁(yè)沒(méi)有對(duì)應(yīng)的頁(yè)幀(物理內(nèi)存的一頁(yè))。 - 未緩存
指的是织堂,虛擬頁(yè)被內(nèi)存使用叠艳,相當(dāng)于一個(gè)變量被聲明。但是還沒(méi)有定義易阳。所以附较,只是在VM中占用,但是還沒(méi)有分配頁(yè)幀潦俺。(沒(méi)有分配頁(yè)幀的意思是拒课,對(duì)應(yīng)的值沒(méi)有加載進(jìn)物理內(nèi)存) - 以緩存
值得是,VM中的虛擬頁(yè)事示,已經(jīng)連接到頁(yè)幀早像,同時(shí)也從磁盤中讀取數(shù)據(jù)存儲(chǔ)在對(duì)應(yīng)的頁(yè)幀。
圖上說(shuō)是虛擬頁(yè)存儲(chǔ)在磁盤上肖爵?大哥卢鹦,主存是緩存,虛擬頁(yè)怎么可能比緩存慢劝堪。
頁(yè)表?xiàng)l目(Page Table Entry)維護(hù)了虛擬頁(yè)到頁(yè)幀的轉(zhuǎn)換冀自,由操作系統(tǒng)維護(hù)谁榜。
頁(yè)表?xiàng)l目存儲(chǔ)在物理內(nèi)存中。
頁(yè)表?xiàng)l目每一項(xiàng)由:有效位凡纳,和物理頁(yè)號(hào)組成。
有效位指的是:1該虛擬頁(yè)已經(jīng)指向頁(yè)幀(以緩存)帝蒿,0該虛擬頁(yè)沒(méi)有被使用或者已使用但是未指向頁(yè)幀(未分配和未緩存)荐糜。
物理頁(yè)號(hào),指的是虛擬頁(yè)指向的頁(yè)幀地址葛超。
指向物理內(nèi)存的是以緩存暴氏,指向VP的是未緩存,NULL的代表未分配绣张。
除了有效位以外答渔,頁(yè)表中還可以存儲(chǔ)其他的信息,比如是否可讀之類的侥涵。
頁(yè)命中
命中可以理解成沼撕,當(dāng)CPU取數(shù)據(jù)的時(shí)候芜飘,能夠直接主存中獲取,成為命中嗦明。如果數(shù)據(jù)還沒(méi)有存進(jìn)主存成為未命中。
在虛擬內(nèi)存中娶牌,DRAM緩存不命中成為缺頁(yè)。
當(dāng)CPU讀取數(shù)據(jù)的時(shí)候回發(fā)生兩種情況:
1. 虛擬地址指向的表項(xiàng)PTE中有效位為0
可能是未緩存或者是未分配汹桦,這時(shí)候觸發(fā)一個(gè)缺頁(yè)異常!
linux下营勤,MMU試圖翻譯一個(gè)虛擬地址A時(shí),觸發(fā)一個(gè)缺頁(yè)葛作。這個(gè)異常導(dǎo)致控制轉(zhuǎn)移到內(nèi)核的缺頁(yè)處理程序::
- 確認(rèn)A地址是合法。
缺頁(yè)處理程序搜索區(qū)域結(jié)構(gòu)的鏈表猖凛,把A和每個(gè)區(qū)域結(jié)構(gòu)中的vm_start
和vm_end
做比較赂蠢。如果指令不合法,發(fā)生一個(gè)段錯(cuò)誤segmatation fault
,結(jié)束程序辨泳。
因?yàn)锳地址可能是個(gè)函數(shù)虱岂,或是堆上或是棧上數(shù)據(jù)玖院,所有要每個(gè)都搜索。 - 地址合法的情況下第岖,確認(rèn)是否有權(quán)限
也就是难菌,進(jìn)城是否又讀寫或執(zhí)行該區(qū)域內(nèi)頁(yè)幀的權(quán)限。 - 權(quán)限合法的情況下蔑滓,加載進(jìn)主存
當(dāng)物理內(nèi)存未滿的情況下郊酒,可能是直接找個(gè)空閑的地方加載頁(yè)幀。(不知道啊键袱。書上都沒(méi)寫燎窘。可能是這樣)
否則蹄咖,缺頁(yè)處理程序在物理內(nèi)存中選擇一個(gè)犧牲頁(yè)褐健,然后,如果該犧牲也被修改過(guò)了澜汤,那么將頁(yè)幀內(nèi)容寫會(huì)磁盤蚜迅。然后將新的磁盤內(nèi)容加載進(jìn)頁(yè)幀。同時(shí)更新頁(yè)表俊抵。
當(dāng)缺頁(yè)處理程序返回的時(shí)候慢叨,CPU重新啟動(dòng)引起缺頁(yè)的指令,這時(shí)候A已經(jīng)是以緩存的务蝠。正常讀取拍谐。
選擇犧牲頁(yè),應(yīng)該是又算法的馏段,局部性原理轩拨。
其中在第一部搜索接受的時(shí)候,結(jié)構(gòu)是這樣的:
缺頁(yè)之前:
缺頁(yè)處理程序返回之后:
當(dāng)我工作集超出了物理內(nèi)存的大小院喜,會(huì)產(chǎn)生抖動(dòng)亡蓉,頁(yè)面將不斷的換進(jìn)換出。
虛擬頁(yè)與共享庫(kù)
當(dāng)多個(gè)程序調(diào)用同一個(gè)共享庫(kù)時(shí)喷舀,程序沒(méi)必要為每一個(gè)程序加載一次共享庫(kù)硫麻。
而是不同程序的虛擬頁(yè)指向同一頁(yè)幀拿愧。
產(chǎn)生了多對(duì)一的情形:
不同程序的虛擬頁(yè)對(duì)應(yīng)同一頁(yè)幀
頁(yè)面調(diào)度和虛擬地址空間的結(jié)合有點(diǎn):
- 簡(jiǎn)化程序鏈接
每個(gè)程序可以采用相同基本格式,從同一虛擬地址開(kāi)始唾戚。 - 簡(jiǎn)化加載
當(dāng)程序加載進(jìn)內(nèi)存的時(shí)候叹坦,只需要分配虛擬頁(yè)募书,而不必加載進(jìn)頁(yè)幀。當(dāng)需要的時(shí)候毕箍,發(fā)生缺頁(yè)異常而柑,然后加載。按需加載粹排。 - 簡(jiǎn)化共享
方便共享庫(kù)的加載顽耳。 - 簡(jiǎn)化內(nèi)存分配
在虛擬地址空間中連續(xù)的地址妙同,在物理地址空間中不一定連續(xù)粥帚。
也就是程序在堆棧中分配的地址芒涡,在物理空間中可能并不是連續(xù)的。
地址翻譯過(guò)程
- 處理器生成虛擬地址傳送給MMU
- MMU生成PTE地址赠群,并從主存或高速緩存請(qǐng)求乎串,去訪問(wèn)的是頁(yè)表?xiàng)l目叹誉。應(yīng)該是將整一項(xiàng)返回給MMU
- 高速緩存(查找頁(yè)表?xiàng)l目)以后返回一項(xiàng)給MMU
命中情況下
- MMU根據(jù)返回的PTE(此時(shí)PTE的有效位為1)構(gòu)造物理地址长豁,再次發(fā)送給主存
- 主存直接讀取數(shù)據(jù)匠襟,發(fā)送給CPU
缺頁(yè)
- PTE有效位為0酸舍,MMU觸發(fā)缺頁(yè)異常。CPU中的控制轉(zhuǎn)移到內(nèi)核中的缺一處理程序
- 確定犧牲頁(yè)忽舟,替換叮阅。缺頁(yè)處理程序更新PTE
- 確立處理程序返回浩姥,CPU再次執(zhí)行導(dǎo)致缺頁(yè)的程序
TLB緩存
CPU每次請(qǐng)求状您,MMU都去查找一次過(guò)于浪費(fèi)膏孟。
因此MMU中有一個(gè)翻譯后背緩沖器(Tanslation Lookaside Buffer)
在上面的第2部時(shí)。變?yōu)椋篗MU去查找TLB颗搂,如果沒(méi)查找到幕垦,再去主存中查找頁(yè)表?xiàng)l目先改。返回后跟新TLB仇奶。
頁(yè)表分級(jí)
暫時(shí)不是很懂。不過(guò)有點(diǎn)理解吧
二. linux虛擬內(nèi)存系統(tǒng)
execve函數(shù)
調(diào)用execve函數(shù)以后執(zhí)行以下步驟
- 刪除已存在的用戶區(qū)域
刪除當(dāng)前進(jìn)程虛擬地址中用戶部分已存在的結(jié)構(gòu)别惦,.text掸掸,.data等 - 映射私有區(qū)域
為因程序的代碼扰付,數(shù)據(jù)仁讨,bss和站區(qū)域創(chuàng)建新的結(jié)構(gòu)洞豁。
這些區(qū)域都是私有的,代碼區(qū)和數(shù)據(jù)區(qū)映射對(duì)應(yīng)文件的.text闰挡,.data礁哄。而.bss映射到匿名文件桐绒,其大小保存在要執(zhí)行的文件中茉继。 - 映射共享區(qū)域
如果要執(zhí)行的程序調(diào)用了共享庫(kù)之類的烁竭,那么需要將這些庫(kù)映射到用戶虛擬空間中的共享區(qū)域派撕。 - 設(shè)置程序計(jì)數(shù)器(PC)
最后一件事情是設(shè)置進(jìn)程上下文中的程序計(jì)數(shù)器终吼,使其指向代碼區(qū)域的入口點(diǎn)。
圖中請(qǐng)求二進(jìn)制0的地方,為映射到匿名文件
mmap()
。
動(dòng)態(tài)內(nèi)存分配
分配器指的是new
,delete
,malloc
,free
這些良姆。
分為顯示分配器歇盼,如上面的四個(gè)豹缀,也就是需要用戶手動(dòng)釋放
隱式分配器也就是垃圾收集器慨代,比如java等語(yǔ)言。
malloc實(shí)現(xiàn)
#include <stdlib.h>
void *malloc(size_t size);
返回一個(gè)void *
指針氮惯,可以隱式轉(zhuǎn)化為任意類型妇汗。
其分配的塊總是對(duì)其的说莫。32下為8的倍數(shù)储狭,64位下是16的倍數(shù)辽狈。
malloc
并不初始化其分配的內(nèi)存,calloc
初始化驮配。
malloc
的實(shí)現(xiàn)壮锻,基于mmap()
和sbrk()
躯保。
#include <unistd.h>
void *sbrk(intptr_t incr);
以后補(bǔ)