Linux内核之内存3: 进程的内存消耗和内存泄漏

1.进程的VMA

(1)进程地址空间

在Linux系统中,每个进程都有自己的虚拟内存空间0~3G;

内核空间只有一个3G~4G;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-htaZj4ZA-1598499510613)(media/39176a76208129a24056fa3f9bf23e04.jpg)]

进程通过系统API调用,在内核空间申请内存,不统计在任何用户进程;进程消耗内存,单指用户空间内存消耗;

(2)VMA列表

LINUX用task_struct来描述进程,其中的mm_struct是描述内存的结构体,mm_struct有一个vma列表,管理当前进程的所有vma段。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7HypcM2V-1598499510616)(media/c0e4305d1d352443eb995b58eaf1e6b1.png)]

每个进程的内存由多个vma段组成:

(3)查看VMA方法:

1.pmap

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fn0VqW9K-1598499510617)(media/13ccc825d7e11b6e9345534002a6bf25.png)]

由图知,从接近0地址开始,第一个4K是只读代码段,第二个4K是只读数据段,还有其他共享库代码段,堆栈等;

可见一个进程的VMA涵盖多个地址区域**,但并没有覆盖所有地址空间**。VMA未覆盖的地址空间是illegal的,访问这些地址,缺页中断,发生pagefault.

2.cat /proc/pid/maps

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XrGeAQWP-1598499510619)(media/200b79c79bbed7cc3bf79b82455a09c5.png)]

读文件形式,与pmap一一对应;

3.cat /proc/pid/smaps

更详细的描述

00400000-00401000 r-xp 00000000 08:15 20316320 /home/leon/work/linux/mm/a.out
Size:         4 kb
KernelPageSize:    4 kB
MMUPageSize:      4 kB
Rss:          4 kB
Pss:          4 kB
Shared_Clean:     0 kB
Shared_Dirty:     0 kB
Private_Clean:     4 kB
Private_Dirty:     0 kB
Referenced:      4 kB
Anonymous:       0 kB
LazyFree:       0 kB
AnonHugePages:     0 kB
ShmemPmdMapped:    0 kB
Shared_Hugetlb:    0 kB
Private_Hugetlb:    0 kB
Swap:         0 kB
SwapPss:        0 kB
Locked:        0 kB
VmFlags: rd ex mr mw me dw sd

查看VMA的三个方法对比

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KnPLug2c-1598499510620)(media/fbe52107869af6ec71998a87b12c39c2.png)]

VMA的来源,代码段,数据段,堆栈段。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9BwwyJtZ-1598499510623)(media/1d4cbcb84b83d8eb509049e88dfcda9f.png)]

VMA是linux最核心数据结构之一。

2.page fault的几种可能性,major和minor

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aAZ9dkmy-1598499510624)(media/b7e5bf2c1ad0ec776d99dfc99c90528d.png)]

mmu给cpu发page fault时,可以从寄存器读到两个元素,pagefault地址pagefault原因

(1)访问Heap堆(首次申请,不是从Libc获取),第一次写,发生pagefault,linux检查VMA权限,发现权限合法,发缺页中断,申请一页内存,并更新页表。

(2)访问空区域,访问非法,发段错误;

(3)访问代码段, 在此区域写,报pagefault,检查权限发现错误,报段错误;

(4)访问代码段,在此区域读/执行,linux检查权限合法,若代码不在内存,那么申请内存页,把代码从硬盘读到内存。

伴随I/O的pagefault, 叫major pagefault, 否则minor pagefault.

major pagefault耗时远大于 minor pagefault.

\time -v python hello.py

3.内存是如何被瓜分的: :vss、rss、pss和uss

rss是不是代表进程的内存消耗呢,NO。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0NvPPmfQ-1598499510625)(media/6073a13855c3d6c6f0334b953cd7f285.png)]

VSS:单个进程全部可访问的地址空间,但未必所有虚拟地址都已经映射物理内存;

RSS:驻留内存,单个进程实际占用的物理内存大小(不十分准确的描述);上图的进程1

PSS:
比例化的内存消耗,相对RSS,将共享内存空间按被共享进程数量比例化;上图的C库4被三个进程共享,所以4/3;

USS:进程独占内存,比如上图的堆6。

案例,连续运行两次a.out,查看内存占用情况

运行程序a.out

./a.out &
pidof a.out
cat /proc/pid/smaps |more

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gPyKvrtv-1598499510627)(media/5280f46620090ef6c3fa837ef5fbdfbe.png)]


./a.out &
pidof a.out

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7SXvN81O-1598499510628)(media/552b45603d10618e2d7b0809e91253b3.png)]

cat /proc/pid_2/smaps |more

PSS变化

shared_clean

private_clean

4.应用内存泄漏的界定方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LlsupTTy-1598499510628)(media/5835a1555e4cb021132a1d4826cc318c.png)]

统计系统的内存消耗,查看PSS。

检查有没有内存泄漏,检查USS

./smem

smem –pie=command

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2mmpCFRL-1598499510629)(media/988c1868230625fb4282deb0ff7e70c7.png)]

smem –bar=command

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oGbvhuSh-1598499510630)(media/64ac61c220baae25eb3ee449ad3bbc89.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gQaQFVYl-1598499510631)(media/40574a9d8e29e2f10c507ed96a5c1b4e.png)]

android里面有类似的工具,procmem/procrank

smem分析系统内存使用是通过/proc/smaps的,procrank是通过分析/proc/kpagemap。

5.应用内存泄漏的检测方法:valgrind和addresssanitizer

其他查询内存泄漏工具:

valgrind:

	gcc -g leak-example.c -o leak-example

	valgrind --tool=memcheck --leak-check=yes ./leak-example

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UKodxfIp-1598500052901)(media/8323ab1eb838a435ddc6f82f731969ed.png)]

20468 HEAP SUMMARY:

20468 in use at exit: 270,336 bytes in 22 blocks

20468 total heap usage: 44 allocs, 22 frees, 292,864 bytes allocated

20468

20468 258,048 bytes in 21 blocks are definitely lost in loss record 2 of 2

20468 at 0x4C2DB8F: malloc (in
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

20468 by 0x4005C7: main (leak-example.c:6)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uYOsWPOa-1598500052903)(media/06e725b77df25e31fdb09166e84dd4e1.png)]

valgrid是在虚拟机跑APP,速度很慢;

新版gcc4.9以后集成了asan

asan:

	gcc -g -fsanitize=address ./leak-example.c

	gcc -fuse-ld=gold -fsanitize=address -g ./lsan.c

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aRxm0vzE-1598500052905)(media/79984ebb28cbf21cd21690b20aa13ddd.png)]

#1 0x40084e in main lsan.c:9

内存泄漏不一定在用户空间,排查内核空间,检测slab , vmalloc

slaptop, 检查申请和释放不成对。

在内核编译,打开kmemleak选项。

5.工程调试内存泄漏问题一般步骤:

(1) meminfo, free 多点采样确认有内存泄漏。

(2)定位,smem检查用户空间

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zj9u8ip1-1598500174678)(media/66e0b0b993fdacac3ac33583aec70b62.png)]

USS在不断增加。

(3) slab,检查内核空间。

cat /proc/slabinfo

其他查看内存信息的方法

cat /proc/meminfo

cat /proc/buddyinfo

cat /proc/zoneinfo

cat /proc/meminfo
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值