linux通过meminfo 与 slab 定位内存泄漏
前言
问题真是一个接一个,做开发就是解决一个又一个问题吗?
像死机、内存泄漏这些问题很多时候是没有框架、设计或有了框架和设计但是团队没有统一遵循标准按着自己性子来导致的,统一的框架和设计也许会损失一定的灵活性,但是他会让你在编码的时候遵从一定的范式,且通过规范格式可以做到良好的自检查,例如将一个代码的实现分别放在A、B、C三个地方,A、B、C、分别干啥,接口是啥,A、B、C的范例等都在框架和设计中定义好了,每个编码人员按这个进行具体的开发编码工作,可以并行有序,甚至A、B、C进行不同的分工开发互不影响,比如A是解析配置的,B是做初始化的,C是业务处理主体。
对于应用开发,从框架、设计及编码质量这些工程角度避免低级错误,把开发的大部分时间用在算法、业务逻辑实现与优化等给客户带来良好体验与价值的地方,是一个软件团队需要努力的方向。
好吧,回到内存泄漏,这里指的是那些默默消耗了系统有限内存的操作,不仅仅指代码中申请而没有释放的内存,简单总结了下面几种情况进行检查和定位:
1,应用进程造成的内存泄漏
2,内核空间/或因应用进程的操作导致内核空间的内存泄漏
3,用户空间产生的临时文件(如日志等)造成的内存泄漏
应用进程造成的内存泄漏
1)采用ps或top命令进行观察
首先,我们习惯性的会看下那个进程在泄漏内存,我这里使用一个test_core_dump的测试进程,该进程每2秒钟会分配一个10000字节的空间,并作简单赋值(注意:如果仅malloc而不使用,编译器会优化,实际测试时将看不到内存泄漏的测试效果):
root@OpenWrt:/# ps
PID USER VSZ STAT COMMAND
14444 root 15984 S test_core_dump
省略不必要的信息,这里,我们主要看VSZ这个字段,这个字段表示该进程的虚拟内存大小,单位为KBytes,也就是此时我的测试进程已经占用近16M的虚拟内存空间,那是否意味着物理内存就已经被吃掉16M呢,这个我等下再讲。
或者我们通过top命令,也可以观察进程的VSZ字段,这里我当时没抓速据,所以就不放速据了,不管是top还是ps,重点是看VSZ字段的变化,当你发现VSZ字段一直在变化,则很明显这个进程有内存泄漏的问题,比如我现使用ps再看:
root@OpenWrt:/# ps
PID USER VSZ STAT COMMAND
14444 root 73884 S test_core_dump
我的测试进程已经占用近73M的虚拟地址空间。
2)查看/proc/meminfo
一般我们在发现有进程内存泄漏时,还会去查看一个文件,就是/proc/meminfo,看系统还有多少内存,比如我在上一步第一次ps时就去看了这个文件:
root@OpenWrt:/# cat /proc/meminfo
MemTotal: 125064 kB
MemFree: 28536 kB
Buffers: 8128 kB
Cached: 27844 kB
SwapCached: 0 kB
Active: 23004 kB
Inactive: 19996 kB
Active(anon): 10888 kB
Inactive(anon): 696 kB
Active(file): 12116 kB
Inactive(file): 19300 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Dirty: 0 kB
Writeback: 0 kB
AnonPages: 7092 kB
Mapped: 4648 kB
Shmem: 4556 kB
Slab: 36684 kB
SReclaimable: 5792 kB
SUnreclaim: 30892 kB
KernelStack: 704 kB
PageTables: 588 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 62532 kB
Committed_AS: 37800 kB
VmallocTotal: 1048372 kB
VmallocUsed: 12308 kB
VmallocChunk: 1020828 kB
看了系统还有MemFree: 28536 kB,约28M内存(我在系统启动完成时,就看了一次,大概是剩39M