linux内存泄漏检测

简介:      在实际的项目中,最难缠的问题就是内存泄漏,当然还有panic之类的,内存泄漏分为两部分用户空间的和内核空间的.我们就分别从这两个层面分析一下.      用户空间查看内存泄漏和解决都相对简单。
     在实际的项目中,最难缠的问题就是内存泄漏,当然还有panic之类的,内存泄漏分为两部分用户空间的和内核空间的.我们就分别从这两个层面分析一下.
     用户空间查看内存泄漏和解决都相对简单。定位问题的方法和工具也很多相对容易.我们来看看.
    1. 查看内存信息
     cat /proc/meminfo、free、cat /proc/slabinfo等
    2.  查看进程的状态信息
    top、ps、cat /proc /pid/maps/status/fd等
   通常我们定位问题先在shell下ps查看当前运行进程的状态,嵌入式上可能显示的信息会少一些.

点击(此处)折叠或打开

  1. root@hos-machine:~# ps -uaxw
  2. USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
  3. root 1 0.0 0.1 119872 3328 ? Ss 8月10 0:24 /sbin/init splash
  4. root 2 0.0 0.0 0 0 ? S 8月10 0:00 [kthreadd]
  5. root 3 0.0 0.0 0 0 ? S 8月10 0:44 [ksoftirqd/0]
  6. root 5 0.0 0.0 0 0 ? S 8月10 0:00 [kworker/0:0H]
  7. root 7 0.0 0.0 0 0 ? S 8月10 3:50 [rcu_sched]
  8. root 8 0.0 0.0 0 0 ? S 8月10 0:00 [rcu_bh]
  9. root 9 0.0 0.0 0 0 ? S 8月10 0:12 [migration/0]
  10. root 10 0.0 0.0 0 0 ? S 8月10 0:01 [watchdog/0]
  11. root 11 0.0 0.0 0 0 ? S 8月10 0:01 [watchdog/1]
  12. root 12 0.0 0.0 0 0 ? S 8月10 0:12 [migration/1]
  13. root 13 0.0 0.0 0 0 ? S 8月10 1:18 [ksoftirqd/1]
  14. root 15 0.0 0.0 0 0 ? S 8月10 0:00 [kworker/1:0H]
  15. root 16 0.0 0.0 0 0 ? S 8月10 0:01 [watchdog/2]
  16. root 17 0.0 0.0 0 0 ? S 8月10 0:12 [migration/2]
  17. root 18 0.0 0.0 0 0 ? S 8月10 1:19 [ksoftirqd/2]
  18. root 20 0.0 0.0 0 0 ? S 8月10 0:00 [kworker/2:0H]
  19. root 21 0.0 0.0 0 0 ? S 8月10 0:01 [watchdog/3]
  20. root 22 0.0 0.0 0 0 ? S 8月10 0:13 [migration/3]
  21. root 23 0.0 0.0 0 0 ? S 8月10 0:41 [ksoftirqd/3]
  22. root 25 0.0 0.0 0 0 ? S 8月10 0:00 [kworker/3:0H]
  23. root 26 0.0 0.0 0 0 ? S 8月10 0:00 [kdevtmpfs]
  24. root 27 0.0 0.0 0 0 ? S 8月10 0:00 [netns]
  25. root 329 0.0 0.0 0 0 ? S 8月10 0:00 [ext4-rsv-conver]
  26. root 339 0.0 0.0 0 0 ? S 8月10 0:05 [kworker/1:1H]
  27. root 343 0.0 0.0 0 0 ? S 8月10 0:11 [kworker/3:1H]
  28. root 368 0.0 0.0 39076 1172 ? Ss 8月10 0:10 /lib/systemd/systemd-journald
  29. root 373 0.0 0.0 0 0 ? S 8月10 0:00 [kauditd]
  30. root 403 0.0 0.0 45772 48 ? Ss 8月10 0:01 /lib/systemd/systemd-udevd
  31. root 444 0.0 0.0 0 0 ? S 8月10 0:09 [kworker/2:1H]
  32. systemd+ 778 0.0 0.0 102384 516 ? Ssl 8月10 0:04 /lib/systemd/systemd-timesyncd
  33. root 963 0.0 0.0 191264 8 ? Ssl 8月10 0:00 /usr/bin/vmhgfs-fuse -o subtype=vmhgfs-fuse,allow_other /mnt/hgfs
  34. root 987 9.6 0.0 917024 0 ? Ssl 8月10 416:08 /usr/sbin/vmware-vmblock-fuse -o subtype=vmware-vmblock,default_permi
  35. root 1007 0.2 0.1 162728 3084 ? Sl 8月10 10:14 /usr/sbin/vmtoolsd
  36. root 1036 0.0 0.0 56880 844 ? S 8月10 0:00 /usr/lib/vmware-vgauth/VGAuthService -s
  37. root 1094 0.0 0.0 203216 388 ? Sl 8月10 1:48 ./ManagementAgentHost
  38. root 1100 0.0 0.0 28660 136 ? Ss 8月10 0:02 /lib/systemd/systemd-logind
  39. message+ 1101 0.0 0.1 44388 2608 ? Ss 8月10 0:21 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile
  40. root 1110 0.0 0.0 173476 232 ? Ssl 8月10 0:54 /usr/sbin/thermald --no-daemon --dbus-enable
  41. root 1115 0.0 0.0 4400 28 ? Ss 8月10 0:14 /usr/sbin/acpid
  42. root 1117 0.0 0.0 36076 568 ? Ss 8月10 0:01 /usr/sbin/cron -f
  43. root 1133 0.0 0.0 337316 976 ? Ssl 8月10 0:00 /usr/sbin/ModemManager
  44. root 1135 0.0 0.2 634036 5340 ? Ssl 8月10 0:19 /usr/lib/snapd/snapd
  45. root 1137 0.0 0.0 282944 392 ? Ssl 8月10 0:06 /usr/lib/accountsservice/accounts-daemon
  46. syslog 1139 0.0 0.0 256396 352 ? Ssl 8月10 0:04 /usr/sbin/rsyslogd -n
  47. avahi 1145 0.0 0.0 44900 1092 ? Ss 8月10 0:11 avahi-daemon: running [hos-machine.local]
这个是ubuntu系统里的信息比较详细,我们可以很清晰看到VMZ和RSS的对比信息.VMZ就是这个进程申请的虚拟地址空间,而RSS是这个进程占用的实际物理内存空间.
通常一个进程如果有内存泄露VMZ会不断增大,相对的物理内存也会增加,如果是这样一般需要检查malloc/free是否匹配。根据进程ID我们可以查看详细的VMZ相关的信息。例:

点击(此处)折叠或打开

  1. root@hos-machine:~# cat /proc/1298/status
  2. Name:    sshd
  3. State:    S (sleeping)
  4. Tgid:    1298
  5. Ngid:    0
  6. Pid:    1298
  7. PPid:    1
  8. TracerPid:    0
  9. Uid:    0    0    0    0
  10. Gid:    0    0    0    0
  11. FDSize:    128
  12. Groups:    
  13. NStgid:    1298
  14. NSpid:    1298
  15. NSpgid:    1298
  16. NSsid:    1298
  17. VmPeak:     65620 kB
  18. VmSize:     65520 kB
  19. VmLck:     0 kB
  20. VmPin:     0 kB
  21. VmHWM:     5480 kB
  22. VmRSS:     5452 kB
  23. VmData:     580 kB
  24. VmStk:     136 kB
  25. VmExe:     764 kB
  26. VmLib:     8316 kB
  27. VmPTE:     148 kB
  28. VmPMD:     12 kB
  29. VmSwap:     0 kB
  30. HugetlbPages:     0 kB
  31. Threads:    1
  32. SigQ:    0/7814
  33. SigPnd:    0000000000000000
  34. ShdPnd:    0000000000000000
  35. SigBlk:    0000000000000000
  36. SigIgn:    0000000000001000
  37. SigCgt:    0000000180014005
  38. CapInh:    0000000000000000
  39. CapPrm:    0000003fffffffff
  40. CapEff:    0000003fffffffff
  41. CapBnd:    0000003fffffffff
  42. CapAmb:    0000000000000000
  43. Seccomp:    0
  44. Cpus_allowed:    ffffffff,ffffffff
  45. Cpus_allowed_list:    0-63
  46. Mems_allowed:    00000000,00000001
  47. Mems_allowed_list:    0
  48. voluntary_ctxt_switches:    1307
  49. nonvoluntary_ctxt_switches:    203
如果我们想查看这个进程打开了多少文件可以
 ls -l /proc/1298/fd/* | wc
查看进程详细的内存映射信息

cat /proc/7393/maps
我们看一下meminfo各个注释:参考documentation/filesystem/proc.txt 

  1. MemTotal: Total usable ram (i.e. physical ram minus a few reserved bits and the kernel binary code) 
  2. MemFree: The sum of LowFree+HighFree
  3. Buffers: Relatively temporary storage for raw disk blocks shouldn't get tremendously large (20MB or so)
  4.  Cached: in-memory cache for files read from the disk (the pagecache). Doesn't include 
  5. SwapCached SwapCached: Memory that once was swapped out, is swapped back in but still also is in the swapfile (if memory is needed it
  6.               doesn't need to be swapped out AGAIN because it is already in the swapfile. This saves I/O)
  7.  Active: Memory that has been used more recently and usually not reclaimed unless absolutely necessary. 
  8. Inactive: Memory which has been less recently used. It is more eligible to be reclaimed for other purposes 
  9. HighTotal: 
  10. HighFree: Highmem is all memory above ~860MB of physical memory Highmem areas are for use by userspace programs, or
  11.               for the pagecache. The kernel must use tricks to access this memory, making it slower to access than lowmem.
  12.  LowTotal:
  13.  LowFree: Lowmem is memory which can be used for everything that highmem can be used for, but it is also available for the
  14.               kernel's use for its own data structures. Among many other things, it is where everything from the Slab is
  15.               allocated. Bad things happen when you're out of lowmem. 
  16. SwapTotal: total amount of swap space available
  17.  SwapFree: Memory which has been evicted from RAM, and is temporarily on the disk 
  18. Dirty: Memory which is waiting to get written back to the disk 
  19. Writeback: Memory which is actively being written back to the disk
  20.  AnonPages: Non-file backed pages mapped into userspace page tables
  21.  AnonHugePages: Non-file backed huge pages mapped into userspace page tables 
  22. Mapped: files which have been mmaped, such as libraries 
  23. Slab: in-kernel data structures cache
  24.  SReclaimable: Part of Slab, that might be reclaimed, such as caches
  25.  SUnreclaim: Part of Slab, that cannot be reclaimed on memory pressure 
  26. PageTables: amount of memory dedicated to the lowest level of page tables. 
  27. NFS_Unstable: NFS pages sent to the server, but not yet committed to stable storage 
  28. Bounce: Memory used for block device "bounce buffers" 
  29. WritebackTmp: Memory used by FUSE for temporary writeback buffers 
  30. CommitLimit: Based on the overcommit ratio ('vm.overcommit_ratio'), this is the total amount of memory currently available to
  31.               be allocated on the system. This limit is only adhered to if strict overcommit accounting is enabled (mode 2 in
  32.               'vm.overcommit_memory').
  33.               The CommitLimit is calculated with the following formula: CommitLimit = ('vm.overcommit_ratio' * Physical RAM) + Swap
  34.               For example, on a system with 1G of physical RAM and 7G
  35.               of swap with a `vm.overcommit_ratio` of 30 it would
  36.               yield a CommitLimit of 7.3G.
  37.               For more details, see the memory overcommit documentation in vm/overcommit-accounting.
  38.  Committed_AS: The amount of memory presently allocated on the system. The committed memory is a sum of all of the memory which
  39.               has been allocated by processes, even if it has not been
  40.               "used" by them as of yet. A process which malloc()'s 1G
  41.               of memory, but only touches 300M of it will only show up as using 300M of memory even if it has the address space
  42.               allocated for the entire 1G. This 1G is memory which has been "committed" to by the VM and can be used at any time
  43.               by the allocating application. With strict overcommit enabled on the system (mode 2 in 'vm.overcommit_memory'),
  44.               allocations which would exceed the CommitLimit (detailed above) will not be permitted. This is useful if one needs
  45.               to guarantee that processes will not fail due to lack of memory once that memory has been successfully allocated. 
  46. VmallocTotal: total size of vmalloc memory area
  47.  VmallocUsed: amount of vmalloc area which is used 
  48. VmallocChunk: largest contiguous block of vmalloc area which is free
我们只需要关注几项就ok.  buffers/cache/slab/active/anonpages

Active= Active(anon) + Active(file)    (同样Inactive)
AnonPages: Non-file backed pages mapped into userspace page tables\
buffers和cache的区别注释说的很清楚了.
有时候不是内存泄露,同样也会让系统崩溃,比如cache、buffers等占用的太多,打开太多文件,而等待系统自动回收是一个非常漫长的过程.
从proc目录下的meminfo文件了解到当前系统内存的使用情况汇总,其中可用的物理内存=memfree+buffers+cached,当memfree不够时,内核会通过
回写机制(pdflush线程)把cached和buffered内存回写到后备存储器,从而释放相关内存供进程使用,或者通过手动方式显式释放cache内存

点击(此处)折叠或打开

  1. drop_caches
  2. Writing to this will cause the kernel to drop clean caches, dentries and inodes from memory, causing that memory to become free.
  3. To free pagecache:
  4. echo 1 > /proc/sys/vm/drop_caches 
  5. To free dentries and inodes: 
  6. echo 2 > /proc/sys/vm/drop_caches
  7.  To free pagecache, dentries and inodes: 
  8. echo 3 > /proc/sys/vm/drop_caches
  9. As this is a non-destructive operation and dirty objects are not freeable, the user should run `sync`first
用户空间内存检测也可以通过 mtrace来检测用法也非常简单,之前文章我们有提到过. 包括比较有名的工具 valgrind、以及dmalloc、memwatch 等.各有特点.

   内核内存泄露的定位比较复杂,先判断是否是内核泄露了,然后在具体定位什么操作,然后再排查一些可疑的模块,内核内存操作基本都是kmalloc
即通过slab/slub/slob机制,所以如果meminfo里slab一直增长那么很有可能是内核的问题.我们可以更加详细的查看slab信息
cat /proc/slabinfo 
如果支持slabtop更好,基本可以判断内核是否有内存泄漏,并且是在操作什么对象的时候发生的。

点击(此处)折叠或打开

  1. cat /proc/slabinfo
  2. slabinfo - version: 2.1
  3. # name active_objs> num_objs> objsize> objperslab> pagesperslab> : tunables limit> batchcount> sharedfactor> : slabdata active_slabs> num_slabs> sharedavail>
  4. fuse_request 0 0 288 28 2 : tunables 0 0 0 : slabdata 0 0 0
  5. fuse_inode 0 0 448 18 2 : tunables 0 0 0 : slabdata 0 0 0
  6. fat_inode_cache 0 0 424 19 2 : tunables 0 0 0 : slabdata 0 0 0
  7. fat_cache 0 0 24 170 1 : tunables 0 0 0 : slabdata 0 0 0
在内核的配置中里面已经支持了一部分memleak自动检查的选项,可以打开来进行跟踪调试.
这里没有深入的东西,算是抛砖引玉吧~.







相关文章
|
2月前
|
安全 Linux Shell
Linux上执行内存中的脚本和程序
【9月更文挑战第3天】在 Linux 系统中,可以通过多种方式执行内存中的脚本和程序:一是使用 `eval` 命令直接执行内存中的脚本内容;二是利用管道将脚本内容传递给 `bash` 解释器执行;三是将编译好的程序复制到 `/dev/shm` 并执行。这些方法虽便捷,但也需谨慎操作以避免安全风险。
182 6
|
6天前
|
缓存 Java Linux
如何解决 Linux 系统中内存使用量耗尽的问题?
如何解决 Linux 系统中内存使用量耗尽的问题?
|
6天前
|
缓存 Linux
如何检查 Linux 内存使用量是否耗尽?
何检查 Linux 内存使用量是否耗尽?
|
13天前
|
缓存 算法 Java
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
35 6
|
16天前
|
算法 Linux 开发者
深入探究Linux内核中的内存管理机制
本文旨在对Linux操作系统的内存管理机制进行深入分析,探讨其如何通过高效的内存分配和回收策略来优化系统性能。文章将详细介绍Linux内核中内存管理的关键技术点,包括物理内存与虚拟内存的映射、页面置换算法、以及内存碎片的处理方法等。通过对这些技术点的解析,本文旨在为读者提供一个清晰的Linux内存管理框架,帮助理解其在现代计算环境中的重要性和应用。
|
22天前
|
Web App开发 JavaScript 前端开发
使用 Chrome 浏览器的内存分析工具来检测 JavaScript 中的内存泄漏
【10月更文挑战第25天】利用 Chrome 浏览器的内存分析工具,可以较为准确地检测 JavaScript 中的内存泄漏问题,并帮助我们找出潜在的泄漏点,以便采取相应的解决措施。
138 9
|
22天前
|
监控 JavaScript 前端开发
如何检测和解决 JavaScript 中内存泄漏问题
【10月更文挑战第25天】解决内存泄漏问题需要对代码有深入的理解和细致的排查。同时,不断优化和改进代码的结构和逻辑也是预防内存泄漏的重要措施。
35 6
|
21天前
|
存储 缓存 监控
|
25天前
|
Web App开发 缓存 JavaScript
如何检测和解决闭包引起的内存泄露
闭包引起的内存泄露是JavaScript开发中常见的问题。本文介绍了闭包导致内存泄露的原因,以及如何通过工具检测和代码优化来解决这些问题。
|
2月前
|
C语言 Android开发 C++
基于MTuner软件进行qt的mingw编译程序的内存泄漏检测
本文介绍了使用MTuner软件进行Qt MinGW编译程序的内存泄漏检测的方法,提供了MTuner的下载链接和测试代码示例,并通过将Debug程序拖入MTuner来定位内存泄漏问题。
基于MTuner软件进行qt的mingw编译程序的内存泄漏检测