小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

內(nèi)存整理的迷思

 jinye6 2011-06-23
內(nèi)存整理的迷思 

看了接二連三出現(xiàn)于本組的有關(guān)內(nèi)存整理的帖子,終于覺(jué)得有必要寫(xiě)一點(diǎn)文字了,這些 
帖子如果是在別的組尚且情有可原,可是出現(xiàn)在編程組中卻實(shí)屬不該,看來(lái)不少人仍然 
對(duì)Windows的內(nèi)存管理機(jī)制存在種種誤解,希望這篇短文能夠澄清這些誤解中的一部分 
(如果不是全部的話)。 

本文可自由轉(zhuǎn)載,轉(zhuǎn)載不須注明出處,也不須提及作者名字,如要修改內(nèi)容,唯需注意 
所述知識(shí)之準(zhǔn)確性,以免誤人子弟。如發(fā)現(xiàn)本文有錯(cuò)誤之處,也請(qǐng)不吝指出。 

*   進(jìn)程內(nèi)存布局 

Win32中每個(gè)進(jìn)程擁有4GB的虛擬內(nèi)存地址空間。 
典型的Winnt系統(tǒng)中的一個(gè)進(jìn)程的內(nèi)存布局如下。 

  +--------------+   0xffffffff 
  |   系統(tǒng)代碼           | 
  |   設(shè)備驅(qū)動(dòng)           | 
  |   內(nèi)存映射文件   | 
  +--------------+   0x80000000 
  |   用戶dll映像     | 
  +--------------+ 
  |   heap                   | 
  +--------------+ 
  |   stack                 | 
  +--------------+ 
  |   global               | 
  +--------------+ 
  |   用戶exe映像     | 
  +--------------+   0x00010000 
  |   保留                   | 
  +--------------+ 

整個(gè)4GB虛擬地址空間分為兩部分,上面2GB是系統(tǒng)代碼,下面2GB是用戶代碼(用戶區(qū)最 
底部的64KB空間為系統(tǒng)保留), 

*   物理內(nèi)存分頁(yè) 

以上是虛擬內(nèi)存,再看物理內(nèi)存。Windows通過(guò)2級(jí)頁(yè)表來(lái)將虛擬內(nèi)存地址映射到物理內(nèi) 
存。如圖所示: 
                      
    +-----+     +------------------------------------------+ 
    |   CR3   |     |   一級(jí)頁(yè)表索引   |   二級(jí)頁(yè)表索引   |   頁(yè)內(nèi)偏移量   |   32位虛擬地址格式 
    +-----+     +------------------------------------------+ 
          |             |                                         |                                       |                                 
          |             |                                         |                                       |                                     
          |             |         第一級(jí)頁(yè)表             |         第二級(jí)頁(yè)表           |             物理內(nèi)存     
          +------+-> +-----------+     +--+-> +-----------+     +-+---> +-----------+   
                        |     |   頁(yè)表入口     |     |     |     |   頁(yè)表入口     |     |   |         |   4KB內(nèi)存頁(yè)   |   
                        |     +-----------+     |     |     +-----------+     |   +---> |                       |   
                        +-> |   頁(yè)表入口     +--+     +-> |   頁(yè)表入口     +--+             |                       |   
                              +-----------+                 +-----------+                   +-----------+   
                              |   共1024條     |                 |   共1024條     |                   |   4KB內(nèi)存頁(yè)   |   
                              +-----------+                 +-----------+                   |                       |   
                              |   ...               |                 |   ...               |                   |                       |   
                              |                       |                 |                       |                   +-----------+   
                              |                       |                 |                       |                   |   ...               |   
                              |                       |                 |                       |                   |                       |   
                              +-----------+                 +-----------+                   +-----------+   
    +------------+----------+ 
    |   20位索引值   |   12位標(biāo)志   |   頁(yè)表入口格式 
    +------------+----------+ 

物理內(nèi)存按4KB為單位劃分為頁(yè)面,給定一個(gè)32位虛擬地址,Windows首先從CR3寄存器 
取得第一級(jí)頁(yè)表,然后從虛擬地址的一級(jí)頁(yè)表索引字段取得一級(jí)頁(yè)表入口,從一級(jí)頁(yè)表 
入口的20位索引可找到對(duì)應(yīng)的二級(jí)頁(yè)表,然后從虛擬地址的二級(jí)頁(yè)表索引字段取得二級(jí) 
頁(yè)表入口,從二級(jí)頁(yè)表入口的20位索引找到具體的4KB物理內(nèi)存頁(yè),最后根據(jù)虛擬地址 
的頁(yè)內(nèi)偏移字段訪問(wèn)物理內(nèi)存。聽(tīng)上去比較復(fù)雜,不過(guò)對(duì)照?qǐng)D片一看就很清楚了。每個(gè) 
進(jìn)程都有自己的一套頁(yè)表,對(duì)不同的進(jìn)程,Windows只要在CR3寄存器裝入不同的一級(jí)頁(yè) 
表地址就可以了。(這里給出的是一個(gè)概念模型,實(shí)際上Windows對(duì)頁(yè)表訪問(wèn)還有一些優(yōu) 
化技巧) 

為什么要分頁(yè)呢,這是因?yàn)樘摂M內(nèi)存中的數(shù)據(jù)不一定必須在物理內(nèi)存中,如果一個(gè)頁(yè)面 
的數(shù)據(jù)在磁盤(pán)上,Windows就在對(duì)應(yīng)的頁(yè)表入口的標(biāo)志位中做一個(gè)標(biāo)記,這樣訪問(wèn)到這 
個(gè)頁(yè)面時(shí)就引發(fā)一個(gè)頁(yè)面錯(cuò)誤。Windows一旦捕捉到頁(yè)面錯(cuò)誤,就將相應(yīng)的頁(yè)面從磁盤(pán) 
載入物理內(nèi)存并再次嘗試讀取,這個(gè)過(guò)程對(duì)應(yīng)用程序來(lái)說(shuō)是透明的,應(yīng)用程序無(wú)需關(guān)心 
自己要訪問(wèn)的數(shù)據(jù)是在物理內(nèi)存里還是在磁盤(pán)上。 

*   內(nèi)存分配 

Windows應(yīng)用程序使用VirtualAlloc   API函數(shù)分配內(nèi)存塊。也許你用的編程語(yǔ)言使用不 
同的關(guān)鍵字,但最終它們都被轉(zhuǎn)換為對(duì)VirtualAlloc的調(diào)用。VirtualAlloc分為兩個(gè)步 
驟,第一步是保留,第二步是提交。保留的意思是將虛擬地址做個(gè)標(biāo)記表示我預(yù)訂了這 
個(gè)位置,接下來(lái)的分配就不會(huì)分配在已經(jīng)被預(yù)定的位置了。提交的意思是實(shí)際準(zhǔn)備開(kāi)始 
用這個(gè)內(nèi)存塊。 

*   懶惰策略 

即使提交了內(nèi)存塊,Windows也并不立即為這段地址初始化頁(yè)表。因?yàn)榭赡芤欢蝺?nèi)存雖 
然被提交,某些區(qū)域卻從來(lái)不使用,為這些地址構(gòu)造頁(yè)表完全是白費(fèi)力氣。Windows采 
取懶惰策略,一直到某個(gè)頁(yè)面錯(cuò)誤出現(xiàn),才為那個(gè)頁(yè)面創(chuàng)建頁(yè)表。這個(gè)技術(shù)使得即使分 
配很大塊的內(nèi)存也可以在瞬間完成。 

*   進(jìn)程工作集 

你可能在想,如果一個(gè)進(jìn)程提交了1GB的虛擬內(nèi)存,并且將這1GB虛擬內(nèi)存全部訪問(wèn)一遍, 
那么是不是它就能占用整個(gè)計(jì)算機(jī)的所有物理內(nèi)存呢?答案是否。 

Windows啟動(dòng)時(shí),根據(jù)計(jì)算機(jī)上安裝的內(nèi)存數(shù)量計(jì)算兩個(gè)值“進(jìn)程默認(rèn)工作集大小”和 
“進(jìn)程最大工作集大小”。每個(gè)進(jìn)程以默認(rèn)工作集大小啟動(dòng)。隨著進(jìn)程使用內(nèi)存的增加, 
工作集可以漸漸增大,直到最大值。如果系統(tǒng)有足夠的空閑頁(yè)面,進(jìn)程工作集甚至可以 
超過(guò)最大值,反正多出來(lái)的內(nèi)存閑著也是閑著。如果系統(tǒng)沒(méi)有多余的空閑頁(yè)面,而進(jìn)程 
又達(dá)到了最大工作集限制,對(duì)后續(xù)的頁(yè)面錯(cuò)誤,Windows先刪除該進(jìn)程的一個(gè)頁(yè)面,然 
后將要求的頁(yè)面載入。當(dāng)空閑內(nèi)存進(jìn)一步減少時(shí),Windows將開(kāi)始縮小各個(gè)進(jìn)程的工作 
集,將一些頁(yè)面換出內(nèi)存。 

所以,一個(gè)惡意的或錯(cuò)誤的程序?qū)嶋H上并沒(méi)有辦法用拼命分配內(nèi)存的方法對(duì)系統(tǒng)造成過(guò) 
大的影響。 

*   內(nèi)存整理 

有了上面這些知識(shí),你就很容易看出來(lái)所謂的內(nèi)存整理有多么荒謬。物理內(nèi)存按4KB分 
頁(yè),根本無(wú)所謂碎片化,就算物理內(nèi)存堆放得再整齊連續(xù),系統(tǒng)總是按照4KB為單位訪 
問(wèn)它。 

我所見(jiàn)的大多數(shù)內(nèi)存整理程序的做法是分配一塊很大的內(nèi)存,意圖將其他進(jìn)程的數(shù)據(jù)換 
入磁盤(pán),然后釋放這塊內(nèi)存來(lái)得到大塊物理內(nèi)存。然而由于Windows的工作集裁剪策略, 
這個(gè)做法實(shí)際上無(wú)法起作用,如果系統(tǒng)的內(nèi)存壓力相當(dāng)重,那么不管這個(gè)程序試圖分配 
多少內(nèi)存,結(jié)果只是導(dǎo)致自己的內(nèi)存被換出,而不是其他進(jìn)程的。 

退一步說(shuō),即使這個(gè)動(dòng)作能夠起到將其他進(jìn)程的內(nèi)存換出的作用,但這實(shí)際上只是一個(gè) 
損害系統(tǒng)性能的動(dòng)作,而不是一種優(yōu)化,因?yàn)楹芸炱渌M(jìn)程就會(huì)產(chǎn)生大量頁(yè)面錯(cuò)誤,結(jié) 
果就是硬盤(pán)猛轉(zhuǎn)。 

*   堆碎片化問(wèn)題 

整理物理內(nèi)存雖然是無(wú)稽之談,但進(jìn)程的動(dòng)態(tài)存儲(chǔ)區(qū)--heap,確實(shí)是會(huì)有碎片化問(wèn)題的。 
準(zhǔn)確地說(shuō),這不是內(nèi)存碎片,而是地址碎片。如果程序反復(fù)分配釋放小塊內(nèi)存,heap的 
地址可能變得很不連續(xù),雖然耗盡2GB虛擬地址的可能不大,但在碎片化的堆中尋找一 
塊可用內(nèi)存就會(huì)變得比較慢從而影響執(zhí)行效率。 

解決這個(gè)問(wèn)題的方法只能是寫(xiě)程序的時(shí)候注意考慮這個(gè)問(wèn)題,而不可能借助外部程序。 
例如使用一個(gè)內(nèi)存池來(lái)管理自己的內(nèi)存,Jeffrey   Richter的 <Advanced   Windows> 一書(shū) 
中介紹了一種重載class的operator   new的方法。 

--   
Felix

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多