ptmalloc,tcmalloc和jemalloc内存分配策略研究
轉(zhuǎn)載:https://cloud.tencent.com/developer/article/1173720
?
操作系統(tǒng)內(nèi)存布局
各種malloc的內(nèi)存分配管理方式離不開(kāi)操作系統(tǒng)的內(nèi)存布局策略。
32位經(jīng)典內(nèi)存布局
32位系統(tǒng)下經(jīng)典內(nèi)存布局如上,程序起始的1GB地址為內(nèi)核空間,接下來(lái)是向下增長(zhǎng)的棧空間和由0x40000000向上增長(zhǎng)的mmap地址。而堆地址是從底部開(kāi)始,去除ELF、數(shù)據(jù)段、代碼段、常量段之后的地址并向上增長(zhǎng)。但是這種布局有幾個(gè)問(wèn)題,首先是容易遭受溢出攻擊;其次是,堆地址空間只有不到1G有木有?如果mmap內(nèi)存比較少地址很浪費(fèi)有木有?所以后來(lái)就有了另一種內(nèi)存布局。
32位默認(rèn)內(nèi)存布局
這幅圖描述地比較清楚也比較完整。首先是加入了幾種Random offset隨機(jī)偏移,導(dǎo)致內(nèi)存溢出攻擊不那么容易了,其次是堆仍然向上,但是mmap向下增長(zhǎng)。但是這樣的話棧空間就不是動(dòng)態(tài)增長(zhǎng)的了,所以現(xiàn)在的操作系統(tǒng)都有棧大小限制來(lái)著(Windows好像默認(rèn)是2MB對(duì)吧?Linux可以u(píng)limit –s查看)。這種內(nèi)存布局地址利用度比較高。
64位內(nèi)存布局
64位系統(tǒng)的尋址空間比較大,所以仍然沿用了32位的經(jīng)典布局,但是加上了隨機(jī)的mmap起始地址,以防止溢出攻擊。反正一時(shí)半會(huì)是用不了這么大的內(nèi)存地址了,所以至少N多年不會(huì)變了(話說(shuō)要生產(chǎn)出40TB+的內(nèi)存條,把堆內(nèi)存地址用光,一時(shí)半會(huì)也搞不定吧)。
總結(jié)
縱觀各種內(nèi)存布局,對(duì)于大內(nèi)存各種malloc基本上都是直接mmap的。而對(duì)于小數(shù)據(jù),則通過(guò)向操作系統(tǒng)申請(qǐng)擴(kuò)大堆頂,這時(shí)候操作系統(tǒng)會(huì)把需要的內(nèi)存分頁(yè)映射過(guò)來(lái),然后再由這些malloc管理這些堆內(nèi)存塊,減少系統(tǒng)調(diào)用。而在free內(nèi)存的時(shí)候,不同的malloc有不同的策略,不一定會(huì)把內(nèi)存真正地還給系統(tǒng),所以很多時(shí)候,如果訪問(wèn)了free掉的內(nèi)存,并不會(huì)立即Run Time Error,只有訪問(wèn)的地址沒(méi)有對(duì)應(yīng)的內(nèi)存分頁(yè),才會(huì)崩掉。
Ptmalloc
Ptmalloc采用主-從分配區(qū)的模式,當(dāng)一個(gè)線程需要分配資源的時(shí)候,從鏈表中找到一個(gè)沒(méi)加鎖的分配區(qū),在進(jìn)行內(nèi)存分配。
小內(nèi)存分配
在ptmalloc內(nèi)部,內(nèi)存塊采用chunk管理,并且將大小相似的chunk用鏈表管理,一個(gè)鏈表被稱為一個(gè)bin。前64個(gè)bin里,相鄰的bin內(nèi)的chunk大小相差8字節(jié),稱為small bin,后面的是large bin,large bin里的chunk按先大小,再最近使用的順序排列,每次分配都找一個(gè)最小的能夠使用的chunk。
Chunk的結(jié)構(gòu)如上所示,A位表示是不是在主分配區(qū),M表示是不是mmap出來(lái)滴,P表示上一個(gè)內(nèi)存緊鄰的chunk是否在使用,如果沒(méi)在使用,則size of previous chunk是上一個(gè)chunk的大小,否則無(wú)意義(而且被用作被分配出去的內(nèi)存了),正式根據(jù)P標(biāo)記位和size of previous chunk在free內(nèi)存塊的時(shí)候來(lái)進(jìn)行chunk合并的。當(dāng)然,如果chunk空閑,mem里還記錄了一些指針用于索引臨近大小的chunk的,實(shí)現(xiàn)原理就不復(fù)述了,知道大致作用就行。
在free的時(shí)候,ptmalloc會(huì)檢查附近的chunk,并嘗試把連續(xù)空閑的chunk合并成一個(gè)大的chunk,放到unstored bin里。但是當(dāng)很小的chunk釋放的時(shí)候,ptmalloc會(huì)把它并入fast bin中。同樣,某些時(shí)候,fast bin里的連續(xù)內(nèi)存塊會(huì)被合并并加入到一個(gè)unsorted bin里,然后再才進(jìn)入普通bin里。所以malloc小內(nèi)存的時(shí)候,是先查找fast bin,再查找unsorted bin,最后查找普通的bin,如果unsorted bin里的chunk不合適,則會(huì)把它扔到bin里。
大內(nèi)存分配
Ptmalloc的分配的內(nèi)存頂部還有一個(gè)top chunk,如果前面的bin里的空閑chunk都不足以滿足需要,就是嘗試從top chunk里分配內(nèi)存。如果top chunk里也不夠,就要從操作系統(tǒng)里拿了。
還有就是特別大的內(nèi)存,會(huì)直接從系統(tǒng)mmap出來(lái),不受chunk管理,這樣的內(nèi)存在回收的時(shí)候也會(huì)munmap還給操作系統(tǒng)。
簡(jiǎn)而言之,就是:**
**小內(nèi)存: [獲取分配區(qū)(arena)并加鎖] -> fast bin -> unsorted bin -> small bin -> large bin -> top chunk -> 擴(kuò)展堆
大內(nèi)存: 直接mmap
總結(jié)
釋放的時(shí)候,幾乎是和分配反過(guò)來(lái),再加上可一些chunk合并和從一個(gè)bin轉(zhuǎn)移到另一個(gè)bin的操作。并且如果頂部有足夠大的空閑chunk,則收縮堆頂并還給操作系統(tǒng)。
介于此,對(duì)于ptmalloc的內(nèi)存分配使用有幾個(gè)注意事項(xiàng):
總結(jié)
以上是生活随笔為你收集整理的ptmalloc,tcmalloc和jemalloc内存分配策略研究的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 餐厅点餐系统源码(带电脑端和手机端)
- 下一篇: 五大黑科技资源网站,你想要的这里都有