轉自:http://blog.csdn.net/ycnian/article/details/12971863緩存
咱們寫過不少C程序了,常常會分配內存。記得剛學C語言時老師說過,能夠向兩個地方申請內存:一個是棧、一個是堆。小塊內存向棧申請,函數調用結束後程序會自動釋放內存。大塊內存向堆申請,記得必定要本身釋放,不然會形成內存泄漏。向堆申請內存直接調用malloc()就能夠了,參數是你申請的內存量。釋放內存時直接調用free()就能夠了,參數是內存塊指針。多線程
看似平靜的海面,海底則波濤洶涌。當時尚未學操做系統原理,更沒有讀過Linux內核代碼。如今仔細想一想才發現申請動態內存是一件多麼麻煩的事情。動態內存管理涉及到兩個層面的問題:內核層面和用戶層面。系統中的內存如何管理這是內核考慮的事情,總不能讓應用程序隨便使用系統中的內存吧。內核嚮應用程序提供了接口(爲此Linux提供了兩個系統調用brk和mmap),當應用程序須要申請內存時向內核提出請求,內核查找並分配一塊可用內存供應用程序使用。這部份內容屬於內核範疇,不屬於C基礎庫,所以不深刻說了。那麼用戶層面作什麼呢?用戶層面須要合理管理內存申請和釋放請求。好比:brk()能夠擴充或收縮堆的大小,你總不能每分配一次內存就調用一次brk()吧?釋放內存時更麻煩,你必須保證內存塊的釋放順序。好比先申請了內存塊a,而後申請了內存塊b,而後釋放a(b仍然在使用),若是釋放a時調用了brk()就會出問題。你不能在使用b的同時釋放a。函數
好在出現了一個叫作「內存分配器」的東西,內存分配器接管了應用程序申請內存和釋放內存的請求,應用程序不再須要直接調用brk()和mmap()了,而是向內存分配器提交申請。有了內存分配器,咱們只須要記住malloc()和free()兩個接口函數就能夠了,其餘繁雜事情所有交給內存分配器負責了。申請內存時,內存分配器會一次向內核申請大量內存,而後分批交給應用程序,從而提升了效率。釋放內存時,應用程序也是將內存釋放給內存分配器,內存分配器在合適的時候再將內存釋放會內核。spa
dlmalloc就是一種內存分配器,由Doug Lea在1987年開發完成,這是Android系統中使用的內存分配器。而Linux系統中採用的是ptmalloc,ptmalloc在dlmalloc的基礎上進行了改進,以更好適應多線程。dlmalloc採用兩種方式申請內存,若是應用程序單次申請的內存量小於256kb,dlmalloc調用brk()擴展進程堆空間,可是dlmalloc向內核申請的內存量大於應用程序申請的內存量,申請到內存後dlmalloc將內存分紅兩塊,一塊返回給應用程序,另外一塊做爲空閒內存先保留起來。下次應用程序申請內存時dlmalloc就不須要向內核申請內存了,從而加快內存分配效率。當應用程序調用free()釋放內存時,若是內存塊小於256kb,dlmalloc並不立刻將內存塊釋放回內存,而是將內存塊標記爲空閒狀態。這麼作的緣由有兩個:一是內存塊不必定能立刻釋放會內核(好比內存塊不是位於堆頂端),二是供應用程序下次申請內存使用(這是主要緣由)。當dlmalloc中空閒內存量達到必定值時dlmalloc纔將空閒內存釋放會內核。若是應用程序申請的內存大於256kb,dlmalloc調用mmap()向內核申請一塊內存,返回返還給應用程序使用。若是應用程序釋放的內存大於256kb,dlmalloc立刻調用munmap()釋放內存。dlmalloc不會緩存大於256kb的內存塊,由於這樣的內存塊太大了,最好不要長期佔用這麼大的內存資源。操作系統
從下篇文章開始,咱們將詳細講解dlmalloc的代碼,環境是Linux 32位系統。.net