glibc內存碎片問題【轉】

    在dfs修bug的過程中,經常會發現sn節點內存的異常增加。一開始以爲是內存泄漏,可是找遍各種工具卻 發現不了,終於開始懷疑glibc本身的內存管理,上網查看,果然存在glibc的內存碎片問題。以前一直疑惑不解的sn進程內存非正常增長問題,現在終於找到了答案。汗,看來自己對glibc的瞭解正是太膚淺了。以下是某高手對glibc的內存管理做的總結:

    Linux用戶進程是如何釋放內存的,下圖是Linux進程使用內存的基本流程: 

 
    見圖1 
 從圖中我們可以看出,進程的堆,並不是直接建立在Linux的內核的內存分配策略上的,而是建立在glibc的堆管理策略上的(也就是glibc的動態內存分配策略上),堆的管理是由glibc進行的。 
所以我們調用free對malloc得到的內存進行釋放的時候,並不是直接釋放給操作系統,而是還給了glibc的堆管理實體,而glibc會在把實際的物理內存歸還給系統的策略上做一些優化,以便優化用戶任務的動態內存分配過程。 

那麼glibc的堆管理器在什麼時候才把物理內存歸還給系統呢? 
它會從堆的最大線性地址開始,從後向前計算用戶任務當前有多少空閒的堆內存(直到碰到使用中的堆內存地址爲止),比如在該圖中,

    
    見圖2 
 它會認爲有2048k的可釋放內存,只有在該值大於某個特定的threshhold時(2.3.6上爲64k),它纔會把這些內存歸還給系統。而在中間的“未使用”內存是不會歸還給系統的,所以系統也不可能再利用這塊物理內存頁(我們假設系統沒有swap區和swap文件),也就是說系統的內存會爲此減少,除非在它之前的堆內存都用free進行釋放以後,glibc的堆管理器纔有可能(只是有可能)把該段內存歸還給系統。 

由此,我們在使用malloc/free時應該小心,特別是在初始化時分配了好多內存,但是在這之後卻再也不需要這麼多的內存了,而這塊內存又沒有達到threshhold值或者在堆的最高線性地址處有某塊內存沒有釋放,但是它前面的所有堆內存都釋放了;這種情況下,用戶任務將會浪費一些物理內存,這在資源比較緊張的嵌入式系統中是不可容忍的。 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章