全面解析虛擬內(nèi)存
一個(gè)系統(tǒng)中的進(jìn)程是與其他進(jìn)程共享CPU和主存資源的。隨著對CPU需求的增長,進(jìn)程以某種合理的平滑的方式慢了下來。這里給大家分享一些關(guān)于全面解析虛擬內(nèi)存,希望對大家能有所幫助。
虛擬內(nèi)存空間
1.保留區(qū)(受保護(hù)的地址)
保留區(qū)即為受保護(hù)的地址,大小為128M,位于虛擬地址空間的最低部分,未賦予物理地址。任何對它的引用都是非法的,用于捕捉使用空指針和小整型值指針引用內(nèi)存的異常情況。
它并不是一個(gè)單一的內(nèi)存區(qū)域,而是對地址空間中受到操作系統(tǒng)保護(hù)而禁止用戶進(jìn)程訪問的地址區(qū)域的總稱。大多數(shù)操作系統(tǒng)中,極小的地址通常都是不允許訪問的,如NULL。C語言將無效指針賦值為0也是出于這種考慮,因?yàn)?地址上正常情況下不會存放有效的可訪問數(shù)據(jù)。。
2.代碼段
代碼段也稱正文段或文本段,通常用于存放程序執(zhí)行代碼(即CPU執(zhí)行的機(jī)器指令)。一般C語言執(zhí)行語句都編譯成機(jī)器代碼保存在代碼段。通常代碼段是可共享的,因此頻繁執(zhí)行的程序只需要在內(nèi)存中擁有一份拷貝即可。代碼段通常屬于只讀,以防止其他程序意外地修改其指令(對該段的寫操作將導(dǎo)致段錯(cuò)誤)。某些架構(gòu)也允許代碼段為可寫,即允許修改程序。
3.數(shù)據(jù)段(.data段)
數(shù)據(jù)段通常用于存放程序中已初始化的全局變量和靜態(tài)局部變量。數(shù)據(jù)段屬于靜態(tài)內(nèi)存分配(靜態(tài)存儲區(qū)),可讀可寫。由于全局變量未初始化時(shí),其默認(rèn)值為0,因此值為0的全局變量位于.bbs段(不位于數(shù)據(jù)段)。對于未初始化的局部變量,其值是不可預(yù)測的。注意:在代碼段和數(shù)據(jù)段之間還包括其它段:只讀數(shù)據(jù)段和符號段等。
4. .bbs段
該段用于存放未初始化的全局變量和靜態(tài)局部變量,包括值為0的全局變量。 數(shù)據(jù)段和.bbs段又稱為全局?jǐn)?shù)據(jù)區(qū),前者初始化,后者未初始化。
ELF段包括:代碼段、其它段(在.data段和.text段之間,包括只讀數(shù)據(jù)段和符號段等)、.data段(數(shù)據(jù)段)和.bbs段,都屬于可執(zhí)行程序部分。
5.堆空間
new( )和malloc( )函數(shù)分配的空間就屬于堆空間。
分配的堆內(nèi)存是經(jīng)過字節(jié)對齊的空間,以適合原子操作。堆管理器通過鏈表管理每個(gè)申請的內(nèi)存,由于堆申請和釋放是無序的,最終會產(chǎn)生內(nèi)存碎片。堆內(nèi)存一般由應(yīng)用程序分配釋放,回收的內(nèi)存可供重新使用。若程序員不釋放,程序結(jié)束時(shí)操作系統(tǒng)可能會自動回收。
堆的末端由break指針標(biāo)識,當(dāng)堆管理器需要更多內(nèi)存時(shí),可通過系統(tǒng)調(diào)用brk()和sbrk()來移動break指針以擴(kuò)張堆,一般由系統(tǒng)自動調(diào)用。
使用堆時(shí)經(jīng)常出現(xiàn)兩種問題:1) 釋放或改寫仍在使用的內(nèi)存(“內(nèi)存破壞”);2)未釋放不再使用的內(nèi)存(“內(nèi)存泄漏”)。當(dāng)釋放次數(shù)少于申請次數(shù)時(shí),可能已造成內(nèi)存泄漏。泄漏的內(nèi)存往往比忘記釋放的數(shù)據(jù)結(jié)構(gòu)更大,因?yàn)樗峙涞膬?nèi)存通常會圓整為下個(gè)大于申請數(shù)量的2的冪次(如申請212B,會圓整為256B)。
6.內(nèi)存映射段(共享庫)
內(nèi)核將硬盤文件的內(nèi)容直接映射到內(nèi)存, 任何應(yīng)用程序都可通過Linux的mmap()系統(tǒng)調(diào)用請求這種映射。內(nèi)存映射是一種方便高效的文件I/O方式, 因而被用于裝載動態(tài)共享庫。如C標(biāo)準(zhǔn)庫函數(shù)(fread、fwrite、fopen等)和Linux系統(tǒng)I/O函數(shù),它們都是動態(tài)庫函數(shù),其中C標(biāo)準(zhǔn)庫函數(shù)都被封裝在了/lib/libc.so庫文件中,都是二進(jìn)制文件。這些動態(tài)庫函數(shù)都是與位置無關(guān)的代碼,即每次被加載進(jìn)入內(nèi)存映射區(qū)時(shí)的位置都是不一樣的,因此使用的是其本身的邏輯地址,經(jīng)過變換成線性地址(虛擬地址),然后再映射到內(nèi)存。而靜態(tài)庫不一樣,由于靜態(tài)庫被鏈接到可執(zhí)行文件中,因此其位于代碼段,每次在地址空間中的位置都是固定的。
7.棧空間
用于存放局部變量(非靜態(tài)局部變量,C語言稱為自動變量),分配存儲空間時(shí)從上往下。
虛擬內(nèi)存實(shí)現(xiàn)方式
頁面和頁框
我們來打個(gè)比方,假設(shè)你現(xiàn)在有一臺32KB內(nèi)存的電腦,虛擬內(nèi)存是64KB。首先我們先將64KB的虛擬內(nèi)存切個(gè)片,一個(gè)片大小為4KB,所以總共切了16片。同時(shí),把32KB的物理內(nèi)存也按4KB的切片,總共切了8片。那么我們就稱虛擬內(nèi)存的一個(gè)片叫做頁面,物理內(nèi)存的一個(gè)片叫做頁框。
頁表
同學(xué)們可能已經(jīng)猜到了,沒錯(cuò),虛擬內(nèi)存和物理內(nèi)存之間是有一個(gè)映射關(guān)系的。這個(gè)映射該怎么實(shí)現(xiàn)呢,這就需要我們頁表的登場啦!頁表中維護(hù)著頁表和頁框的對應(yīng)關(guān)系。舉個(gè)栗子,一個(gè)地址為0x0010000000000100的16位地址。16位地址可拆分為兩部分,前4位和后12位。前4位對應(yīng)著16個(gè)虛擬頁表的號牌用于在頁表中尋找對應(yīng)的頁框號,后12位用于頁內(nèi)偏址。0010即是2號,我們在頁表中查找2號選手對應(yīng)的頁框,假設(shè)是100。那么我們虛擬地址所對應(yīng)的物理地址即可得出,為100+之前的后12位頁內(nèi)偏移地址,即0x100000000000100。
不過畢竟頁面比頁框?yàn)?6:8,那么肯定會有一部分的頁面沒有所對應(yīng)的頁框,如果我們的虛擬地址就在這些頁面中我們該怎么辦呢?
缺頁中斷
沒錯(cuò),如果我們的虛擬地址所在頁面沒有對應(yīng)的頁框,那么系統(tǒng)會產(chǎn)生一個(gè)缺頁中斷。缺頁中斷使CPU停下手頭的工作,轉(zhuǎn)而去尋找一個(gè)使用最少的一個(gè)頁框,將其寫入到磁盤中(如果頁框范圍內(nèi)地址的內(nèi)容有改變的話,沒有改變則不需要寫入磁盤)。然后修改將頁面指向該頁框,修改映射關(guān)系,至此缺頁中斷處理結(jié)束。CPU繼續(xù)執(zhí)行之前的工作。
TLB
到這里,虛擬內(nèi)存已經(jīng)可以完整的映射到物理內(nèi)存了,但還有一些問題。那就是速度問題。我們設(shè)想一下,如果把頁表存儲在進(jìn)程中,那么每次CPU都得進(jìn)入內(nèi)存中查詢,非常的影響速度。那我們?nèi)绻O(shè)置一個(gè)寄存器在CPU中,那速度不就很快了么?確實(shí)這樣CPU的訪問速度會非常的快,但是每次的進(jìn)程切換,都會有新的頁表載入該寄存器中,同樣非常影響速度。那我們就沒有辦法了么?根據(jù)計(jì)算機(jī)科學(xué)家的統(tǒng)計(jì),其實(shí)有一些頁面映射是非常頻繁的,而剩余的映射則非常少,那么我們就可以將這些映射最頻繁的頁面放入CPU寄存器中,而這個(gè)CPU寄存器我們就叫他TLB。
虛擬內(nèi)存原理
內(nèi)存在計(jì)算機(jī)中的作用很大,電腦中所有運(yùn)行的程序都需要經(jīng)過內(nèi)存來執(zhí)行,如果執(zhí)行的程序很大或很多,就會導(dǎo)致內(nèi)存消耗殆盡。為了解決這個(gè)問題,Windows中運(yùn)用了虛擬內(nèi)存技術(shù),即拿出一部分硬盤空間來充當(dāng)內(nèi)存使用,當(dāng)內(nèi)存占用完時(shí),電腦就會自動調(diào)用硬盤來充當(dāng)內(nèi)存,以緩解內(nèi)存的緊張。舉一個(gè)例子來說,如果電腦只有128MB物理內(nèi)存的話,當(dāng)讀取一個(gè)容量為200MB的文件時(shí),就必須要用到比較大的虛擬內(nèi)存,文件被內(nèi)存讀取之后就會先儲存到虛擬內(nèi)存,等待內(nèi)存把文件全部儲存到虛擬內(nèi)存之后,跟著就會把虛擬內(nèi)里儲存的文件釋放到原來的安裝目錄里了。
當(dāng)系統(tǒng)運(yùn)行時(shí),先要將所需的指令和數(shù)據(jù)從外部存儲器(如硬盤、軟盤、光盤等)調(diào)入內(nèi)存中,CPU再從內(nèi)存中讀取指令或數(shù)據(jù)進(jìn)行運(yùn)算,并將運(yùn)算結(jié)果存入內(nèi)存中,內(nèi)存所起的作用就像一個(gè)“二傳手”的作用。當(dāng)運(yùn)行一個(gè)程序需要大量數(shù)據(jù)、占用大量內(nèi)存時(shí),內(nèi)存這個(gè)倉庫就會被“塞滿”,而在這個(gè)“倉庫”中總有一部分暫時(shí)不用的數(shù)據(jù)占據(jù)著有限的空間,所以要將這部分“惰性”的數(shù)據(jù)“請”出去,以騰出地方給“活性”數(shù)據(jù)使用。這時(shí)就需要新建另一個(gè)后備“倉庫”去存放“惰性”數(shù)據(jù)。由于硬盤的空間很大,所以微軟Windows操作系統(tǒng)就將后備“倉庫”的地址選在硬盤上,這個(gè)后備“倉庫”就是虛擬內(nèi)存。在默認(rèn)情況下,虛擬內(nèi)存是以名為Pagefile.sys的交換文件保存在硬盤的系統(tǒng)分區(qū)中。
虛擬內(nèi)存相關(guān)文章:
★ 如何合理設(shè)置電腦虛擬內(nèi)存,提高電腦運(yùn)行速度
★ 提高內(nèi)存使用效能的幾種方法
★ 介紹幾個(gè)妙招加快內(nèi)存運(yùn)行速度
★ 全面釋放C盤被強(qiáng)行占用的空間
★ 讓你的電腦一點(diǎn)都不卡
★ 電腦系統(tǒng)資源不足及解決辦法
★ 電腦技巧
★ 電腦技巧
★ 電腦死機(jī)的常見原因
★ 關(guān)于電腦死機(jī)的原因及解決方法分享
本站部分文章來自網(wǎng)絡(luò)或用戶投稿。涉及到的言論觀點(diǎn)不代表本站立場。閱讀前請查看【免責(zé)聲明】發(fā)布者:天下,如若本篇文章侵犯了原著者的合法權(quán)益,可聯(lián)系我們進(jìn)行處理。本文鏈接:http://www.256680.cn/dnxx/nczs/45571.html