Linux 应用 - 动态库 - 内存占用

背景

  • 在小内存(64M)嵌入式Linux平台上开发中遇到以下两个现象
  1. 验证公版程序,由于程序文件较大,设备flash中放不下,测试时需要将部分动态库放在SD卡中,插上SD卡,添加SD卡路径到动态库查找路径后再执行程序;程序支持SD卡录像功能,测试录像功能时,在录像过程中拔掉SD卡,程序必现bus err崩溃问题,gdb定位到的错误代码是随机的,但是大部分是保存在SD卡中的动态库中的代码,如果不拔卡能够稳定运行,如果不放动态库在SD中,程序也不会有问题,只是录像写文件会失败。
  2. 裁减公版程序,程序功能裁减的非常少了,但是内存占用依然很多,觉得非常异常,故分析一下,观察进程/proc/[pid]/smaps下的动态库代码段数据,发现动态库代码段所占物理内存在不断变化。

疑惑

  • 在PC上运行程序产生了固有印象:程序和动态库跑起来后会被加载进内存,可以删除其文件。
  1. 因此现象1中拔卡应该也没问题,动态库加载进内存了,原文件就没用了。
  2. 现象2更无法解释,动态库的代码段大小为什么会不断变化。

分析

  • 通过strace 分析任意一个程序的动态库加载流程,如下:
execve("./test", ["./test"], 0x7ffdaa80ac30 /* 26 vars */) = 0
....
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\240\35\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2030928, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0303f75000
mmap(NULL, 4131552, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f0303985000
mprotect(0x7f0303b6c000, 2097152, PROT_NONE) = 0
mmap(0x7f0303d6c000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7f0303d6c000
mmap(0x7f0303d72000, 15072, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f0303d72000
close(3)                                = 0
....
  • 由上可知动态库(代码段数据)是通过mmap系统接口加载进内存的。

mmap工作原理

  • mmap被调用时,会按参数申请连续的虚拟内存,当程序访问到虚拟内存页,由于没有映射物理内存,CPU会陷入OS,内核执行异常处理,分配物理内存,并用文件的内容填充该内存页,然后返回进程的上下文,执行进程指令;mmap申请物理内存页的粒度是单页。
  • mmap 占用的物理内存大小记录在 /proc/meminfo中的Mapped项,Mapped项属于 cache的一部分。

动态库内存占用

  • 因此动态库并不是整个加载进内存,而是按需按内存页的形式加载进内存。
  1. 当内存充足时,删除动态库文件也可能不会出异常,动态库所占物理内存大小也可能是固定的。
  2. 当手动执行drop_cache,或者内存不是很充足时,物理内存剩余触底 min_free_kbytes 触发内核进行释放cache操作,动态库mmap使用的标志是MAP_PRIVATE,该标志的内存可被释放,其满足条件的物理内存页将被释放,因此/proc/[pid]/smaps中的其代码端物理内存占用在不断变化,如果物理内存释放后,SD卡被拔出,又访问该物理内存保存的代码,CPU就会产生异常,触发缺页中断,读取文件,由于SD卡已拔出,文件不存在了,因此无法通过总线访问,再按照mmap时的地址等信息通过总线去访问,则会触发bus err 崩溃异常。
  3. 动态库所占物理内存会动态变化,甚至可能少于静态库所需物理内存,但是可能导致IO变高,在内存不充足的情况下,频繁的缺页中断处理会导致系统负载变大。
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值