91精品国产手机在线-白筒袜嫩萝双腿之间乳白液体-青青操手机在线视频观看-日本中文字幕人妻日韩-日韩精品在线观看视频网站-天堂资源中文最新版在线一区-欧美专区一区二区三区-国产综合亚洲欧美在线-国产精品久久久久久福利69堂

手機虛擬空間軟件 虛擬空間哪個好用

內(nèi)存管理模塊是操作系統(tǒng)的心臟;這對應(yīng)用和系統(tǒng)管理非常重要 。在本文中,我將關(guān)注實際的內(nèi)存問題,但我不會回避技術(shù)內(nèi)幕 。因為很多概念是通用的,所以本文中的大多數(shù)例子都取自32位x86平臺的Linux和Windows系統(tǒng) 。本系列的第一篇文章討論應(yīng)用程序的內(nèi)存布局 。
多任務(wù)操作系統(tǒng)中的每個進程都在自己的內(nèi)存池中運行 。該池是虛擬地址空間空,在32位模式下始終是4GB內(nèi)存地址塊 。這些虛擬地址通過頁表映射到物理內(nèi)存,頁表由操作系統(tǒng)維護,由處理器引用 。每個流程都有自己的頁表,但還是有隱藏的故事 。只要虛擬地址被啟用,它就會作用于在這臺機器上運行的所有軟件,包括內(nèi)核本身 。因此,必須為內(nèi)核保留一些虛擬地址:
這并不意味著內(nèi)核使用了這么多物理內(nèi)存,只是可以控制這么大的地址空,可以根據(jù)內(nèi)核的需要映射到物理內(nèi)存 。內(nèi)核/在Linux中,內(nèi)核/內(nèi)核代碼和數(shù)據(jù)總是可尋址的,隨時可以處理中斷和系統(tǒng)調(diào)用 。相反,用戶模式地址空之間的映射隨著進程切換的發(fā)生而不斷變化:
藍色區(qū)域表示映射到物理內(nèi)存的虛擬地址,而白色區(qū)域表示未映射的部分 。在上面的例子中,火狐使用了相當(dāng)多的虛擬地址空房間,因為它是一個傳奇的內(nèi)存消耗者 。地址空中的每個條帶對應(yīng)于不同的內(nèi)存段,如堆和堆棧 。請記住,這些段只是簡單的內(nèi)存地址范圍,與英特爾處理器的段無關(guān) 。總之,以下是Linux進程的標(biāo)準(zhǔn)內(nèi)存段布局:
當(dāng)計算機快樂、安全、可愛、正常運行時,幾乎每個進程的每個段的起始虛擬地址都與上圖完全一致,這也為遠程發(fā)現(xiàn)程序安全漏洞打開了大門 。一個挖掘過程經(jīng)常需要引用絕對內(nèi)存地址:棧地址、庫函數(shù)地址等 。遠程攻擊者必須依靠地址空之間布局的一致性來摸索這些地址 。如果他們猜對了,就會有人完蛋 。因此,地址空之間的隨機排列逐漸流行起來 。Linux通過向堆棧、內(nèi)存映射段和堆棧的起始地址添加隨機偏移量來破壞布局 。遺憾的是,32位地址空相當(dāng)緊湊,隨機化留下的空并不大,削弱了這種技術(shù)的效果 。
進程地址/調(diào)用方法或函數(shù)會將新的堆棧幀推入堆棧 。當(dāng)函數(shù)返回時,堆棧框架被清理 。也許是因為數(shù)據(jù)嚴(yán)格遵循LIFO順序,這種簡單的設(shè)計意味著您不必使用復(fù)雜的數(shù)據(jù)結(jié)構(gòu)來跟蹤堆棧的內(nèi)容,只需一個指向堆棧頂部的簡單指針 。因此,推動和彈出過程非常快速和準(zhǔn)確 。此外,堆棧空的持續(xù)重用有助于將活動堆棧內(nèi)存保留在CPU緩存中,從而加速訪問 。進程中的每個線程都有自己的堆棧 。
通過持續(xù)將數(shù)據(jù)壓入堆棧,如果數(shù)據(jù)超出其容量,則對應(yīng)于堆棧的存儲區(qū)域?qū)⒈缓谋M 。這將觸發(fā)一個頁面錯誤,將由Linux的expand_stack()處理,它將調(diào)用acct_stack_growth()來檢查是否有適合堆棧增長的地方 。如果棧的大小低于RLIMIT_STACK(通常為8MB),棧一般會加長,程序會繼續(xù)愉快運行,不會感覺到發(fā)生了什么 。這是將堆棧擴展到所需大小的常規(guī)機制 。但是,如果達到最大堆棧空大小,將出現(xiàn)堆棧溢出,程序?qū)⑹盏椒侄五e誤 。當(dāng)映射的堆棧區(qū)域擴展到所需的大小時,它不會收縮,即使堆棧不是那么滿 。這就像聯(lián)邦預(yù)算,總是在增長 。
動態(tài)堆棧增長是唯一允許訪問未映射內(nèi)存區(qū)域(圖中白色區(qū)域)的情況 。對未映射內(nèi)存區(qū)域的任何其他訪問都將觸發(fā)頁面錯誤,從而導(dǎo)致段錯誤 。有些映射區(qū)域是只讀的,因此試圖寫入這些區(qū)域也會導(dǎo)致段錯誤 。
堆棧下面是我們的內(nèi)存映射部分 。這里,內(nèi)核將文件的內(nèi)容直接映射到內(nèi)存 。任何應(yīng)用程序都可以通過Linux的mmap()系統(tǒng)調(diào)用(實現(xiàn))或Windows的create file mapping()/mapviewpoffice()請求這個映射 。內(nèi)存映射是一種方便高效的文件I/O方法,因此被用來加載動態(tài)庫 。也可以創(chuàng)建不對應(yīng)任何文件的匿名內(nèi)存映射 。該方法用于存儲程序的數(shù)據(jù) 。在Linux中,如果您通過malloc()請求大塊內(nèi)存,C運行時將創(chuàng)建這樣一個匿名映射,而不是使用堆內(nèi)存 。“chunk”表示大于MMAP_THRESHOLD,默認(rèn)值為128KB,可以通過mallopt()進行調(diào)整 。
說到堆,就是下一塊地址空 。與堆棧一樣,堆在運行時用于內(nèi)存分配;但不同的是,堆用于存儲其生存期獨立于函數(shù)調(diào)用的數(shù)據(jù) 。大多數(shù)語言都提供堆管理功能 。因此,滿足內(nèi)存請求已經(jīng)成為語言運行時庫和內(nèi)核的共同任務(wù) 。在C語言中,堆分配的接口是malloc()系列函數(shù),而在具有垃圾收集功能的語言(如C#)中,這個接口是新的關(guān)鍵字 。
如果堆中有足夠的空空間來滿足內(nèi)存請求,它可以由語言運行時庫處理,而無需內(nèi)核的參與 。否則,堆將被擴大,請求所需的內(nèi)存塊將通過brk()系統(tǒng)調(diào)用(實現(xiàn))來分配 。堆管理非常復(fù)雜,需要精心設(shè)計的算法來處理程序中雜亂的分配模式,并優(yōu)化速度和內(nèi)存效率 。處理堆請求所需的時間可能有很大差異 。實時系統(tǒng)通過專用分配器解決了這個問題 。堆也可能變得碎片化,如下圖所示:

手機虛擬空間軟件 虛擬空間哪個好用

文章插圖
最后,我們來看看最底層的內(nèi)存段:BSS、數(shù)據(jù)段和代碼段 。在C語言中,BSS和數(shù)據(jù)段存儲靜態(tài)(全局)變量的內(nèi)容 。不同的是,BSS存儲的是未初始化的靜態(tài)變量內(nèi)容,它們的值不是直接在程序的源代碼中設(shè)置的 。BSS內(nèi)存區(qū)域是匿名的:它不映射到任何文件 。如果你寫靜態(tài)的int cntActiveUsers,cntActiveUsers的內(nèi)容將保存在BSS中 。
另一方面,數(shù)據(jù)段在源代碼中保存初始化的靜態(tài)變量內(nèi)容 。這個內(nèi)存區(qū)域不是匿名的 。它將程序的二進制映像的一部分,即靜態(tài)變量與源代碼中指定的初始值進行映射 。因此,如果您編寫static int cntWorkerBees = 10,則cntWorkerBees的內(nèi)容將保存在數(shù)據(jù)部分,初始值為10 。雖然數(shù)據(jù)段被映射到一個文件,但它是一個私有內(nèi)存映射,這意味著在這里更改內(nèi)存不會影響映射的文件 。一定也是這樣,否則給全局變量賦值會改變硬盤上的二進制映像,這是不可想象的 。
下圖中的數(shù)據(jù)段示例更復(fù)雜,因為它使用了指針 。在這種情況下,指針gonzo(4字節(jié)內(nèi)存地址)本身的值保存在數(shù)據(jù)段中 。它指向的實際字符串不在這里 。該字符串存儲在只讀的代碼段中 。它保存你所有的代碼加上一些小片段,比如字符串的文字值 。代碼段也將您的二進制文件映射到內(nèi)存,但是寫入該區(qū)域?qū)?dǎo)致您的程序收到代碼段錯誤 。這有助于防止指針錯誤,盡管它不如用C語言編程時注意預(yù)防那么有效 。下圖顯示了我們示例中的這些段和變量:
手機虛擬空間軟件 虛擬空間哪個好用

文章插圖
【手機虛擬空間軟件 虛擬空間哪個好用】您可以通過讀取文件/proc/PID _ of _ process/map來檢查Linux進程中的內(nèi)存區(qū)域 。請記住,一個片段可能包含許多區(qū)域 。例如,每個內(nèi)存映射文件在mmap部分都有自己的區(qū)域,動態(tài)庫有類似于BSS和數(shù)據(jù)部分的附加區(qū)域 。下一篇文章將解釋這些“區(qū)域”的真正含義 。有時候人們會提到“數(shù)據(jù)段”,意思是所有的數(shù)據(jù)段+BSS+堆 。
您可以通過nm和objdump命令查看二進制圖像并打印符號、它們的地址、段和其他信息 。最后需要指出的是,上面描述的虛擬地址布局在Linux中是一種“靈活布局”,并且已經(jīng)作為默認(rèn)方法使用了一些年 。它假設(shè)我們有值RLIMIT_STACK 。當(dāng)情況不是這樣時,Linux返回到經(jīng)典布局,如下圖所示:
以上就是虛擬地址空之間的布局 。下一篇文章將討論內(nèi)核如何跟蹤這些內(nèi)存區(qū)域 。我們將分析內(nèi)存映射,看看文件的讀寫操作是如何與之相關(guān)的,以及內(nèi)存使用配置文件的意義 。

    推薦閱讀