Linux用掉的物理内存哪里去了

    内存是计算机系统的重要资源,在嵌入式系统中尤为明显。上层应用的程序员会接触到内存的使用,最常见的是堆栈。堆和栈仅仅是内存使用中的一部分,还有许多平常不太多见的部分占用着物理内存。在系统优化维护中,需要关注内存资源的整体使用情况以及大致的划分。在Linux系统中,通过free命令得到的Used内存被消耗在哪里了。下面我们逐步分析,Used内存被谁Used。为Linux系统维护和优化提供正确的指导。下面以我们的一个系统环境为例,分解统计过程。

总使用内存=Slab+PageTables+内存文件系统+SHM+用户进程的数据段+用户进程的文本段

(1)获取已使用物理内存值

~ # echo 3 > /proc/sys/vm/drop_caches
cat /proc/meminfo
~ # cat /proc/meminfo
MemTotal:        1763344 kB
MemFree:          946048 kB

执行之前先清理一下缓存,避免buffer和cache带来的误差。因为buffer和cache中并不全是正在使用的,没在使用的部分需要释放。

总使用内存=MemTotal-MemFree=817296kB

(2)获取Slab,PageTables的值

同(1),在cat /proc/meminfo中可以获取到它们的值。

Slab:              35616 kB
PageTables:         2672 kB
(3)获取内存文件系统占用的空间大小

在统计中,我们把共享内存部分独立统计,实际上它体现在内存文件系统的/dev/shm中。这里需要注意,不要重复统计。另外,挂载上来的外设空间也需要去除掉。

du -s 	/
du -s 	/RAMDISK
du -s 	/datadisk0
du -s 	/etc
du -s 	/init
du -s 	/lib32
du -s 	/linuxrc
du -s 	/mnt
du -s 	/proc
du -s 	/sbin
du -s 	/sysdisk0
du -s 	/usr
du -s 	/version
du -s 	/bin
du -s 	/dev
du -s 	/dev/shm
du -s 	/home
du -s 	/lib
du -s 	/lib64
du -s 	/lxImage
du -s 	/null
du -s 	/root
du -s 	/sys
du -s 	/tmp
du -s 	/var
结果如下:

675764	/            根目录
0	/RAMDISK     
168	/datadisk0   挂载第二块flash: /dev/ubi1_0
416	/etc
0	/init
18240	/lib32
0	/linuxrc
0	/mnt
0	/proc
15808	/sbin
494620	/sysdisk0    挂载第一块flash: /dev/ubi0_0
18912	/usr
0	/version
6096	/bin
94144	/dev         其中包括了挂载的tmpfs,对应/dev/shm共享内存
94128	/dev/shm     共享内存
209648	/home        重定向的目录/sysdisk0/home
5216	/lib
20512	/lib64
1568	/lxImage     BSP工具包
0	/null
16	/root
0	/sys
0	/tmp
48	/var
统计方法是:内存文件系统占用大小 = / - /datadisk0 - sysdisk0 - /dev/shm = 86848kB

(4)统计共享内存的大小

在上一步中已经有了统计结果:

94128	/dev/shm     共享内存

(5)统计用户进程的数据段占用内存大小

通过统计所有用户进程的smaps中的rss来获取用户进程数据段实际使用的物理内存大小。这里面不包括共享内存部分。因此统计的是smaps中的私有rss数据段。

用一个脚本来执行这段计算,得到的结果如下:

325,344
41,584
42,800
18,928
9,120
9,344
9,568
4,288
5,808
5,616
4,272
3,536
3,184
3,344
3,168
3,040
2,944
2,544
2,448
总和为500880kB

(6)统计用户进程的文本段占用内存大小

许多系统都会使用到动态库,动态库的大小通过rss统计不准确。好在较新的linux中提供了pss的统计值,看看pss和rss的对比区别。pss中把共享那部分按照引用次数平均分配到各进程中,这样统计出来就不会有重复了,呵呵!赞

RSS- Resident Set Size 实际使用物理内存(包含共享库占用的内存)
PSS- Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)
RSS is the total memory actually held in RAM for a process.RSS can be misleading, because it reports the total all of the shared libraries that the process uses, even though a shared library is only loaded into memory once regardless of how many processes use it. RSS is not an accurate representation of the memory usage for a single process.
PSS differs from RSS in that it reports the proportional size of its shared libraries, i.e. if three processes all use a shared library that has 30 pages, that library will only contribute 10 pages to the PSS that is reported for each of the three processes. PSS is a very useful number because when the PSS for all processes in the system are summed together, that is a good representation for the total memory usage in the system. When a process is killed, the shared libraries that contributed to its PSS will be proportionally distributed to the PSS totals for the remaining processes still using that library. In this way PSS can be slightly misleading, because when a process is killed, PSS does not accurately represent the memory returned to the overall system.

我们通过脚本对smaps中的文本段pss进行统计,结果如下:

6,501
10,027
10,782
14,614
4,975
7,779
2,914
1,347
5,584
4,072
1,376
988
715
663
748
952
1,387
526
438
总和为76388kB

汇总+思考:

汇总:35616 + 2672 + 86848 + 94128 + 500880 + 76388 = 796532. ( ⊙ o ⊙ )咦!? 咋比总使用内存817296kB还少了20764kB。想想是为什么呢?可以对比ps列出的下面的进程列表,分析一下以上统计中遗漏了什么,作为一个思考题  :)

/ # ps
PID   USER     TIME   COMMAND
    1 root       0:02 init
    2 root       0:00 [kthreadd]
    3 root       0:00 [migration/0]
    4 root       0:00 [ksoftirqd/0]
    5 root       0:00 [watchdog/0]
    6 root       0:00 [migration/1]
    7 root       0:00 [ksoftirqd/1]
    8 root       0:00 [watchdog/1]
    9 root       0:00 [migration/2]
   10 root       0:00 [ksoftirqd/2]
   11 root       0:00 [watchdog/2]
   12 root       0:00 [migration/3]
   13 root       0:00 [ksoftirqd/3]
   14 root       0:00 [watchdog/3]
   16 root       0:02 [events/0]
   17 root       0:00 [events/1]
   18 root       0:00 [events/2]
   19 root       0:00 [events/3]
   20 root       0:00 [rt_events/0]
   21 root       0:00 [rt_events/1]
   22 root       0:00 [rt_events/2]
   23 root       0:00 [rt_events/3]
   24 root       0:00 [khelper]
   27 root       0:00 [async/mgr]
  103 root       0:00 [sync_supers]
  105 root       0:00 [bdi-default]
  107 root       0:00 [kblockd/0]
  108 root       0:00 [kblockd/1]
  109 root       0:00 [kblockd/2]
  110 root       0:00 [kblockd/3]
  119 root       0:00 [khubd]
  165 root       0:00 [rpciod/0]
  166 root       0:00 [rpciod/1]
  167 root       0:00 [rpciod/2]
  168 root       0:00 [rpciod/3]
  179 root       0:00 [cerrhelper]
  180 root       0:00 [ecc_bg_thread]
  181 root       0:00 [nmi_daemon/0]
  182 root       0:01 [nmi_daemon/1]
  183 root       0:01 [nmi_daemon/2]
  184 root       0:01 [nmi_daemon/3]
  189 root       0:00 [khungtaskd]
  190 root       0:00 [kswapd0]
  191 root       0:00 [aio/0]
  192 root       0:00 [aio/1]
  193 root       0:00 [aio/2]
  194 root       0:00 [aio/3]
  195 root       0:00 [nfsiod]
  196 root       0:00 [crypto/0]
  197 root       0:00 [crypto/1]
  198 root       0:00 [crypto/2]
  199 root       0:00 [crypto/3]
  789 root       0:00 [mtdblockd]
  835 root       0:00 {rcS} /bin/sh /etc/init.d/rcS
  840 root       0:00 /sbin/udevd --daemon
 1476 root       0:00 telnetd
 1481 root       0:00 /sbin/udevd --daemon
 1520 root       0:00 /sbin/udevd --daemon
 1524 root       0:10 [ubi_bgt0d]
 1528 root       0:01 [ubifs_bgt0_0]
 1532 root       0:00 [ubi_bgt1d]
 1536 root       0:00 [ubifs_bgt1_0]
 1541 root       0:00 syslogd -l 8
 1546 root       0:00 {bspAppS.sh} /bin/sh /etc/init.d/bspAppS.sh
 1549 root       0:00 {admin.sh} /bin/sh /etc/init.d/admin.sh
 1569 daemon     0:00 portmap
 1571 root       0:00 rpc.mountd -d all
 1573 root       0:00 [lockd]
 1574 root       0:00 [nfsd4]
 1575 root       0:00 [nfsd]
 1576 root       7:27 ******  
 1641 root       0:56 ******
 1642 root       1:35 ******
 2047 root       0:40 ******
 2048 root       0:14 ******
 2049 root       0:18 ******
 2050 root       0:09 ******
 2051 root       0:34 ******
 2052 root       0:17 ******
 2053 root       2:26 ******
 2102 root       5:57 ******
 2138 root       4:02 ******
 2150 root     5295:2 ******
 2169 root       0:16 ******
 2170 root       0:41 ******
 2171 root       0:44 ******
 2250 root       0:12 ******
 2302 root      29:45 ******
 2303 root       0:14 ******
 2379 zte        0:00 -sh
 2380 root       0:00 sh
 2553 root       0:01 sh
 2775 root       0:00 ps
注:******这些是我的业务进程的名字,因为是敏感信息,所以用******代替。

总结:

通过以上的统计分析,能够总体上观察到已经使用的物理内存哪里去了。从而找到内存消耗的热点,进而找到优化点。以上的每一步都可以进一步细化统计分析,进一步减小包围圈,定位到具体的内存占用者。呵呵,再交流。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值