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