虚拟内存机制笔记
                            
                            
                            1.為什么要有虛擬內(nèi)存
在早期的計算機中,是沒有虛擬內(nèi)存的概念的。我們要運行一個程序,會把程序全部裝入內(nèi)存,然后運行。
當(dāng)運行多個程序時,經(jīng)常會出現(xiàn)以下問題:
1)進程地址空間不隔離,沒有權(quán)限保護。
由于程序都是直接訪問物理內(nèi)存,所以一個進程可以修改其他進程的內(nèi)存數(shù)據(jù),
甚至修改內(nèi)核地址空間中的數(shù)據(jù)。
2)內(nèi)存使用效率低
當(dāng)內(nèi)存空間不足時,要將其他程序暫時拷貝到硬盤,然后將新的程序裝入內(nèi)存運行。
由于大量的數(shù)據(jù)裝入裝出,內(nèi)存使用效率會十分低下。
3)程序運行的地址不確定
因為內(nèi)存地址是隨機分配的,所以程序運行的地址也是不確定的。2.虛擬地址和物理地址
對于32位系統(tǒng),尋址指針為4字節(jié),對應(yīng)的虛擬地址空間為0-2^32,即0-4G。
對于64位系統(tǒng),尋址指針為8字節(jié),對應(yīng)的虛擬地址空間為0-2^64,即0-16G。
要注意的是,這個地址空間是虛擬的,并非實際存在的。
Linux內(nèi)核把虛擬地址空間分為兩部分:用戶進程空間,內(nèi)核進程空間。
如下入所示:在緩存原理中,換入/換出的數(shù)據(jù)以塊為最小單位。在內(nèi)存管理時,頁是地址空間的最小單位。
虛擬地址空間劃分為多個固定大小的虛擬頁(VP),物理地址空間(DRAM內(nèi)存)劃分為多個固定大小的物理頁(PP),
虛擬頁和物理頁的大小是一樣的,通常為4KB。虛擬頁和物理頁存在著以下關(guān)系:
虛擬頁和磁盤文件映射,然后緩存到物理頁。
根據(jù)是否映射,是否緩存,可以將虛擬頁的狀態(tài)分為以下三種:
1)未映射的頁
即虛擬頁沒有映射到磁盤文件
2)未緩存的頁
虛擬頁映射到了磁盤文件,但是沒有緩存到物理頁,也就是內(nèi)存上。
3)緩存的頁
虛擬頁映射到了磁盤文件,并且緩存到物理頁
如下圖所示:3.虛擬地址的工作原理
對于進程來說,使用的都是虛擬地址。每個進程維護一個單獨的頁表。何為頁表?
頁表是一種數(shù)組結(jié)構(gòu),存放著各虛擬頁的狀態(tài),是否映射,是否緩存。1)數(shù)組的索引號,表示虛擬頁號
2)數(shù)組的值
若為null,表示未映射的頁
若非null,第一位表示有效位,為1,表明緩存的頁;為0,表明未緩存的頁。
其余位表示緩存到的物理頁號。頁表結(jié)構(gòu)圖如下:進程執(zhí)行時,當(dāng)需要訪問虛擬地址中存放的值時,步驟如下:
1)CPU會先找到虛擬地址所在的虛擬頁(VP3),根據(jù)頁表,找出頁表中第3條的值。
判斷有效位,為1,DRMA緩存命中,獲根據(jù)物理頁號,找到物理頁中的內(nèi)容,返回。
2)若有效位為0,產(chǎn)生缺頁異常,調(diào)用內(nèi)核缺頁異常處理程序。
它會選擇一個物理頁(如PP4),作為犧牲頁,將該頁的內(nèi)容刷新到磁盤文件。然后,把VP3映射的磁盤文件,緩存到該物理頁。
頁表中的第3條,有效位變1,同時,物理頁號表號變?yōu)镻P4。
3)缺頁異常處理完畢后,返回中斷前的指令,重新執(zhí)行,此時緩存命中,執(zhí)行1)
4)將找到的內(nèi)容映射到高速緩存,CPU從高速緩存中獲取該值,結(jié)束。4.使用虛擬地址需要注意的問題
1)磁盤和主存?zhèn)魉晚摰幕顒咏凶鲰撁嬲{(diào)度。頁面調(diào)度會引起磁盤流量,如果程序的局部性不好,會頻繁進行頁面調(diào)度,叫做“緩存顛簸”。
操作系統(tǒng)會在內(nèi)存中分配一塊交換區(qū)作為緩沖區(qū),來加速頁面的調(diào)度。
2)一級頁表占用的空間是比較大的,根據(jù)按需調(diào)度的原則,一般使用的是多級頁表,即一級頁表指向二級頁表,這樣大大壓縮了頁表的大小。5.地址翻譯
地址翻譯指的是DRAM緩存命中時,由虛擬地址找到物理地址的過程。
該過程是完全由硬件來完成的。
1)CPU有一個專門的頁表基地址寄存器(PTBR)指向當(dāng)前頁表的基地址,快速定位到該進程的頁表。
2)根據(jù)虛擬頁號,找到虛擬地址在頁表的值。
3)根據(jù)值中的物理頁號,找到物理地址。6.Linux中的虛擬內(nèi)存機制Linux把虛擬內(nèi)存劃分成區(qū)域area的集合,一個area包括連續(xù)的多個頁。
area的數(shù)據(jù)結(jié)構(gòu)如下所示:
1)內(nèi)核為每個進程維護了一個單獨的任務(wù)結(jié)果task_struct
2)task_struct的mm指針,指向了mm_struct,該結(jié)構(gòu)描述虛擬內(nèi)存的運行狀態(tài)。
3)mm_struct的pgd指針指向進程的一級頁表的基地址。
mmap指針,指向vm_area_struct鏈表。
4)vm_area_struct描述area的結(jié)構(gòu),vm_start表示area的開始位置,vm_end表示area的結(jié)束位置,vm_prot表示area內(nèi)的頁的讀寫權(quán)限,vm_flags表示area內(nèi)的頁面是進程私有還是共享,vm_next指向下一個area節(jié)點。在Linux中,當(dāng)發(fā)生缺頁異常時,步驟如下:
1)缺頁異常程序,檢查虛擬地址在哪個area內(nèi)。
2)訪問的虛擬頁若沒有讀寫權(quán)限,則觸發(fā)一個保護異常,終止進程。
3)選擇犧牲頁,刷新到磁盤,從磁盤加載缺失的內(nèi)容到物理頁,更新頁表。7.Linux虛擬內(nèi)存需要注意的問題
內(nèi)存映射機制:初始化虛擬內(nèi)存區(qū)域時,會把虛擬內(nèi)存和磁盤文件對象對應(yīng)起來。由于內(nèi)存映射機制,一個磁盤文件對象可被多個進程共享訪問,也可被多個進程私有訪問。
當(dāng)共享訪問時,一個進程的對該對象的修改會顯示到其他進程。
當(dāng)私有訪問時,修改時會產(chǎn)生保護故障,內(nèi)核會拷貝這個私有對象,修改的是這個新對象,其他進程指向的是原來的對象。fork函數(shù)是說明內(nèi)存映射機制很好的例子:
fork函數(shù)會創(chuàng)建帶有獨立虛擬地址空間的新進程,內(nèi)核會把當(dāng)前進程的虛擬內(nèi)存中數(shù)據(jù)結(jié)構(gòu)復(fù)制一份給新進程。虛擬內(nèi)存area包括共享區(qū)域和私有區(qū)域,新建的進程對私有區(qū)域做修改時,會觸發(fā)寫時拷貝,為新進程維護私有的虛擬地址空間。8.虛擬地址作用總結(jié)
1)虛擬內(nèi)存管理可以控制物理內(nèi)存的訪問權(quán)限?
訪問的虛擬頁若沒有讀寫權(quán)限,則觸發(fā)一個保護異常,終止進程。
2)虛擬內(nèi)存讓每個進程有獨立的地址空間
對于私有區(qū)域來說,當(dāng)不同進程對該區(qū)域做修改時,會觸發(fā)寫時拷貝,為新進程維護私有的虛擬地址空間。
3)VA到PA的映射會給分配和釋放內(nèi)存帶來方便。
物理內(nèi)存不連續(xù)的地址,可映射到連續(xù)的虛擬內(nèi)存地址。
4)內(nèi)存效率高
使用了頁面調(diào)度,不會造成大量的數(shù)據(jù)裝入裝出。
                        
                        
                        在早期的計算機中,是沒有虛擬內(nèi)存的概念的。我們要運行一個程序,會把程序全部裝入內(nèi)存,然后運行。
當(dāng)運行多個程序時,經(jīng)常會出現(xiàn)以下問題:
1)進程地址空間不隔離,沒有權(quán)限保護。
由于程序都是直接訪問物理內(nèi)存,所以一個進程可以修改其他進程的內(nèi)存數(shù)據(jù),
甚至修改內(nèi)核地址空間中的數(shù)據(jù)。
2)內(nèi)存使用效率低
當(dāng)內(nèi)存空間不足時,要將其他程序暫時拷貝到硬盤,然后將新的程序裝入內(nèi)存運行。
由于大量的數(shù)據(jù)裝入裝出,內(nèi)存使用效率會十分低下。
3)程序運行的地址不確定
因為內(nèi)存地址是隨機分配的,所以程序運行的地址也是不確定的。2.虛擬地址和物理地址
對于32位系統(tǒng),尋址指針為4字節(jié),對應(yīng)的虛擬地址空間為0-2^32,即0-4G。
對于64位系統(tǒng),尋址指針為8字節(jié),對應(yīng)的虛擬地址空間為0-2^64,即0-16G。
要注意的是,這個地址空間是虛擬的,并非實際存在的。
Linux內(nèi)核把虛擬地址空間分為兩部分:用戶進程空間,內(nèi)核進程空間。
如下入所示:在緩存原理中,換入/換出的數(shù)據(jù)以塊為最小單位。在內(nèi)存管理時,頁是地址空間的最小單位。
虛擬地址空間劃分為多個固定大小的虛擬頁(VP),物理地址空間(DRAM內(nèi)存)劃分為多個固定大小的物理頁(PP),
虛擬頁和物理頁的大小是一樣的,通常為4KB。虛擬頁和物理頁存在著以下關(guān)系:
虛擬頁和磁盤文件映射,然后緩存到物理頁。
根據(jù)是否映射,是否緩存,可以將虛擬頁的狀態(tài)分為以下三種:
1)未映射的頁
即虛擬頁沒有映射到磁盤文件
2)未緩存的頁
虛擬頁映射到了磁盤文件,但是沒有緩存到物理頁,也就是內(nèi)存上。
3)緩存的頁
虛擬頁映射到了磁盤文件,并且緩存到物理頁
如下圖所示:3.虛擬地址的工作原理
對于進程來說,使用的都是虛擬地址。每個進程維護一個單獨的頁表。何為頁表?
頁表是一種數(shù)組結(jié)構(gòu),存放著各虛擬頁的狀態(tài),是否映射,是否緩存。1)數(shù)組的索引號,表示虛擬頁號
2)數(shù)組的值
若為null,表示未映射的頁
若非null,第一位表示有效位,為1,表明緩存的頁;為0,表明未緩存的頁。
其余位表示緩存到的物理頁號。頁表結(jié)構(gòu)圖如下:進程執(zhí)行時,當(dāng)需要訪問虛擬地址中存放的值時,步驟如下:
1)CPU會先找到虛擬地址所在的虛擬頁(VP3),根據(jù)頁表,找出頁表中第3條的值。
判斷有效位,為1,DRMA緩存命中,獲根據(jù)物理頁號,找到物理頁中的內(nèi)容,返回。
2)若有效位為0,產(chǎn)生缺頁異常,調(diào)用內(nèi)核缺頁異常處理程序。
它會選擇一個物理頁(如PP4),作為犧牲頁,將該頁的內(nèi)容刷新到磁盤文件。然后,把VP3映射的磁盤文件,緩存到該物理頁。
頁表中的第3條,有效位變1,同時,物理頁號表號變?yōu)镻P4。
3)缺頁異常處理完畢后,返回中斷前的指令,重新執(zhí)行,此時緩存命中,執(zhí)行1)
4)將找到的內(nèi)容映射到高速緩存,CPU從高速緩存中獲取該值,結(jié)束。4.使用虛擬地址需要注意的問題
1)磁盤和主存?zhèn)魉晚摰幕顒咏凶鲰撁嬲{(diào)度。頁面調(diào)度會引起磁盤流量,如果程序的局部性不好,會頻繁進行頁面調(diào)度,叫做“緩存顛簸”。
操作系統(tǒng)會在內(nèi)存中分配一塊交換區(qū)作為緩沖區(qū),來加速頁面的調(diào)度。
2)一級頁表占用的空間是比較大的,根據(jù)按需調(diào)度的原則,一般使用的是多級頁表,即一級頁表指向二級頁表,這樣大大壓縮了頁表的大小。5.地址翻譯
地址翻譯指的是DRAM緩存命中時,由虛擬地址找到物理地址的過程。
該過程是完全由硬件來完成的。
1)CPU有一個專門的頁表基地址寄存器(PTBR)指向當(dāng)前頁表的基地址,快速定位到該進程的頁表。
2)根據(jù)虛擬頁號,找到虛擬地址在頁表的值。
3)根據(jù)值中的物理頁號,找到物理地址。6.Linux中的虛擬內(nèi)存機制Linux把虛擬內(nèi)存劃分成區(qū)域area的集合,一個area包括連續(xù)的多個頁。
area的數(shù)據(jù)結(jié)構(gòu)如下所示:
1)內(nèi)核為每個進程維護了一個單獨的任務(wù)結(jié)果task_struct
2)task_struct的mm指針,指向了mm_struct,該結(jié)構(gòu)描述虛擬內(nèi)存的運行狀態(tài)。
3)mm_struct的pgd指針指向進程的一級頁表的基地址。
mmap指針,指向vm_area_struct鏈表。
4)vm_area_struct描述area的結(jié)構(gòu),vm_start表示area的開始位置,vm_end表示area的結(jié)束位置,vm_prot表示area內(nèi)的頁的讀寫權(quán)限,vm_flags表示area內(nèi)的頁面是進程私有還是共享,vm_next指向下一個area節(jié)點。在Linux中,當(dāng)發(fā)生缺頁異常時,步驟如下:
1)缺頁異常程序,檢查虛擬地址在哪個area內(nèi)。
2)訪問的虛擬頁若沒有讀寫權(quán)限,則觸發(fā)一個保護異常,終止進程。
3)選擇犧牲頁,刷新到磁盤,從磁盤加載缺失的內(nèi)容到物理頁,更新頁表。7.Linux虛擬內(nèi)存需要注意的問題
內(nèi)存映射機制:初始化虛擬內(nèi)存區(qū)域時,會把虛擬內(nèi)存和磁盤文件對象對應(yīng)起來。由于內(nèi)存映射機制,一個磁盤文件對象可被多個進程共享訪問,也可被多個進程私有訪問。
當(dāng)共享訪問時,一個進程的對該對象的修改會顯示到其他進程。
當(dāng)私有訪問時,修改時會產(chǎn)生保護故障,內(nèi)核會拷貝這個私有對象,修改的是這個新對象,其他進程指向的是原來的對象。fork函數(shù)是說明內(nèi)存映射機制很好的例子:
fork函數(shù)會創(chuàng)建帶有獨立虛擬地址空間的新進程,內(nèi)核會把當(dāng)前進程的虛擬內(nèi)存中數(shù)據(jù)結(jié)構(gòu)復(fù)制一份給新進程。虛擬內(nèi)存area包括共享區(qū)域和私有區(qū)域,新建的進程對私有區(qū)域做修改時,會觸發(fā)寫時拷貝,為新進程維護私有的虛擬地址空間。8.虛擬地址作用總結(jié)
1)虛擬內(nèi)存管理可以控制物理內(nèi)存的訪問權(quán)限?
訪問的虛擬頁若沒有讀寫權(quán)限,則觸發(fā)一個保護異常,終止進程。
2)虛擬內(nèi)存讓每個進程有獨立的地址空間
對于私有區(qū)域來說,當(dāng)不同進程對該區(qū)域做修改時,會觸發(fā)寫時拷貝,為新進程維護私有的虛擬地址空間。
3)VA到PA的映射會給分配和釋放內(nèi)存帶來方便。
物理內(nèi)存不連續(xù)的地址,可映射到連續(xù)的虛擬內(nèi)存地址。
4)內(nèi)存效率高
使用了頁面調(diào)度,不會造成大量的數(shù)據(jù)裝入裝出。
參考資料: 《
》
總結(jié)
 
                            
                        - 上一篇: MySQL索引和SQL调优手册
- 下一篇: 前端:闭包的概念
