• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            大龍的博客

            常用鏈接

            統(tǒng)計

            最新評論

            Windows內(nèi)存原理與內(nèi)存管理(轉(zhuǎn))

            轉(zhuǎn):http://hi.baidu.com/%D0%A1%B0%FC%D7%D349/blog/item/de1a8e4fa5eeafc3d0c86a68.html
            1.進程地址空間
                Windows為每個進程分配了4GB的虛擬地址空間,讓每個進程都認為自己擁有4GB的內(nèi)存空間,4GB怎么來的? 32位 CPU可以取地址的空間為2的32次方,就是4GB.
                當我們在Windows中雙擊一個應用程序圖標后,系統(tǒng)為該應用程序創(chuàng)建一個進程,Windows使得每個進程都擁有2GB的地址空間,這2GB地址空間用于程序存放代碼,數(shù)據(jù),堆棧,自由存儲區(qū)(堆),另外2GB用于共享系統(tǒng)使用.

            2.虛擬地址到實際地址的映射

             

                前面的這些地址并不是物理內(nèi)存中的地址,而是該進程空間中的虛擬地址,虛擬空間只是Windows為該進程分配的一個虛擬的地址空間,只有當其和物理內(nèi)存相關(guān)聯(lián)后才有意義.
            2.1內(nèi)存分頁
                每個物理地址對應一個虛擬地址?1GB那頁表該有多長,所以將內(nèi)存分頁管理,4K為一頁,即4K就是一個最小單位。
            2.2建立映射--分頁
                進程被創(chuàng)建時會建立一個虛擬內(nèi)從到物理內(nèi)存的映射表--頁表,根據(jù)頁表可以將虛擬內(nèi)存和物理內(nèi)存關(guān)聯(lián)起來.

            2.3虛擬內(nèi)存
                就是把磁盤拿來當內(nèi)存用,這是以前買電腦時的想法。所以就一直都想不明白一個問題:要真是這樣,那內(nèi)存分個什么1GB,2GB,4GB,大家都買個1M的內(nèi)存條,然后把自己磁盤拿來當內(nèi)存用多好,比2GB,4GB不知道要大多少。
                其實這個說法有一點擦邊球的味道,虛擬內(nèi)存是一些系統(tǒng)頁文件,存放在磁盤上,每個系統(tǒng)頁文件大小也為4K,物理內(nèi)存也被分頁,每個頁大小也為4K,這樣虛擬頁文件和物理內(nèi)存頁就可以對應,實際上虛擬內(nèi)存就是用于物理內(nèi)存的臨時存放的磁盤空間

                頁文件就是內(nèi)存頁,物理內(nèi)存中每頁叫物理頁,磁盤上的頁文件叫虛擬頁,物理頁+虛擬頁就是系統(tǒng)所以使用的頁文件的總和。還有映像頁文件和映射頁文件,映像頁文件就是拿程序本身當頁文件使用(而不是用系統(tǒng)的頁文件),映射頁文件就是使用磁盤上的文件(非系統(tǒng)頁文件)來當頁文件使用(這主要用于讀取文件)

                虛擬地址頁的狀態(tài)
                (1)空閑:該區(qū)域沒有被所使用,也沒有被預定,沒有和物理內(nèi)存管理
                (2)私有:該區(qū)域雖然沒有被使用,但是已經(jīng)被申請(預定了),別人無法使用它。同樣也沒和物理內(nèi)存關(guān)聯(lián)
                (3)提交:該區(qū)域已經(jīng)和物理內(nèi)存管理,可以使用了
            2.4虛擬內(nèi)存和物理內(nèi)存的管理
                Windows是多任務的系統(tǒng),在每個進程創(chuàng)建時,系統(tǒng)為每個進程也創(chuàng)建了一個頁表,用于虛擬地址到物理地址的轉(zhuǎn)換。比如現(xiàn)在程序在執(zhí)行進程A,用戶切換到了另外一個進程B,則系統(tǒng)會將進程A在內(nèi)存中的數(shù)據(jù)存放到頁文件中,并更新進程A的頁表(使虛擬地址和頁文件形成映射)。然后讀取進程B的頁表,根據(jù)頁表判斷進程B的數(shù)據(jù)是在內(nèi)存中還是在頁文件中(通過頁文件的類型來判斷),如果在內(nèi)存中就直接讀取,如果在頁面文件中,就將頁面文件內(nèi)容讀入物理內(nèi)存,然后更新頁表(使虛擬地址和物理內(nèi)存形成映射)。這樣一看,虛擬內(nèi)存實際上就是冒牌的物理內(nèi)存了吧。
            3.程序執(zhí)行
                一個PE文件有數(shù)據(jù)區(qū),代碼區(qū),堆棧區(qū)(由系統(tǒng)分配,用于管理局部變量),使用OD載入一個程序就可以知道這些都是以二進制的形式保存在文件中。
                程序剛運行的時候,系統(tǒng)不直接將整個程序載入到物理內(nèi)存中,也不將其載入到頁文件中,而是以程序文件本身作為頁文件形成映射(虛擬地址到頁文件的映射),建立頁表,然后隨著程序的執(zhí)行通過頁表來將其虛擬地址轉(zhuǎn)換成物理地址(將頁文件讀入內(nèi)存),然后在讀取內(nèi)存中的指令或數(shù)據(jù)。當進程被切換時,將內(nèi)存內(nèi)容保存到頁文件,更新頁表,如此往復,實現(xiàn)多任務操作。

                可以知道,程序的代碼段,數(shù)據(jù)段,堆棧區(qū)(系統(tǒng)分配)這些虛擬地址區(qū)域已經(jīng)是映射狀態(tài),即有相應的物理內(nèi)存與之對應。系統(tǒng)為每個進程提供了2G的自己的虛擬地址空間,剩下的虛擬地址空間干什么用?
                剩下的虛擬地址空間就是給程序運行時動態(tài)分配內(nèi)存使用。C++中 new的功能就是動態(tài)分配地址空間:
                申請內(nèi)存的最小單位是區(qū)域,每個區(qū)域為CPU粒度大小,即64K,每次申請的內(nèi)存都必須是64K的整數(shù)倍,C++ new功能申請一個區(qū)域,保留該區(qū)域,然后提交需要的頁,其他的保留。  
                char *address=new char[1024];   //分配1K的內(nèi)存
                這條語句首先申請一個區(qū)域的地址空間,表示這個區(qū)域已經(jīng)被預定了,這就是上述區(qū)域狀態(tài)中的私有狀態(tài),雖然預定了,但是還沒有和物理內(nèi)存關(guān)聯(lián)起來,所以程序也無法使用該內(nèi)存,然后程序?qū)⑦@1K的內(nèi)存提交,就是映射到了內(nèi)存當中,區(qū)域的狀態(tài)就變成了映射狀態(tài),這樣程序就可以使用這1K的內(nèi)存了,而剩下的頁仍然為保留狀態(tài)。那當進程被切換時,這1K的進程存放在哪呢?程序本身的頁文件已經(jīng)被代碼,全局數(shù)據(jù),堆棧這些所使用了,所以系統(tǒng)會為自由存儲區(qū)分配的內(nèi)存分配新的頁文件來做虛擬內(nèi)存。

                局部變量的定義是由系統(tǒng)分配的,它將局部變量分配到堆棧區(qū),因為堆棧區(qū)已經(jīng)映射了,所以不用在映射,故不用使用新的頁文件了。堆棧區(qū)的大小為1M左右,如果分配的局部變量超過1M會產(chǎn)生堆棧溢出。

                可以看到,系統(tǒng)的單個頁文件大小為4K,程序自己的虛擬空間地址00010000到7FFEFFFF差不多是2G動態(tài)分配一個500M的內(nèi)存后,物理內(nèi)存,頁文件,可用的虛擬地址空間都減少了500M
                查詢內(nèi)存狀態(tài)使用VirtualQuery(Address[n],&membaseinf,sizeof(MEMORY_BASIC_INFORMATION))
            定義3個變量
            char Stack[20*1024];//存在堆棧中,堆棧在程序啟動時已經(jīng)被映像到內(nèi)存中了
            char* Dynamic=new char[64*1024];  //動態(tài)分配一個70K的內(nèi)存
            char* Dynamic2=new char[1024];  //動態(tài)分配一個1K的內(nèi)存

            參數(shù)說明:

            地址所在頁面基地址:查詢的地址所在的頁面的起始地址
            頁面所在區(qū)域的基地址:頁面所在區(qū)域的起始地址
            區(qū)域保護屬性:分配區(qū)域時要設(shè)置區(qū)域的讀寫屬性
            從頁面基地址開始擁有相同屬性(空閑,保留,提交)的所有頁的字節(jié)數(shù):可以看到這些都是4096的整數(shù)倍,因為一個頁4096,該大小一般都和申請的內(nèi)存空間大小相當,因為這些內(nèi)存都被提交了。

            申請一個內(nèi)存空間的過程
            首先申請一個虛擬地址空間區(qū)域,然后提交申請的內(nèi)存空間大小的頁(將其和頁文件關(guān)聯(lián))。其他的地址空間保留。

            第一條指令分配了一個字符數(shù)組的局部變量,該變量分配在堆棧中,由系統(tǒng)分配,所以其區(qū)域為程序的靜態(tài)存儲區(qū),即在程序啟動時候這個區(qū)域的所有虛擬地址就和程序文件本身映像了,所以局部變量的區(qū)域基地址都是一樣的,那為什么它的頁面文件類型是頁文件呢?不應該是exe映像么?因為現(xiàn)在文件在內(nèi)存中,所有是物理頁,就是頁文件。

            第二條指令動態(tài)分配了一塊大小為1K的內(nèi)存區(qū)域,這塊內(nèi)存分配在自由存儲區(qū),它所在的區(qū)域是在堆中申請的一個區(qū)域,第三條指令在堆中分配了一個70K左右的內(nèi)存,因為他們是在堆中分配的,所以這2個變量的區(qū)域基地址是不一樣的。

            分配的區(qū)域有多大?
            第三條指令分配了一個70K左右的內(nèi)存,它會向系統(tǒng)申請多大的區(qū)域呢?由區(qū)域大小為64K的整數(shù)倍知該區(qū)域至少為128K,查詢這70K之后的虛擬地址的狀態(tài)

            可以看到該地址所在的區(qū)域和Dynamic是一樣的,它的基地址為580000(轉(zhuǎn)載者加:不應該是594000吧),在那70K之后,這之后的區(qū)域的狀態(tài)為保留,說明系統(tǒng)保留了剩下的區(qū)域,這剩下的區(qū)域有966656,就是966K左右的大小,那整個區(qū)域的大小就是(0x14000)81920+966656。

            posted on 2010-04-15 00:58 大龍 閱讀(3452) 評論(0)  編輯 收藏 引用

            久久99精品九九九久久婷婷| 一本一道久久综合狠狠老| 久久99精品久久久久久| 99久久精品无码一区二区毛片| 精品久久久久久99人妻| 人妻丰满?V无码久久不卡| 久久夜色精品国产噜噜麻豆| 国产高潮国产高潮久久久91 | 狠狠色丁香婷婷久久综合五月| 中文国产成人精品久久不卡| 欧美精品一本久久男人的天堂| 香蕉久久影院| 久久这里只有精品久久| 亚洲AV无码一区东京热久久| 久久精品国产一区二区三区| 久久精品国产亚洲AV高清热| 亚洲国产精品综合久久网络 | 99久久超碰中文字幕伊人| 久久夜色撩人精品国产| 精品久久久久久久| 久久精品国产亚洲av高清漫画| 国产精品久久久久久久app | 久久久久亚洲精品天堂久久久久久| yy6080久久| 午夜精品久久久久成人| 久久激情五月丁香伊人| 好久久免费视频高清| 国内精品久久久久久99蜜桃| 久久WWW免费人成一看片| 久久精品亚洲乱码伦伦中文 | 亚洲欧美成人久久综合中文网| 中文字幕一区二区三区久久网站| 久久国产精品成人影院| 久久久亚洲欧洲日产国码二区| 99久久综合国产精品免费| 热久久最新网站获取| Xx性欧美肥妇精品久久久久久| 蜜臀久久99精品久久久久久小说| 久久婷婷国产剧情内射白浆| 中文精品久久久久人妻| 日韩欧美亚洲综合久久影院Ds|