linux 性能自我學習 ———— 關于內存 [七]
前言
內存的基本知識,將在操作系統篇中詳細介紹,這里只說明如何排查問題。
正文
內存的分配和回收:
在malloc 是c 標準庫中的內存分配函數,對應到系統調用上,有兩種實現方式,一種是brk()和 mmap()
對于小塊內存,小于128k 使用brk來分配,也就是通過移動堆棧的位置來分配內存。這些內存釋放后,不會立即歸還給系統,而是緩存起來。
大塊內存,使用mmap()分配,在文件映射段找一塊空閑內存分配出去。
brk() 方式的緩存,可以減少缺頁異常的發生,提高內存訪問效率。不過這些內存沒有歸還系統,在內存工作繁忙時, 頻繁的內存分配和稀釋會造成內存碎片。
而mmap() 方式分配的內存,會釋放時直接規劃系統,所以每次mmap 都會發生缺頁異常。在內存工作繁忙時,頻繁的內存分配導致大量的缺頁異常,使內核的管理負擔增大。
那么就到了內存不足的情況:
-
回收緩存,比如使用lru算法,回收最近使用最少的內存頁面
-
回收不常用訪問的內存,把不常用的內存通過交互分區直接寫道磁盤中。
-
殺死進程,內存緊張時,系統會通過oom,直接殺死占用大量內存的進程。
第一種好理解,就是回收內存,在操作系統篇會介紹的比較詳細。
第二種,回收不常用的內存,會用到交換分區。swap 其實就是把一塊磁盤空間當作內存來用。它可以把進程暫不用的磁盤寫入到內存中。
第三種是oom。
-
一個進程消耗的內存越大,oom_score 就越大。
-
一個進程運行占用的cpu越多,oom_score 就越小。
oom_adj 的范圍 是[-17,15],數值越大,表示進程越容易被oom殺死。數值越小,表示進程越不容易被oom殺死,-17表示禁用oom。
一般情況下,查看內存的方式為??
里面有幾個參數:
total : 一共多少內存
used: 使用了多少內存
free: 沒有使用多少內存
shared: 共享內存大小
buff/cache 是緩存和緩沖區的大小
available: 表示新進程可用內存大小
availabel 不僅包含了free內存,還包含了可回收內存。
如果要看到進程的內存使用情況:
這里有另外幾個參數:
-
virt 是進程虛擬內存的大小, 只要進程申請過的內存, 即便還沒有真正分配物理內存,也會計算在內。
-
res 是長駐內存的大小,也就是進程實際使用的物理內存大小,但是不包含swap和共享內存。
-
shr 是共享內存大小
-
%mem 是進程使用物理內存占用系統內存的百分比
注意:
-
虛擬內存通常并不會全部分配物理內存。一般虛擬內存比長駐內存要大得多。
-
共享內存并不一定正在的共享比如程序代碼段,非共享的動態鏈接庫,也都算在shr里面。
下面看下cached 和 buff的區別:
在free 手冊中:
-
buffers 是內核緩沖區用到的內存,對于了/proc/meminfo 中的 buffers
-
cache 是內核頁緩存和slab 用到的內存,對應的是/proc/meminfo 中的cached 與 SReclaimable 之和。
查看/proc/meminfo的描述:
buffers 是對原始磁盤快的臨時存儲,也就是用來緩存磁盤的數據,通常不會特別大。
這樣內核就可以把分散的寫集中起來,同一優化磁盤的寫入,比如可以多次小的合并單次單的寫。
cached 是從磁盤讀取文件的緩存,也就是用來緩存從文件讀取的數據。這樣下次訪問這些文件的時候,就可以直接從內存中讀取,不用訪問磁盤。
所以呢? 一個是讀一個是寫,都是磁盤的概念。
和我們應用程序的緩存和緩沖不一樣。
但是是不是寫的時候只要 buffer 有影響,但是都cache 沒有影響呢?
在寫文件的時候對buffer 和 cache 都有影響,對寫磁盤對 buffer 有影響。
同樣讀的時候也是一樣的,對于磁盤來說,無論讀還是寫,都對buffer和cache 都有影響。
結
下一節,內存泄漏怎么分析。