乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

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

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

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

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

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

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

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

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

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

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

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

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

      *   內(nèi)存分配 

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

      *   懶惰策略 

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

      *   進程工作集 

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

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

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

      *   內(nèi)存整理 

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

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

      退一步說,即使這個動作能夠起到將其他進程的內(nèi)存換出的作用,但這實際上只是一個 
      損害系統(tǒng)性能的動作,而不是一種優(yōu)化,因為很快其他進程就會產(chǎn)生大量頁面錯誤,結(jié) 
      果就是硬盤猛轉(zhuǎn)。 

      *   堆碎片化問題 

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

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

      --   
      Felix

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

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多