Android性能监控小工具

6 篇文章 0 订阅

//编译方法如下:

//d:\android-ndk-r8e-windows-x86\android-ndk-r8e为Android NDK根目录

cd d:\android-ndk-r8e-windows-x86\android-ndk-r8e\toolchains\arm-linux-androideabi-4.6\prebuilt\windows\bin\

arm-linux-androideabi-g++.exe -fPIE -pie -fpermissive --sysroot=d:\android-ndk-r8e-windows-x86\android-ndk-r8e\platforms\android-9\arch-arm\ -I d:\android-ndk-r8e-windows-x86\android-ndk-r8e\sources\cxx-stl\stlport\stlport\ -l d:\android-ndk-r8e-windows-x86\android-ndk-r8e\sources\cxx-stl\stlport\libs\armeabi-v7a\libstlport_shared.so e:\itrans\osres_mon_android.cpp -o e:\itrans\osres_mon_android 1>stdout 2>&1

//简略为:g++ -fPIE -pie --sysroot="" -I"\stlport" -l"libstlport_shared.so" osres_mon_android.cpp -o osres_mon_android

//运行方法:

//需依赖libstlport_shared.so共享库,确保该共享库位于链接路径中

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <fcntl.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>

#include <vector>
#include <string>

// 更新周期,单位微妙,即1秒
#define UPDATE_PERIOD 1000000
#define CALC_FACTOR (1E8/UPDATE_PERIOD)

static char *nexttoksep(char **strp, char *sep)  
{  
    char *p = strsep(strp,sep);  
    return (p == 0) ? "" : p;  
}  
static char *nexttok(char **strp)  
{  
    return nexttoksep(strp, " ");  
}  
static int ps_line(int pid, unsigned int& ret_vsize, unsigned int& ret_rss)  
{  
    char statline[1024];  
    char user[32];  
    struct stat stats;  
    int fd, r;  
    char *ptr, *name, *state;  
    int ppid, tty;  
    unsigned wchan, rss, vss, eip;  
    unsigned utime, stime;  
    int prio, nice, rtprio, sched;  
    struct passwd *pw;  

    sprintf(statline, "/proc/%d", pid);  
    stat(statline, &stats);  

    sprintf(statline, "/proc/%d/stat", pid);
    fd = open(statline, O_RDONLY);  
    if(fd == 0) return -1;  
    r = read(fd, statline, 1023);  
    close(fd);  
    if(r < 0) return -1;  
    statline[r] = 0;  

    ptr = statline;  
    nexttok(&ptr); // skip pid  
    ptr++;          // skip "("  

    name = ptr;  
    ptr = strrchr(ptr, ')'); // Skip to *last* occurence of ')',  
    *ptr++ = '\0';           // and null-terminate name.  

    ptr++;          // skip " "  
    state = nexttok(&ptr);  
    ppid = atoi(nexttok(&ptr));  
    nexttok(&ptr); // pgrp  
    nexttok(&ptr); // sid  
    tty = atoi(nexttok(&ptr));  

    nexttok(&ptr); // tpgid  
    nexttok(&ptr); // flags  
    nexttok(&ptr); // minflt  
    nexttok(&ptr); // cminflt  
    nexttok(&ptr); // majflt  
    nexttok(&ptr); // cmajflt  
#if 1  
    utime = atoi(nexttok(&ptr));  
    stime = atoi(nexttok(&ptr));  
#else  
    nexttok(&ptr); // utime  
    nexttok(&ptr); // stime  
#endif  
    nexttok(&ptr); // cutime  
    nexttok(&ptr); // cstime  
    prio = atoi(nexttok(&ptr));  
    nice = atoi(nexttok(&ptr));  
    nexttok(&ptr); // threads  
    nexttok(&ptr); // itrealvalue  
    nexttok(&ptr); // starttime  
    vss = strtoul(nexttok(&ptr), 0, 10); // vsize  
    rss = strtoul(nexttok(&ptr), 0, 10); // rss  
    nexttok(&ptr); // rlim  
    nexttok(&ptr); // startcode  
    nexttok(&ptr); // endcode  
    nexttok(&ptr); // startstack  
    nexttok(&ptr); // kstkesp  
    eip = strtoul(nexttok(&ptr), 0, 10); // kstkeip  
    nexttok(&ptr); // signal  
    nexttok(&ptr); // blocked  
    nexttok(&ptr); // sigignore  
    nexttok(&ptr); // sigcatch  
    wchan = strtoul(nexttok(&ptr), 0, 10); // wchan  
    nexttok(&ptr); // nswap  
    nexttok(&ptr); // cnswap  
    nexttok(&ptr); // exit signal  
    nexttok(&ptr); // processor  
    rtprio = atoi(nexttok(&ptr)); // rt_priority  
    sched = atoi(nexttok(&ptr)); // scheduling policy  
    tty = atoi(nexttok(&ptr));  


    //pw = getpwuid(stats.st_uid);  
    //if(pw == 0) {  
    //    sprintf(user,"%d",(int)stats.st_uid);  
    //} else {  
    //    strcpy(user,pw->pw_name);  
    //}  

    ret_vsize = vss / 1024;
    ret_rss = rss * 4;
    return 0;
}  


unsigned long get_pid_from_cmd(char* cmd_name)
{
    int pid = -1;
    DIR *d;
    struct dirent *de;
    char cmdline[1024];
    int fd,r,tmp_pid;

    // 打开文件夹/proc
    d = opendir("/proc");
    if(d == 0) return -1;
    // 遍历/proc下的子文件夹
    while((de = readdir(d)) != 0){
        if(isdigit(de->d_name[0])){
            // 如果文件夹名中含有数字,则可能是某个进程
            tmp_pid = atoi(de->d_name);
            sprintf(cmdline, "/proc/%d/cmdline", tmp_pid);
            // 打开文件/proc/'tmp_pid'/cmdline
            fd = open(cmdline, O_RDONLY);  
            if(fd == 0) {
                r = 0;
            } else {
                // 读取文件/proc/'tmp_pid'/cmdline
                r = read(fd, cmdline, 1023);
                close(fd);
            }
            cmdline[r] = 0;
            // cmdline长度不为零,且cmd_name为其子串
            if (0 != strlen(cmdline) && NULL != strstr(cmdline, cmd_name))
            {
                pid = tmp_pid;
                break;
            }
        }
    }
    closedir(d);
}


// 字符串分割
void SplitString(const std::string& s, std::vector<std::string>& v, const std::string& c)
{
    std::string::size_type pos1, pos2;
    pos2 = s.find(c);
    pos1 = 0;
    while(std::string::npos != pos2)
    {
        v.push_back(s.substr(pos1, pos2-pos1));

        pos1 = pos2 + c.size();
        pos2 = s.find(c, pos1);
    }
    if(pos1 != s.length())
        v.push_back(s.substr(pos1));
}
static unsigned long getTotalCpuTime()
{
    // 获取系统总CPU使用时间
    char fileline[1024]={0};
    char content[1024]={0};
    int fd,r;
    sprintf(fileline, "/proc/stat");
    // 打开文件/proc/stat
    fd = open(fileline, O_RDONLY);  
    if(fd == 0) {
        r = 0;
    } else {
        // 读取文件/proc/stat到content
        r = read(fd, content, 1024 - 1);
        close(fd);
    }
    content[r] = 0;
    // 对content进行分割
    std::vector<std::string> cpuInfos;
    SplitString(content, cpuInfos, " ");
    if (cpuInfos.size() >= 9) {
        unsigned long totalCpuTime = atol(cpuInfos[2].c_str())
            + atol(cpuInfos[3].c_str()) + atol(cpuInfos[4].c_str())
            + atol(cpuInfos[6].c_str()) + atol(cpuInfos[5].c_str())
            + atol(cpuInfos[7].c_str()) + atol(cpuInfos[8].c_str());
        return totalCpuTime;
    }else{
        return 0;
    }
}
static unsigned long getAppCpuTime(int pid)
{
    // 获取应用占用的CPU时间
    char fileline[1024]={0};
    char content[1024]={0};
    int fd,r;
    sprintf(fileline, "/proc/%d/stat", pid);
    // 打开文件/proc/pid/stat
    fd = open(fileline, O_RDONLY);  
    if(fd == 0) {
        r = 0;
    } else {
        // 读取文件/proc/pid/stat到content
        r = read(fd, content, 1024 - 1);
        close(fd);
    }
    content[r] = 0;
    // 对content进行分割
    std::vector<std::string> cpuInfos;
    SplitString(content, cpuInfos, " ");
    if (cpuInfos.size() >= 17) {
        unsigned long appCpuTime = atol(cpuInfos[13].c_str())
            + atol(cpuInfos[14].c_str()) + atol(cpuInfos[15].c_str())
            + atol(cpuInfos[16].c_str());
        return appCpuTime;
    }else{
        return 0;
    }
}

static float getProcessCpuRate(int pid)
{

    unsigned long totalCpuTime1 = getTotalCpuTime();
    unsigned long processCpuTime1 = getAppCpuTime(pid);

    usleep(UPDATE_PERIOD);

    unsigned long totalCpuTime2 = getTotalCpuTime();
    unsigned long processCpuTime2 = getAppCpuTime(pid);

    if(!totalCpuTime1 || !processCpuTime1 || !totalCpuTime2 || !processCpuTime2)
        return 0.0f;

    float cpuRate = 100 * (processCpuTime2 - processCpuTime1)
        / (totalCpuTime2 - totalCpuTime1);

    return cpuRate;
}

int main(int argc, char * argv[])
{
    char cmd[100] = "itranscon";
    unsigned long pid = -1;
    unsigned int vsize = 0;
    unsigned int rss = 0;
    float cpu_rate = 0.0f;
    time_t t;
    if (argc < 2)
    {
        printf("Usage: osres_mon command\n");
        printf("Monitoring default process:itranscon!\n");
    }else
    {
        strcpy(cmd,argv[1]);
    }


    pid =  get_pid_from_cmd(cmd);
    if (pid == -1)
    {
        printf("Not find pid named %s\n",cmd);
        return -1;
    }

    FILE* flog = NULL;
    flog = fopen("osres_mon.log", "w+");
    if(!flog) {
        printf("open log file failed!\n");
    }


    printf("PID COMMAND VSIZE RSS CPU_RATE TIME\n");
    if (flog) {
        fprintf(flog, "PID COMMAND VSIZE RSS CPU_RATE TIME\n");
        fflush(flog);
    }

    //PID 进程ID
    //COMMAND 进程名称
    //VSIZE 进程的虚拟内存大小,以KB为单位
    //RSS 进程实际占用的内存大小,以KB为单位
    //CPU_RATE 进程的CPU使用率
    while (true)
    {
        if (0 != ps_line(pid, vsize, rss)) {
            printf("ps_line() error!\n");
            return -1;
        }
        cpu_rate = getProcessCpuRate(pid);
        t = time(NULL);
        printf("%d\t%s\t%d\t%d\t%.3f%%\t%s\t",
            pid,
            cmd,
            vsize,
            rss,
            cpu_rate,
            asctime(localtime(&t)));
        if (flog) {
            fprintf(flog, "%d\t%s\t%d\t%d\t%.3f%%\t%s\t",
            pid,
            cmd,
            vsize,
            rss,
            cpu_rate,
            asctime(localtime(&t)));
            fflush(flog);
        }
        // usleep <unistd.h> 单位:微秒(us)(百万分之一秒)
        usleep(UPDATE_PERIOD);
    }
    if (flog)
        fclose(flog);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值