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