procNameArray="Host Superexe ServiceManager libplugin-container.so"
procName=""
ProcIdArray=0
ProcId=0
elastosMemmory=0
rate=5
#getopts 是用来处理命令行参数,一般的格式:getopts option varible
#getopts 使用的时候会自动产生两个变量OPTIND和OPTARGR,含义如下
#OPTIND:下一个待处理的参数索引,所以它的初始值就为1,从命令行参数开始,
#命令本身索引是0
#OPTARGR:获取期望参数后,把后面的内容存入OPTARGR中,例如输入
#monitor -d seconds -n proName后,第一次循环,会获取到参数1,即参数d(getopts
#会通过'-'来识别参数),这时就会把参数d后面跟的参数具体值存入到OPTARGR中。这里
#有一个地方大家会注意到 getopts d:n: opt,d和n后面都有一个冒号,这冒号表示在执行
#时,d的后面必须跟参数值的内容。
#getopts 具体的执行流程是每次都会获取到一个参数类型,然后和option比较,如果
#option中有,就把它放入opt变量中,没有把?放入opt变量中,同时把参数后面跟的内容
#放入OPTARGR。这里有一个顺序,是先和option比较,再放入opt中。
#介绍下getopts中的静默模式
#如果在option参数前加':',比如getopts :d:n: opt,这时针对d参数就会有两种非法处理
#方式,invalid option 和 miss option argument
#invalid option:就是当没有匹配上option时,就往变量opt中写入'?'
#miss option argument:当有匹配,但后面没有跟具体内容时,就往opt中写入':'
#非静默模式
#不管匹配还是没有内容,都往opt中写入'?'
while getopts d:n: opt
do
case $opt in
d )
rate=$OPTARG
;;
n )
procNameArray=$OPTARG
;;
? )
echo "usage :monitor -d seconds -n procName"
break
;;
esac
done
#"&&"的用法:至于"&&"左边的命令为真时,才会去执行右边的命令,所以在下面
#的判断中会发现continue的前面还有一个"&&",说明只有前面的命令全为真的时候
#才会执行continue(跳过本次循环的剩余代码,继续下一次循环)
getProcInfo() {
#memory
#VmPeak: 表示进程所占用最大虚拟内存大小
#VmSize: 表示进程当前虚拟内存大小
#VmLck: 表示被锁定的内存大小
#VmHWM: 表示进程所占用物理内存的峰值
#VmRSS: 表示进程当前占用物理内存的大小(与procrank中的RSS)
#VmData: 表示进程数据段的大小
#VmStk: 表示进程堆栈段的大小
#VmExe: 表示进程代码的大小
#VmLib: 表示进程所使用共享库的大小
#VmPTE: 表示进程页表项的大小
while read line
do
[[ "${line/"VmHWM:"/}" != "$line" ]] && info=${info}" "${line} && continue
#[[ "${line/"VmRSS:"/}" != "$line" ]] && info=${info}" "${line} && continue
[[ "${line/"Threads:"/}" != "$line" ]] && info=${info}" "${line} && continue
#这里是将标准输入重定向到status文件,这是status作为标准输入,所以这里每次
#都会从status文件中读取一行到line中,进行判断,一直读到文件结尾结束。
#(注意,这里的重定向周期就是整个循环)
done <"/proc/"$ProcId"/status"
#procrank
#VSS - Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)
#RSS - Resident Set Size 实际使用物理内存(包含共享库占用的内存)
#PSS - Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)
#USS - Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)
#PID Vss Rss Pss Uss cmdline
#get PSS from procrank
#procmem值得获取流程
#1.通过adb shell procrank命令获取android中进程的内存信息
#2.使用grep抓取对应ID的进程信息行,再通过awk命令获取信息行中第四个参数的值
#3.使用sed对获取到的参数值进行处理,清除 非数字,',','.'字符,相应位置用
#空格替换。sed 's/A/B/g'表示把A全部替换成B,B没有的时候,就替换成空格。
procmem=`procrank | grep $ProcId | awk '{print $4}' | sed 's/[^0-9,. ]//g'`
let "elastosMemmory = $elastosMemmory + $procmem"
#openfile
file="/proc/"$ProcId"/fd/"
echo $ProcId $info "OpenFile:"`ls $file | wc -l` "PSS:"$procmem"KB"
info=""
}
下面是一个获取内存信息的函数
先来说一下${line:0:8}的意思:该命令就是获取当前行从0到8的字符,然后判断是不是和后面提供的字符串一样,例如"MemFree:"。
${line:0:8}的模式定义是${var:position:length} -- var表示变量;position表示开始位置;length表示要提取子串的长度。
getFreeMemory() {
while read line
do
[[ "${line:0:8}" == "MemFree:" ]] && memfree=`echo $line | sed 's/[^0-9,. ]//g'` && continue
[[ "${line:0:8}" == "Buffers:" ]] && buffers=`echo $line | sed 's/[^0-9,. ]//g'` && continue
[[ "${line:0:7}" == "Cached:" ]] && cached=`echo $line | sed 's/[^0-9,. ]//g'` && break
done <"/proc/meminfo"
let "totalFree = $memfree + $buffers + $cached"
echo "TotalFree:"$totalFree"kB"
}
#循环获取对应进程的信息
while true; do
#用procName循环和procNameArray数组比较,看是否有对应的进程
for procName in ${procNameArray[@]}
do
echo ""
getProcId #获取对应的ID
for ProcId in ${ProcIdArray[@]}
do
getProcInfo #打印对应ID的信息
done
done
echo "Elastos Memory: "$elastosMemmory"KB"
elastosMemmory=0
getFreeMemory
let "count = $count + 1"
echo $count
echo "----------------------------------\n"
sleep $rate #沉睡多少秒后再循环
done