1. 程式人生 > >外部碎片和內部碎片的區別

外部碎片和內部碎片的區別

一、在記憶體上(使用連續分配演算法來管理分配記憶體時會產生)的外部碎片和內部碎片兩個概念

這幾天一直看作業系統,看到記憶體的連續分配時,對於外部碎片和內部碎片時甚是不解:

記憶體碎片分為:內部碎片和外部碎片 【內部碎片】 內部碎片就是已經被分配出去(能明確指出屬於哪個程序)卻不能被利用的記憶體空間; 內部碎片處於(作業系統分配的用於裝載某一程序的記憶體)區域內部或頁面內部儲存塊。佔有這些區域或頁面的程序並不使用這個儲存塊。而在程序佔有這塊儲存塊時,系統無法利用它。直到程序釋放它,或程序結束時,系統才有可能利用這個儲存塊。 單道連續分配只有內部碎片。多道固定連續分配既有內部碎片,又有外部碎片。 【外部碎片】 外部碎片指的是還沒有被分配出去(不屬於任何程序),但由於太小了無法分配給申請記憶體空間的新程序的記憶體空閒區域。 外部碎片是處於任何兩個已分配區域或頁面之間的空閒儲存塊。這些儲存塊的總和可以滿足當前申請的長度要求,但是由於它們的地址不連續或其他原因,使得系統無法滿足當前申請。
產生外部碎片的一種情況:

舉個例子,在記憶體上,分配三個作業系統分配的用於裝載程序的記憶體區域

A、B和C。假設,三個記憶體區域都是相連的。故而三個記憶體區域不會產生外部碎片。現在假設B對應的程序執行完畢了作業系統隨即收回了B,這個時候A和C中間就有一塊空閒區域了。


多道可變連續分配只有外部碎片。

總之,在記憶體上,外部碎片是位於任何兩個作業系統分配的用於裝載程序的記憶體區域或頁面之間的空閒區域,內部碎片是位於一個作業系統分配的用於裝載程序的記憶體區域或頁面內部的空閒區域。

================================

二、在磁碟上的外部碎片和內部碎片兩個概念

很多人會把檔案碎片跟簇的概念混淆起來。其實對windows系統來說硬碟上的每個分割槽都是由最小儲存單元——簇組成的。就好比,一面牆是由一塊塊轉頭組成的。簇的大小可以在分割槽格式化時由使用者定義,一般是數個KB大小,比如是8KB。假設我有一個檔案,大小是80MB零1KB(1MB=1000KB),換算一下就是80,001KB,其中的80,000KB正好佔用10000個簇,剩下的那1KB,不得以也要佔用1個簇,但這最後一個簇還有7KB的空間沒用上了。而且這個未完全使用的簇,其他檔案也不允許繼續使用。

這就造成了一點點的空間浪費。

不少人就把這被浪費了的7KB空間就是磁碟上的內部碎片。

磁碟上的外部碎片(即平時所說的磁碟碎片,磁碟碎片清理工具只能清理磁碟上的外部碎片,清除不了磁碟上的內部碎片,除非改變檔案系統的分配單位即簇的大小,使之是一個檔案大小的整數倍。)實際上指的是一個檔案佔據那些簇是不連續的,就相當於檔案被分割開來,分別存放在相互間斷的幾段簇上。檔案被分割為幾個部分就是幾個碎片。所以碎片其實是指檔案碎片,可以理解成,檔案破碎成片之意。而且檔案碎片之間有時候順序還是錯亂的。比如說,有時候“檔案裡靠後的碎片”所佔的簇段在硬碟上反而會排在“檔案裡位置靠前的碎片”簇段的前面。這樣一來,一個檔案就會以比較混亂的順序存放在硬碟上。

顯然計算機讀取連續的有序的資料肯定要比不連續的亂序的資料來得快。所以整理碎片可能會大幅度提高系統性能。

舉個例子,起初硬碟某個分割槽是空白的,寫入三個檔案A、B和C。顯然這個時候,三個檔案都是順次佔用三個簇段(這個說明存放檔案所用的檔案系統應該是類似FAT這樣的檔案系統,具體參看註釋1)。故而三個檔案不會產生碎片。

現在假設你刪除了B檔案,這個時候A和C中間就有一塊空閒簇段了。此時還是不存在檔案碎片的,因為每個檔案各自佔據的簇段都是連續的,沒有檔案被分割。而如果現在需要寫入一個檔案D,而且D比剛剛刪去的檔案B要大。那麼A和C之間的空閒簇段就不足以放入D,再假設C後面的空閒簇段也不足以放下D,這個時候D就勢必要分割成兩塊存放,一塊放在A和C之間,另一塊放在C之後。這樣一來,檔案碎片就產生了。D檔案有兩個檔案碎片。

磁碟碎片整理要做的工作就是:把C檔案前移,一直移到緊接A檔案的簇段上去。這樣A和C之間就沒有空閒簇了,C之後剩下的將是一段完整的空閒簇段,足以放下檔案D。這樣D就也佔據一段連續的簇段。碎片也就消除了。


=====================================

外部碎片的兩種理解:

1、在記憶體上,位於任何兩個作業系統分配的用於裝載程序的記憶體區域或頁面之間的空閒區域稱為外部碎片

2、在磁碟上,將檔案分割成幾塊不相連的分片,這樣不相連的分片叫做檔案碎片,也即外部碎片。如果將檔案分割成幾塊相連的分片,這樣相連的分片則不是檔案碎片。

==============================

減少記憶體碎片  記憶體碎片是因為在分配一個記憶體塊後,使之空閒,但不將空閒記憶體歸還給最大記憶體塊而產生的。最後這一步很關鍵。如果記憶體分配程式是有效的,就不能阻止系統分配記憶體塊並使之空閒。即使一個記憶體分配程式不能保證返回的記憶體能與最大記憶體塊相連線(這種方法可以徹底避免記憶體碎片問題),但你可以設法控制並限制記憶體碎片。所有這些作法涉及到記憶體塊的分割。每當系統減少被分割記憶體塊的數量,確保被分割記憶體塊儘可能大時,你就會有所改進。 這樣做的目的是儘可能多次反覆使用記憶體塊,而不要每次都對記憶體塊進行分割,以正好符合請求的儲存量。分割記憶體塊會產生大量的小記憶體碎片,猶如一堆散沙。以後很難把這些散沙與其餘記憶體結合起來。比較好的辦法是讓每個記憶體塊中都留有一些未用的位元組。留有多少位元組應看系統要在多大程度上避免記憶體碎片。對小型系統來說,增加幾個位元組的內部碎片是朝正確方向邁出的一步。當系統請求1位元組記憶體時,你分配的儲存量取決於系統的工作狀態。 如果系統分配的記憶體儲存量的主要部分是 1 ~ 16 位元組,則為小記憶體也分配 16 位元組是明智的。只要限制可以分配的最大記憶體塊,你就能夠獲得較大的節約效果。但是,這種方法的缺點是,系統會不斷地嘗試分配大於極限的記憶體塊,這使系統可能會停止工作。減少最大和最小記憶體塊儲存量之間記憶體儲存量的數量也是有用的。採用按對數增大的記憶體塊儲存量可以避免大量的碎片。例如,每個儲存量可能都比前一個儲存量大 20%。在嵌入式系統中採用“一種儲存量符合所有需要”對於嵌入式系統中的記憶體分配程式來說可能是不切實際的。這種方法從內部碎片來看是代價極高的,但系統可以徹底避免外部碎片,達到支援的最大儲存量。 將相鄰空閒記憶體塊連線起來是一種可以顯著減少記憶體碎片的技術。如果沒有這一方法,某些分配演算法(如最先適合演算法)將根本無法工作。然而,效果是有限的,將鄰近記憶體塊連線起來只能緩解由於分配演算法引起的問題,而無法解決根本問題。而且,當記憶體塊儲存量有限時,相鄰記憶體塊連線可能很難實現。 有些記憶體分配器很先進,可以在執行時收集有關某個系統的分配習慣的統計資料,然後,按儲存量將所有的記憶體分配進行分類,例如分為小、中和大三類。系統將每次分配指向被管理記憶體的一個區域,因為該區域包括這樣的記憶體塊儲存量。較小儲存量是根據較大儲存量分配的。這種方案是最先適合演算法和一組有限的固定儲存量演算法的一種有趣的混合,但不是實時的。 有效地利用暫時的侷限性通常是很困難的,但值得一提的是,在記憶體中暫時擴充套件共處一地的分配程式更容易產生記憶體碎片。儘管其它技術可以減輕這一問題,但限制不同儲存量記憶體塊的數目仍是減少記憶體碎片的主要方法。 現代軟體環境業已實現各種避免記憶體碎片的工具。例如,專為分散式高可用性容錯系統開發的 OSE 實時作業系統可提供三種執行時記憶體分配程式:核心 alloc(),它根據系統或記憶體塊池來分配;堆 malloc(),根據程式堆來分配; OSE 記憶體管理程式 alloc_region,它根據記憶體管理程式記憶體來分配。 從 許多方面來看,Alloc就是終極記憶體分配程式。它產生的記憶體碎片很少,速度很快,並有判定功能。你可以調整甚至去掉記憶體碎片。只是在分配一個儲存量後,使之空閒,但不再分配時,才會產生外部碎片。內部碎片會不斷產生,但對某個給定的系統和八種儲存量來說是恆定不變的。 Alloc 是一種有八個自由表的固定儲存量記憶體分配程式的實現方法。系統程式設計師可以對每一種儲存量進行配置,並可決定採用更少的儲存量來進一步減少碎片。除開始時以外,分配記憶體塊和使記憶體塊空閒都是恆定時間操作。首先,系統必須對請求的儲存量四捨五入到下一個可用儲存量。就八種儲存量而言,這一目標可用三個 如果 語句來實現。其次,系統總是在八個自由表的表頭插入或刪除記憶體塊。開始時,分配未使用的記憶體要多花幾個週期的時間,但速度仍然極快,而且所花時間恆定不變。 堆 malloc() 的記憶體開銷(8 ~ 16 位元組/分配)比 alloc小,所以你可以停用記憶體的專用權。malloc() 分配程式平均來講是相當快的。它的內部碎片比alloc()少,但外部碎片則比alloc()多。它有一個最大分配儲存量,但對大多數系統來說,這一極限值足夠大。可選的共享所有權與低開銷使 malloc() 適用於有許多小型物件和共享物件的 C++ 應用程式。堆是一種具有內部堆資料結構的夥伴系統的實現方法。在 OSE 中,有 28 個不同的儲存量可供使用,每種儲存量都是前兩種儲存量之和,於是形成一個斐波那契(Fibonacci)序列。實際記憶體塊儲存量為序列數乘以 16 位元組,其中包括分配程式開銷或者 8 位元組/分配(在檔案和行資訊啟用的情況下為 16 位元組)。 當你很少需要大塊記憶體時,則OSE記憶體管理程式最適用。典型的系統要把儲存空間分配給整個系統、堆或庫。在有 MMU 的系統中,有些實現方法使用 MMU 的轉換功能來顯著降低甚至消除記憶體碎片。在其他情況下,OSE 記憶體管理程式會產生非常多的碎片。它沒有最大分配儲存量,而且是一種最先適合記憶體分配程式的實現方法。記憶體分配被四捨五入到頁面的偶數——典型值是 4 k 位元組。

相關推薦

外部碎片內部碎片區別

一、在記憶體上(使用連續分配演算法來管理分配記憶體時會產生)的外部碎片和內部碎片兩個概念 這幾天一直看作業系統,看到記憶體的連續分配時,對於外部碎片和內部碎片時甚是不解: 記憶體碎片分為:內部碎片和外部碎片 【內部碎片】 內部碎片就是已經被分配出去(能明確指出屬於哪個

外部碎片內部碎片

 外部碎片,是由於大量資訊由於先後寫入、置換、刪除而形成的空間碎片。  內部碎片,是由於存量資訊容量與最小儲存空間單位不完全相符而造成的空間碎片。還是沿用上面的例子,這次我們的6間倉庫目前都是空置的,但是假設我們管理倉庫的最小空間單位是間,今天運來了容量為2.5間倉庫的貨物,

記憶體分配外部碎片內部碎片

記憶體分配 其實最為簡單的記憶體分配的方法就是將記憶體分為多個固定大小的分割槽,每個分割槽只能容納一個程序,所以多道程式的程式數就會受到分割槽的限制,對於這種方法就是在一個分割槽空閒的時候就可以從輸入

外部時鐘與內部時鐘區別 作用 使用條件

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

【solidity語言】為什麼在合約內部return this.屬性或方法不行的原因?(理解外部呼叫內部呼叫)

contract Person { int[] public array; string public ss; function PersonTest1() public view returns(string) { this.array;

外部中斷內部中斷 硬中斷 軟中斷 中斷下半部

重要宣告: 以下程式碼有貼上 擷取他人勞動成果的成分 如有雷同 不勝榮幸 如您不能容忍 請不要獨自忍受@weChat:iisssssssssii 聯絡小民 主動刪除     中斷含義:  { 中斷是CPU處理外部突發事件的一個重要技術。它能使CPU在執行過程中對外部事件發

android獲取外部儲存內部儲存路徑

StorageManager sm = (StorageManager) activity.getSystemService(Context.STORAGE_SERVICE); // 獲取sdcard的路徑:外部儲存和內部儲存 String[] paths

Hive中如何建立內部外部表以及它們的區別

1.內部表(也稱為管理表)的建立: create table if not exists student( id int, name string, age int ) row format

內部碎片外部碎片

“碎片的記憶體”描述一個系統中所有不可用的空閒記憶體。這些資源之所以仍然未被使用,是因為負責分配記憶體的分配器使這些記憶體無法使用。這一問題通常都會發生,原因在於空閒記憶體以小而不連續方式出現

作業系統記憶體管理之 內部碎片vs外部碎片

“碎片的記憶體”描述一個系統中所有不可用的空閒記憶體。這些資源之所以仍然未被使用,是因為負責分配記憶體的分配器使這些記憶體無法使用。這一問題通常都會發生,原因在於空閒記憶體以小而不連續方式出現在不同的位置。由於分 配方法決定記憶體碎片是否是一個問題,因此記憶體分配器在保證

查看索引碎片維護

alt 索引 sel physical 查看 alter ati sele nta SELECT a.index_id , b.name , a.avg_fragmentation_in_percent FROM sys.dm_db_

碎片活動之間通信

man pre nac activity gets div main class tac // 在碎片中根據getActivity()即可獲取相關活動實例 // MainActivity mainActivity = (MainActivity

【微信小程式】在js中匯入第三方js或自己寫的js,使用外部js中的function的兩種方法 importrequire的區別使用方法

如下 定義了一個外部js檔案,其中有一個function import lunaCommon from '../lunaCommon.js'; var ctx = wx.getStorageSync("ctx"); var filter = "/ms-code"; var apis

libevent庫的外部內部實現

一、從大的方面來講libevent的實現就是: 1、往libevent庫裡註冊事件(I/O事件、signal事件、定時器事件) 2、啟動事件迴圈 3、通過I/O複用(select/poll/epoll)來將有就緒事件通知給系統 4、根據相應事件呼叫相應的函式 二、從細節方面來

cvDrawContours 在影象上繪製外部內部輪廓

                函式cvDrawContours用於在影象上繪製外部和內部輪廓。當thickness >= 0 時,繪製輪廓線;否則填充由輪廓包圍的部分。void cvDrawContours( CvArr *img, CvSeq* contour,                   

抽象類介面的區別,內部類引用外部方法final引數,守護執行緒使用者執行緒

abstract class和interface有什麼區別?         答:宣告方法的存在而不去實現它的類被叫做抽象類(abstract class),它用於要建立一個體現某些基本行為的類,併為該類宣告方法,但不能在該類中實現該類的情況。不能建立abstract 類的

Mesh中 material sharedMaterial 的區別內部實現的推斷

material 和 sharedMaterial 的區別 建立一個Material, 顏色為紅色, 建立兩個Quad,掛上剛剛建立的材質。 效果如下圖: 將第一個Quad掛載如下指令碼, 執行: render = GetComponent<

Web開發中的請求重定向內部轉發的區別

一、呼叫方式 我們知道,在servlet中呼叫轉發、重定向的語句如下: request.getRequestDispatcher("new.jsp").forward(request, response);   //轉發到new.jsp response.sen

碎片活動之間進行通訊、碎片之間進行通訊

為了方便碎片和活動之間進行通訊,FragmentManager提供了一個類似於findViewById()的方法,如下所示: //在活動中呼叫碎片的方法: RightFragment rightFragment = (RightFragment)getFrag

malloc原理記憶體碎片

當一個程序發生缺頁中斷的時候,程序會陷入核心態,執行以下操作: 1、檢查要訪問的虛擬地址是否合法  2、查詢/分配一個物理頁  3、填充物理頁內容(讀取磁碟,或者直接置0,或者啥也不幹)  4、建立對映關係(虛擬地址到實體地址) 重新執行發生缺頁中斷的那條指令 如果第3步