linux delete内存不下降_linux内存分配管理
linux內(nèi)存分配管理
一、前言
作為從事與C/C++程序開發(fā)人員,我們一直需要很好的管理內(nèi)存,申請和釋放;可能很多只知道使用malloc、new去申請,使用free、delete去釋放,但是,去根究其內(nèi)部的原理,可能就不是很清楚了;
這里主要對linux平臺的內(nèi)存管理進行一下總結(jié)和梳理;
二、內(nèi)存申請釋放
Linux虛擬內(nèi)存管理相關(guān)概念請移步至詳解linux虛擬內(nèi)存原理;
這里主要說說的是我們的內(nèi)存是怎么申請的:
在C/C++中,使用malloc進行內(nèi)存分配,C++使用的new,但是其底層也是使用malloc;在系統(tǒng)調(diào)用上面,一般使用的是brk()和mmap()函數(shù);
我們說一說這兩個函數(shù)的使用場景:
brk():
當內(nèi)存分配使用小于128K
對于小于128K的小塊內(nèi)存,系統(tǒng)會使用 brk() 來分配,也就是通過移動堆頂?shù)奈恢脕矸峙鋬?nèi)存。這些內(nèi)存釋放后并不會立刻歸還系統(tǒng),而是被緩存起來,這樣就可以重復(fù)使用。
**注:**使用brk()分配內(nèi)存時,只分配虛擬空間,不對應(yīng)物理內(nèi)存,只有第一次讀/寫數(shù)據(jù)時,引起內(nèi)核缺頁中斷,內(nèi)核才分配對應(yīng)的物理內(nèi)存,然后在虛擬地址上建立映射關(guān)系;
回收內(nèi)存
申請內(nèi)存使用完畢之后,內(nèi)存并不是真正的釋放掉了,而是只回推了**_edata**指針,內(nèi)存可以被重復(fù)利用;
brk分配的內(nèi)存需要等到高地址內(nèi)存釋放以后才能釋放brk分配的內(nèi)存需要等到高地址內(nèi)存釋放以后才能釋放,所以會產(chǎn)生內(nèi)存碎片;
但是當最高地址空間超過了128k,就會執(zhí)行trim(內(nèi)存緊縮)操作;
mmap():
大于128K
大塊內(nèi)存(大于 128K),則直接使用內(nèi)存映射 mmap() 來分配,也就是在文件映射段找一塊空閑內(nèi)存分配出去。
注意:這個和brk()是一樣的,只有第一次使用的時候才會真正分配物理內(nèi)存;
回收內(nèi)存
mmap回收內(nèi)存時是直接釋放歸還,不會進行重復(fù)利用,所以這種會導(dǎo)致每次 mmap 都會發(fā)生缺頁異常。在內(nèi)存工作繁忙時,頻繁的內(nèi)存分配會導(dǎo)致大量的缺頁異常,使內(nèi)核的管理負擔增大。這也是 malloc 只對大塊內(nèi)存使用 mmap 的原因。
參考:Linux內(nèi)存分配小結(jié)--malloc、brk、mmap
三、linux內(nèi)存管理
伙伴算法
定義:由一個母實體分成的兩個各方面屬性一致的兩個子實體,這兩個子實體就處于伙伴關(guān)系。在操作系統(tǒng)分配內(nèi)存的過程中,一個內(nèi)存塊常常被分成兩個大小相等的內(nèi)存塊,這兩個大小相等的內(nèi)存塊就處于伙伴關(guān)系
伙伴系統(tǒng)的宗旨就是用最小的內(nèi)存塊來滿足內(nèi)核的對于內(nèi)存的請求。在最初,只有一個塊,也就是整個內(nèi)存,假如為1M大小,而允許的最小塊為64K,那么當我們申請一塊200K大小的內(nèi)存時,就要先將1M的塊分裂成兩等分,各為512K,這兩分之間的關(guān)系就稱為伙伴,然后再將第一個512K的內(nèi)存塊分裂成兩等分,各位256K,將第一個256K的內(nèi)存塊分配給內(nèi)存,這樣就是一個分配的過程;
伙伴系統(tǒng)特點
1)兩個塊大小相同;2)兩個塊地址連續(xù);3)兩個塊必須是同一個大塊中分離出來的;
作用
伙伴系統(tǒng)是以page為單位進行操作的,一般管理的是大內(nèi)存分配
具體詳細參考:Linux伙伴系統(tǒng)(一)--伙伴系統(tǒng)的概述
- slab 分配器
linux內(nèi)核中會采用伙伴算法進行內(nèi)存分配管理,但是分配的內(nèi)存區(qū)是以頁框為基本單位的。對于內(nèi)核中小塊連續(xù)內(nèi)存的請求,比 如說幾個字節(jié)或者幾百個字節(jié),如果依然分配一個頁框來來滿足該請求,這樣的話就會有內(nèi)存碎片產(chǎn)生;
定義
slab分配器中用到了對象這個概念,所謂對象就是內(nèi)核中的數(shù)據(jù)結(jié)構(gòu)以及對該數(shù)據(jù)結(jié)構(gòu)進行創(chuàng)建和撤銷的操作。它的基本思想是將內(nèi)核中經(jīng)常使用的對象 放到高速緩存中,并且由系統(tǒng)保持為初始的可利用狀態(tài)。比如進程描述符,內(nèi)核中會頻繁對此數(shù)據(jù)進行申請和釋放。當一個新進程創(chuàng)建時,內(nèi)核會直接從slab分 配器的高速緩存中獲取一個已經(jīng)初始化了的對象;當進程結(jié)束時,該結(jié)構(gòu)所占的頁框并不被釋放,而是重新返回slab分配器中。如果沒有基于對象的slab分 配器,內(nèi)核將花費更多的時間去分配、初始化以及釋放一個對象。
slab分配器有以下三個基本目標:
1.減少伙伴算法在分配小塊連續(xù)內(nèi)存時所產(chǎn)生的內(nèi)部碎片;
2.將頻繁使用的對象緩存起來,減少分配、初始化和釋放對象的時間開銷。
3.通過著色技術(shù)調(diào)整對象以更好的使用硬件高速緩存;
參考:Linux內(nèi)存管理中的slab分配器
作用
- 高速緩存
- 分配小塊內(nèi)存
具體詳細參考:【Linux 內(nèi)核】內(nèi)存管理(三)slab分配器
說明:這是linux中比較重要的兩個內(nèi)存管理的方式,我對這塊也只是了解狀態(tài),并沒有深入去研究,這里只是簡單概括一下,以后有時間細細研究一下,現(xiàn)在大概知道這個原理和概念就行了;
四、回收內(nèi)存
那么上面說了內(nèi)存分配相關(guān)的內(nèi)容,那么,如果內(nèi)存出現(xiàn)了緊張,那系統(tǒng)自己會怎么辦?
其實,linux自己也做了一套機制,來進行內(nèi)存回收;
回收緩存,比如使用 LRU(Least Recently Used)算法,回收最近使用最少的內(nèi)存頁面;
原理
LRU(Least recently used,最近最少使用)算法根據(jù)數(shù)據(jù)的歷史訪問記錄來進行淘汰數(shù)據(jù),其核心思想是“如果數(shù)據(jù)最近被訪問過,那么將來被訪問的幾率也更高”。
實現(xiàn)
最常見的實現(xiàn)是使用一個鏈表保存緩存數(shù)據(jù),詳細算法實現(xiàn)如下:
新數(shù)據(jù)插入到鏈表頭部;
每當緩存命中(即緩存數(shù)據(jù)被訪問),則將數(shù)據(jù)移到鏈表頭部;
當鏈表滿的時候,將鏈表尾部的數(shù)據(jù)丟棄。
分析
【命中率】
當存在熱點數(shù)據(jù)時,LRU的效率很好,但偶發(fā)性的、周期性的批量操作會導(dǎo)致LRU命中率急劇下降,緩存污染情況比較嚴重。
【復(fù)雜度】
實現(xiàn)簡單。
【代價】
命中時需要遍歷鏈表,找到命中的數(shù)據(jù)塊索引,然后需要將數(shù)據(jù)移到頭部。
Swap:回收不常訪問的內(nèi)存,把不常用的內(nèi)存通過交換分區(qū)直接寫到磁盤中;
回收不常訪問的內(nèi)存時,會用到交換分區(qū),也稱為Swap。
Swap 其實就是把一塊磁盤空間當成內(nèi)存來用。它可以把進程暫時不用的數(shù)據(jù)存儲到磁盤中(這個過程稱為換出),當進程訪問這些內(nèi)存時,再從磁盤讀取這些數(shù)據(jù)到內(nèi)存中(這個過程稱為換入),Swap 把系統(tǒng)的可用內(nèi)存變大了。
通常只有在內(nèi)存不足時,才會發(fā)生 Swap 交換。
相對于內(nèi)存來說,磁盤讀寫的速度很慢,所以Swap 會導(dǎo)致嚴重的內(nèi)存性能問題。
OOM:殺死進程,內(nèi)存緊張時系統(tǒng)還會通過 OOM(Out of Memory),直接殺掉占用大量內(nèi)存的進程。
oom內(nèi)核的一種保護機制,它表示“內(nèi)存用完了”。它監(jiān)控進程的內(nèi)存使用情況,并且使用 oom_score 為每個進程的內(nèi)存使用情況進行評分:
- 一個進程消耗的內(nèi)存越大,oom_score 就越大;
- 一個進程運行占用的 CPU 越多,oom_score 就越小。
這樣,進程的 oom_score 越大,代表消耗的內(nèi)存越多,也就越容易被 OOM 殺死,從而可以更好保護系統(tǒng)。
當然,為了實際工作的需要,管理員可以通過 /proc 文件系統(tǒng),手動設(shè)置進程的 oom_adj ,從而調(diào)整進程的 oom_score。
oom_adj 的范圍是 [-17, 15],數(shù)值越大,表示進程越容易被 OOM 殺死;數(shù)值越小,表示進程越不容易被 OOM 殺死,其中 -17 表示禁止 OOM。
五、查看內(nèi)存命令
一般我們會使用free來查看內(nèi)存,當然,我們還可以使用ps/top等命令
先看一下free命令吧
root@iZuf67on1pthsuih96udyfZ:~/# freetotal used free shared buff/cache available
Mem: 953036 388052 65808 2860 499176 377200
Swap: 0 0 0
簡單的看一下每個字段的意義:
- total 是總內(nèi)存大小;
- used 是已使用內(nèi)存的大小,包含了共享內(nèi)存;
- free 是未使用內(nèi)存的大小;
- shared 是共享內(nèi)存的大小;
- buff/cache 是緩存和緩沖區(qū)的大小;
- available 是新進程可用內(nèi)存的大小。
這就是大概是linux內(nèi)存相關(guān)的一些知識點,這里寫的比較亂,相當于做個筆記了~~~
想了解學(xué)習更多C++后臺服務(wù)器方面的知識,請關(guān)注:微信公眾號:====CPP后臺服務(wù)器開發(fā)====
掃碼CPP后臺服務(wù)器開發(fā)轉(zhuǎn)載是一種動力 分享是一種美德 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎
總結(jié)
以上是生活随笔為你收集整理的linux delete内存不下降_linux内存分配管理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 已知三角形三点坐标求角度_细心研磨椭圆焦
- 下一篇: lnmp php文件访问不了,记一次ln