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 都有影响。
结
下一节,内存泄漏怎么分析。