• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆-159  評論-223  文章-30  trackbacks-0
            基本原理
               1)系統CPU使用率等于兩個時間點的CPU非空閑時間差除以CPU時間總量差得到的百分比,這兩者可從/proc/stat文件獲得。
               2)系統內存使用率等于系統物理內存消耗量除以系統物理內存總量(memtotal,以KB為單位)得到的百分比,這兩者可從/proc/meminfo文件獲得。
               3)進程CPU使用率等于進程CPU時間(pct,以jiffies為單位)除以進程運行時間(pt)得到的百分比,pct從/proc/pid/stat文件讀取utime和stime字段相加即得,pt等于系統運行時間(st,以秒為單位)減去進程啟動時間(pst,以jiffies為單位),st從/proc/uptime文件獲得,pst從/proc/pid/stat文件讀取starttime字段獲得。
               4)進程內存使用率等于進程駐留集大小(rss)除以系統物理內存總量(memtotal,以KB為單位)得到的百分比,rss從/proc/pid/stat讀取rss字段得到,以頁數為單位。

            代碼實現
               1)基本結構和接口定義在proc_stat.h頭文件內,如下所示
             1struct sys_cpu_time
             2{
             3    unsigned long long user,old_user;
             4    unsigned long long nice,old_nice;
             5    unsigned long long sys,old_sys;
             6    unsigned long long idle,old_idle;
             7    unsigned long long wait,old_wait;
             8    unsigned long long hirq,old_hirq;
             9    unsigned long long sirq,old_sirq;
            10}
            ;
            11
            12struct sys_uptime
            13{
            14    double uptime;
            15    double idle;
            16}
            ;
            17
            18struct sys_mem_info
            19{
            20    unsigned long main_total;
            21    unsigned long main_free;
            22    unsigned long main_used; 
            23    unsigned long main_buffers;
            24    unsigned long main_cached;
            25    unsigned long swap_total;
            26    unsigned long swap_free;
            27    unsigned long swap_used;
            28    unsigned long swap_cached;
            29}
            ;
            30
            31struct system_stat
            32{
            33    sys_cpu_time ct;
            34    sys_mem_info mi;
            35    sys_uptime   ut;
            36}
            ;
            37
            38struct process_stat
            39{
            40    char name[16];
            41    char state;
            42    int ppid;
            43    int pgrp;
            44    int session;
            45    int tty_nr;
            46    int tpgid;
            47    unsigned int flags;
            48    unsigned long minflt;
            49    unsigned long cminflt;
            50    unsigned long majflt;
            51    unsigned long cmajflt;
            52    unsigned long utime;
            53    unsigned long stime;
            54    long cutime;
            55    long cstime;
            56    long priority;
            57    long nice;
            58    long threads;
            59    long iterealvalue;
            60    unsigned long long starttime;
            61    unsigned long vsize;
            62    long rss;
            63}
            ;
            64
            65struct sys_mem_entry
            66{
            67    const char *name;
            68    unsigned long *val;
            69}
             ;
            70
            71static const int PROC_STAT    = 0x0001;
            72static const int PROC_MEM     = 0x0002;
            73static const int PROC_UPTIME = 0x0004;
            74static const int PROC_ALL       = PROC_STAT|PROC_MEM|PROC_UPTIME;
            75
            76bool get_system_stat(system_stat& ss,int flag);
            77
            78bool get_system_usage(float& cpu,float& mem);
            79
            80bool get_process_stat(pid_t id,process_stat& ps);
            81
            82bool get_process_usage(pid_t id,float& cpu,float& mem,unsigned long long& uptime);
               以上sys_cpu_time、sys_mem_info和process_stat結構只是從對應文件中選取了用于計算CPU和內存使用率必須的部分字段,如果需求擴展,可以在其后添加更多的字段;sys_mem_info中的main_used和swap_used是引申字段,它們并不對應于/proc/meminfo文件。

               2)實現在proc_stat.cpp文件內,如下所示
              1static const char* PROC_FILE_STAT    = "/proc/stat";
              2static const char* PROC_FILE_MEMINFO = "/proc/meminfo";
              3static const char* PROC_FILE_UPTIME  = "/proc/uptime";
              4
              5static int compare_sys_mem_entry(const void *a, const void *b)
              6{
              7    return strcmp(static_cast<const sys_mem_entry*>(a)->name,static_cast<const sys_mem_entry*>(b)->name);
              8}

              9
             10inline ssize_t file2str(const char* file,char* buf,size_t len,int* pfd=NULL)
             11{
             12    int fd = -1;
             13    if(pfd) fd = *pfd;
             14
             15    if(-1 == fd){
             16         fd=open(file,O_RDONLY,0);
             17        if(-1==fd) return -1;
             18        if(pfd) *pfd = fd;
             19    }
            else
             20        lseek(fd,0,SEEK_SET);
             21
             22    ssize_t ret = read(fd,buf,len-1);
             23    if(NULL==pfd) close(fd);
             24    if(ret <= 0return -1;
             25    buf[ret] = '\0';
             26
             27    return ret;
             28}

             29
             30bool get_system_stat(system_stat& ss,int flag)
             31{
             32    assert(flag&PROC_ALL);
             33
             34    char buf[2048];
             35    ssize_t ret;    
             36
             37    if(flag & PROC_STAT){
             38        static __thread int stat_id = -1;
             39        ret = file2str(PROC_FILE_STAT,buf,sizeof(buf),&stat_id);
             40        if (-1==ret) return false;
             41        sys_cpu_time* ct = &ss.ct;
             42        if(7!=sscanf(buf,"cpu %Lu %Lu %Lu %Lu %Lu %Lu %Lu",&ct->user,&ct->nice,&ct->sys,&ct->idle,
             43            &ct->wait,&ct->hirq,&ct->sirq))
             44            return false;
             45    }

             46
             47    if(flag & PROC_UPTIME){
             48        static __thread int uptime_id = -1;
             49        ret = file2str(PROC_FILE_UPTIME,buf,sizeof(buf),&uptime_id);
             50        if(-1==ret) return false;
             51        sys_uptime* ut = &ss.ut;
             52        if(2!=sscanf(buf,"%lf %lf",&ut->uptime,&ut->idle))
             53            return false;
             54    }

             55
             56    if(flag & PROC_MEM){
             57        static __thread int mem_id = -1;
             58        ret = file2str(PROC_FILE_MEMINFO,buf,sizeof(buf),&mem_id);
             59        if(-1==ret) return false;
             60
             61        sys_mem_info *mi = &ss.mi;
             62        const sys_mem_entry mem_table[] = {
             63            {"Buffers",      &mi->main_buffers}
             64            {"Cached",       &mi->main_cached}
             65            {"MemFree",      &mi->main_free},   
             66            {"MemTotal",     &mi->main_total},  
             67            {"SwapCached",   &mi->swap_cached},
             68            {"SwapFree",     &mi->swap_free},    
             69            {"SwapTotal",    &mi->swap_total}
             70        }
            ;
             71
             72        char *beg,*end = buf + ret;
             73        char *colon,*lf;
             74        sys_mem_entry key,*sme;
             75
             76        for(beg=buf;beg<end;beg=lf+1){
             77            colon = strchr(beg,':');
             78            if(!colon) break;
             79            *colon++ = '\0';
             80            lf = strchr(colon,'\n'); 
             81            if(!lf) break;
             82            key.name = beg;
             83            sme = (sys_mem_entry*)bsearch(&key,mem_table,NUM_ELEMENTS(mem_table),sizeof(sys_mem_entry),compare_sys_mem_entry);
             84            if(sme) *(sme->val) = ::strtoul(beg=colon,&colon,10);
             85        }

             86        mi->main_used = mi->main_total - mi->main_free;
             87        mi->swap_used = mi->swap_total - mi->swap_free;
             88    }

             89
             90    return true;
             91}

             92
             93bool get_system_usage(float& cpu,float& mem)
             94{
             95    static __thread system_stat ss = {0};
             96    if(!get_system_stat(ss,PROC_MEM|PROC_STAT))
             97        return false;
             98
             99    sys_cpu_time* ct = &ss.ct;
            100    long long user,nice,sys,idle,wait,hirq,sirq,sum;
            101    user = ct->user - ct->old_user;
            102    nice = ct->nice - ct->old_nice;
            103    sys  = ct->sys - ct->old_sys; 
            104    idle = ct->idle - ct->old_idle;
            105    if(idle<0) idle = 0;
            106    wait = ct->wait - ct->old_wait;
            107    hirq = ct->hirq - ct->old_hirq;
            108    sirq = ct->sirq - ct->old_sirq;
            109    ct->old_user = ct->user;
            110    ct->old_nice = ct->nice;
            111    ct->old_sys  = ct->sys;
            112    ct->old_idle = ct->idle;
            113    ct->old_wait = ct->wait;
            114    ct->old_hirq = ct->hirq;
            115    ct->old_sirq = ct->sirq;
            116
            117    sum = user + nice + sys + idle + wait + hirq + sirq;
            118    if(sum<1) sum = 1;
            119    cpu = 100.0*(sum - idle)/sum;
            120
            121    sys_mem_info* mi = &ss.mi;
            122    mem = 100.0*mi->main_used/mi->main_total;
            123
            124    return true;
            125}

            126
            127bool get_process_stat(pid_t id,process_stat& ps)
            128{
            129    char buf[1024],name[64];
            130
            131    sprintf(name,"/proc/%u/stat",id);
            132    ssize_t ret = file2str(name,buf,sizeof(buf));
            133    if(-1==ret) return false;
            134
            135    char* beg = strchr(buf,'(');
            136    if(!beg) return false;
            137
            138    char* end = strchr(++beg,')');
            139    if(!end) return false;
            140
            141    size_t num = end - beg; 
            142    if(num >= sizeof(name))
            143        num = sizeof(name) -1;
            144    memcpy(ps.name,beg,num);
            145    ps.name[num] = '\0';
            146
            147    return 22/*1+5+1+6+6+1+1+1*/ == sscanf(end+2,
            148        "%c "
            149        "%d %d %d %d %d "
            150        "%u "
            151        "%lu %lu %lu %lu %lu %lu "
            152        "%ld %ld %ld %ld %ld %ld "
            153        "%Lu "
            154        "%lu "
            155        "%ld",
            156        &ps.state, //1
            157        &ps.ppid,&ps.pgrp,&ps.session,&ps.tty_nr,&ps.tpgid, //5
            158        &ps.flags,//1
            159        &ps.minflt,&ps.cminflt,&ps.majflt,&ps.cmajflt,&ps.utime,&ps.stime,//6
            160        &ps.cutime,&ps.cstime,&ps.priority,&ps.nice,&ps.threads,&ps.iterealvalue, //6
            161        &ps.starttime,//1
            162        &ps.vsize,//1
            163        &ps.rss); //1
            164}

            165
            166bool get_process_usage(pid_t id,float& cpu,float& mem,unsigned long long& uptime)
            167{
            168    system_stat ss;
            169    if(!get_system_stat(ss,PROC_MEM|PROC_UPTIME))
            170        return false;
            171
            172    process_stat ps;
            173    if(!get_process_stat(id,ps))
            174        return false;
            175
            176    long HZ = sysconf(_SC_CLK_TCK);
            177    unsigned long long pct = ps.utime+ps.stime;
            178    uptime = (unsigned long long)ss.ut.uptime - ps.starttime/HZ;
            179    cpu = uptime ? (100.0*pct/HZ)/uptime : 0.0;
            180
            181    long page_size = sysconf(_SC_PAGESIZE) >> 10;
            182    mem = 100.0*ps.rss*page_size/ss.mi.main_total;
            183
            184    return true;
            185}
               以上get_system_stat接口的實現中,sys_mem_entry數組mem_table中的元素對應于sys_mem_info中的字段,并按其名稱升序排列,便于二分查找。如果需求擴展改變了sys_mem_info結構的成員,只須調整mem_table,保證元素按字段名稱升序排列即可。

            性能優化
               如果頻繁調用get_xxx_usage來獲得資源使用信息,那么存在著不斷打開和關閉描述符操作,而在某些情況下沒必要,例如讀取一些系統proc文件如/proc/stat、/proc/meminfo和/proc/uptime等,只需第一次調用時打開,后續直接讀數據即可,這樣更高效。所以file2str的實現,支持一次打開,多次讀取,當進程退出時,系統內核會自動關閉所有描述符。
            posted on 2013-05-31 19:04 春秋十二月 閱讀(4956) 評論(0)  編輯 收藏 引用 所屬分類: System
            久久精品亚洲一区二区三区浴池| 狠狠色婷婷久久综合频道日韩| 久久精品国产清高在天天线| 久久精品人人槡人妻人人玩AV| 久久久久四虎国产精品| 欧美一级久久久久久久大| 久久99热这里只有精品国产| 99久久久精品免费观看国产| 久久人人爽人人精品视频| 国产成年无码久久久免费| 99久久人妻无码精品系列蜜桃| 欧美精品丝袜久久久中文字幕| 久久婷婷五月综合97色一本一本 | 久久影视国产亚洲| 狠狠色婷婷久久一区二区| 国产午夜精品久久久久九九电影| 欧美日韩精品久久久久| 伊人久久大香线焦综合四虎| 久久国语露脸国产精品电影| 精品国产热久久久福利| 精品蜜臀久久久久99网站| 久久久一本精品99久久精品88| 秋霞久久国产精品电影院| 精品久久久久久无码中文野结衣 | 超级97碰碰碰碰久久久久最新| 久久综合中文字幕| 久久精品国产亚洲精品2020| 久久中文字幕无码专区| 亚洲国产精品久久久久婷婷软件 | 国产99久久久国产精品小说| 久久久久久久99精品免费观看| 伊人久久大香线蕉综合Av| 久久久久亚洲av成人无码电影| 青青草原综合久久| 99久久成人国产精品免费| 色欲久久久天天天综合网精品| 国内精品伊人久久久影院| 亚洲国产精品一区二区三区久久| 日本高清无卡码一区二区久久| 久久久久国产一区二区三区| 久久夜色精品国产|