在android开发中,有时候我们想获取手机的一些硬件信息,比如android手机的总内存和可用内存大小。这个该如何实现呢?
通过读取文件"/proc/meminfo"的信息能够获取手机Memory的总量,而通过ActivityManager.getMemoryInfo(ActivityManager.MemoryInfo)方法可以获取当前的可用Memory量。
"/proc/meminfo"文件记录了android手机的一些内存信息,在命令行窗口里输入"adb shell",进入shell环境,输入"cat /proc/meminfo"即可在命令行里显示meminfo文件的内容,具体如下所示。
1 内存信息查看
proc 文件系统中涉及内存使用情况的文件 主要有:
/proc/meminfo 表征了系统内存使用概要信息:
[root@localhost ~]# cat /proc/meminfo
MemTotal: 505964 kB // 系统可用物理内存总量
MemFree: 16060 kB // 系统空闲内物理内存总量 = HighFree+ LowFree
Buffers: 41132 kB // 系统分配但未被使用的 buffer 数量 ( 注 1)
Cached: 359268 kB // 系统分配但未被使用的 cache 数量 ( 注 1)
SwapCached: 0 kB // 指交换出去的内存,再次交换回来,但在 swap 文件中仍存在,主要为了节约这块内存再次交换出去的 IO 操作
Active: 137156 kB // 最近使用的内存,除非必要,一般不会立即回收
Inactive: 282600 kB // 最近未使用的内存,回收时优先回收
HighTotal: 0 kB // 高端内存总量 (High Zone) , 860M 以上的物理内存
HighFree: 0 kB // 高端内存空闲总量
LowTotal: 505964 kB // 常规内存总量 (Normal Zone) ,可被 kernel 和应用任意使用
LowFree: 16060 kB // 常规内存空闲总量
SwapTotal: 1269124 kB // 总的交换内存大小
SwapFree: 1268948 kB // 空闲的交换内存大小
Dirty: 76 kB // 需要写回磁盘的数据大小
Writeback: 0 kB // 正在写回磁盘的数据大小
Mapped: 33808 kB //mmap 使用的内存大小
Slab: 63204 kB //slab pool 大小
CommitLimit: 1522104 kB // 系统实际可分配内存总量 ( 注 2)
Committed_AS: 98172 kB // 系统当前已分配的内存总量,包括 unused( 注 2)
PageTables: 1660 kB // 管理内存页表所使用的内存
VmallocTotal: 507896 kB //vmalloc 可使用的总内存大小
VmallocUsed: 3676 kB // vmalloc 已用的总内存大小
VmallocChunk: 503960 kB //vmalloc 可分配的最大的逻辑连续的内存大小
....
(1) 、 cache 与 buffer 的区别
Cache 和 buffer 都是系统做为缓冲的内存, cache 指的是 page cache ,表示文件系统的 cache ;而 buffer指的是 buffer cache ,用来为块设备的做读写缓冲,与具体的块设备关联,跟踪块的变化。 Linux 系统之所以使用 cache 和 buffer ,主要是为了提高文件读写访问的性能。
简单来说, buffers 是用来存储,目录里面有什么内容,权限等等。而 cached 直接用来记忆我们打开的文件。如果 cache 的值很大,说明 cache 住的文件数很多。
Cache 和 buffer 的内存对kernel 来说是已经被使用的 , free 的内存是指不需要任何处理即可分配的内存。对应用程序而言,当 free 内存不足时,可以从 buffer 和 cache 中回收内存再次分配。所以对 kernel 而言,可用内存即为 free ,对应用程序,可用内存为 free+cache+buffer 。
(2) 、 CommitLimit 和 Committed_AS
CommitLimit :基于过量分配比率 (vm.overcommit_ratio) ,系统可分配的内存总量大小。这个值只有当采用严格过量内存管理 (vm.overcommit_memory=2) 时才有效。其总大小的计划公式如下:
CommitLimit = (vm.overcommit_ratio * Physical RAM) + Swap
Committed_AS :系统当前已分配的内存总量,包括已分配但尚未使用的内存大小。如,一个进程分配了 1G 的内存,有 300M 在使用,但对 VM 已分配了 1G ,而且这 1G 在任何时候都可以被使用。当(vm.overcommit_memory=2) 时, Committed_AS 不能大于 CommitLimit 。
/proc/pid /status 表征了进程状态信息:
[zhangyan@localhost opt]$ cat /proc/28151/status
Name: memtest
State: R (running)
SleepAVG: 0%
......
Groups: 500
VmSize: 7528 kB // 该进程使用虚拟内存大小,是 VmLib, VmExe, VmData 和 VmStk 的总和
VmLck: 0 kB // 进程当前使用的并且加锁的虚拟内存总数
VmRSS: 5400 kB // 占用的在物理内存大小,它没有交换到硬盘,包括代码,数据和栈
VmData: 5136 kB // 堆使用的虚拟内存
VmStk: 1104 kB // 栈使用的虚拟内存
VmExe: 1 kB // 可执行的和静态链接库所使用的虚拟内存
VmLib: 1259 kB // 动态链接库所使用的虚拟内存
......
/proc/slabinfo 主要表征了 slab pool 内数据的信息:
[root@localhost ~]# cat /proc/slabinfo
slabinfo - version: 2.0
# name <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : tunables <batchcount> <limit> <sharedfactor> : slabdata <active_slabs> <num_slabs> <sharedavail>
nfs_direct_cache 0 0 68 58 1 : tunables 120 60 8 : slabdata 0 0 0
......
主要关注 <active_objs> <num_objs> <objsize> 三个项,一种类型的数据所占内存的大小为: active_objs* objsize ,该类内存池中空闲内存数: (num_objs- active_objs)* objsize 。但并不是所有的空闲的内存单元是可回收的,这与创建时该类型内存池时的属性相关。
2 内存管理策略
与内存相关的配置都在 /proc/sys/vm 目录下 :
/proc/sys/vm/dirty_ratio
文件系统写缓冲区的大小,单位是百分比,表示系统内存的百分比,表示当写缓冲使用到系统内存多少的时候,开始向磁盘写出数据。增大之会使用更多系统内存用于磁盘写缓冲,也可以极大提高系统的写性能。但是,当需要持续、恒定的写入时,应该降低其数值。
/proc/sys/vm/dirty_background_ratio
控制 pdflush 进程在何时刷新磁盘。单位是百分比,表示系统内存的百分比,意思是当写缓冲使用到系统内存多少的时候, pdflush 开始向磁盘写出数据。增大之会使用更多系统内存用于磁盘写缓冲,也可以极大提高系统的写性能。但是,当需要持续、恒定的写入场合时,应该降低其数值。
/proc/sys/vm/dirty_writeback_centisecs
控制 pdflush 的运行间隔。单位是 1/100 秒。缺省数值是 500 ,也就是 5 秒。如果你的系统是持续地写入动作,那么实际上还是降低这个数值比较好,这样可以把尖峰的写操作削平成多次写操作。
/proc/sys/vm/dirty_expire_centisecs
表示如果脏数据在内存中驻留时间超过该值, pdflush 进程在下一次将把这些数据写回磁盘。单位是 1/100 秒。缺省是 30000 ,也就是 30 秒的数据就算旧了,将会刷新磁盘。
/proc/sys/vm/overcommit_memory
指定内核针对内存分配的策略,其值可以是 0 、 1 、 2 。
0 : 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。
1 : 表示内核允许分配所有的物理内存,而不管当前的内存状态如何。
2 : 表示内核允许分配所有的物理内存的一定百分比与交换空间总和之内的内存(参见 overcommit_ratio )。
/proc/sys/vm/overcommit_ratio
如果 overcommit_memory=2 ,可以过载内存的百分比。系统可分配内存 = 交换空间 + 物理内存*overcommit_ratio/100 。