• 计算进程消费cpu和内存


    Linux下没有直接可以调用系统函数知道CPU占用和内存占用。那么如何知道CPU和内存信息呢。只有通过proc伪文件系统来实现。

    proc伪文件就不介绍了,只说其中4个文件。一个是/proc/stat,/proc/meminfo,/proc/<pid>/status,/proc/<pid>/stat

    proc/stat:存放系统的CPU时间信息

    该文件包含了所有CPU活动的信息,该文件中的所有值都是从系统启动开始累计到当前时刻。不同内核版本中该文件的格式可能不大一致,以下通过实例来说明数据该文件中各字段的含义。

    实例数据:2.6.24-24版本上的

    fjzag@fjzag-desktop:~$ cat /proc/stat

    cpu 38082 627 27594 893908 12256 581 895 0 0

    cpu0 22880 472 16855 430287 10617 576 661 0 0

    cpu1 15202 154 10739 463620 1639 4 234 0 0

    intr 120053 222 2686 0 1 1 0 5 0 3 0 0 0 47302 0 0 34194 29775 0 5019 845 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

    ctxt 1434984

    btime 1252028243

    processes 8113

    procs_running 1

    procs_blocked 0

    第一行的数值表示的是CPU总的使用情况,所以我们只要用第一行的数字计算就可以了。下表解析第一行各数值的含义:

    参数 解析(单位:jiffies)

    (jiffies是内核中的一个全局变量,用来记录自系统启动一来产生的节拍数,在linux中,一个节拍大致可理解为操作系统进程调度的最小时间片,不同linux内核可能值有不同,通常在1ms到10ms之间)

    user (38082) 从系统启动开始累计到当前时刻,处于用户态的运行时间,不包含 nice值为负进程。

    nice (627) 从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间

    system (27594) 从系统启动开始累计到当前时刻,处于核心态的运行时间

    idle (893908) 从系统启动开始累计到当前时刻,除IO等待时间以外的其它等待时间iowait (12256) 从系统启动开始累计到当前时刻,IO等待时间(since 2.5.41)

    irq (581) 从系统启动开始累计到当前时刻,硬中断时间(since 2.6.0-test4)

    softirq (895) 从系统启动开始累计到当前时刻,软中断时间(since 2.6.0-test4)stealstolen(0) which is the time spent in other operating systems when running in a virtualized environment(since 2.6.11)

    guest(0) which is the time spent running a virtual CPU for guest operating systems under the control of the Linux kernel(since 2.6.24)

    结论2:总的cpu时间totalCpuTime = user + nice + system + idle + iowait + irq + softirq + stealstolen + guest

    可以利用scanf,sscanf,fscanf读取这些信息,具体可以查man proc.我的程序中只取了前4个。

    /proc/meminfo:存放系统的内存信息

    [ubuntu@root ~]#cat /proc/meminfo
    MemTotal:        2061616 kB
    MemFree:         1093608 kB
    Buffers:          151140 kB
    Cached:           479372 kB
    SwapCached:            0 kB
    Active:           516964 kB
    Inactive:         374672 kB
    Active(anon):     261412 kB
    Inactive(anon):     5604 kB
    Active(file):     255552 kB
    Inactive(file):   369068 kB

    ……

    别的就不说了,主要看第一个MemTotal,系统总的物理内存,它比真实的物理内存要小一点

    /proc/<pid>/status:存放进程的CPU时间信息以及一些综合信息

    [ubuntu@root ~]#cat /proc/889/status
    Name:    Xorg
    State:    S (sleeping)
    Tgid:    889
    Pid:    889
    PPid:    881
    TracerPid:    0
    Uid:    0    0    0    0
    Gid:    0    0    0    0
    FDSize:    256
    Groups:   
    VmPeak:       99036 kB
    VmSize:       52424 kB
    VmLck:           0 kB
    VmHWM:       57004 kB
    VmRSS:       45508 kB
    VmData:       35668 kB
    VmStk:         136 kB
    VmExe:        1660 kB
    VmLib:        6848 kB
    VmPTE:         120 kB
    VmPeak是占用虚拟内存的峰值,也就是最高的一个值,而且是虚拟内存,所以有时候会比物理内存要大。PS和TOP指令都是利用VmPeak计算内存占用的。

    VmRSS是进程所占用的实际物理内存。

    /proc/<pid>/stat:保存着进程的CPU信息。

    [ubuntu@root ~]#cat /proc/889/stat
    889 (Xorg) S 881 889 889 1031 889 4202752 5307477 0 0 0 34943 12605 0 0 20 0 1 0 8146 89399296 11377 4294967295 134512640 136211844 3221201472 3221200460 5456930 0 0 3149824 1367369423 3223423286 0 0 17 0 0 0 0 0 0

    pid=889 进程号

    utime=34943 该任务在用户态运行的时间,单位为jiffies

    stime=12605 该任务在核心态运行的时间,单位为jiffies

    cutime=0 所有已死线程在用户态运行的时间,单位为jiffies

    cstime=0 所有已死在核心态运行的时间,单位为jiffies

    可以利用scanf,sscanf,fscanf读取这些信息,具体可以查man proc.

    结论3:进程的总Cpu时间processCpuTime = utime + stime + cutime + cstime,该值包括其所有线程的cpu时间。

    下面粘贴一下本人写的调用接口

    //get_cpu.h
    
    #ifndef __GET_CPU__
    #define __GET_CPU__
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <iostream>
    #include <unistd.h>
    #include <assert.h>
    #include <algorithm>
    #include <vector>
    #define PROCESS_ITEM 14
    
    typedef struct
    {
        pid_t pid;
        unsigned int utime;   //live thread at user status  (jiffies)
        unsigned int stime;   //live thread at kernel status
        unsigned int cutime;  //killed thread at user status
        unsigned int cstime;  //killed thread at kernel status
    }process_cpu_occupy;
    
    vector<unsigned int>total_cpu_time;
    
    unsigned int get_cpu_process_occupy(const pid_t p);
    const char* get_items(const char* buffer,int ie);
    
    extern float get_cpu(pid_t p);
    extern unsigned int get_total_cpu();
    
    #endif
    //get_cpu.cc
    
    #include "get_cpu.h"
    const char* get_items(const char* buffer,int ie)
    {
        assert(buffer);
        char* p = buffer;
        int len = strlen(buffer);
        int count = 0;
        int i;
    
        if (1 == ie || ie < 1)
        {
            return p;
        }
    
        for (i=0; i<len; i++)
        {
            if (' ' == *p)
            {
                count++;
                if (count == ie-1)
                {
                    p++;
                    break;
                }
            }
            p++;
        }
    
        return p;
    }
    unsigned int get_cpu_process_occupy(const pid_t p)
    {
        char file[64] = {0};
        process_cpu_occupy t;
        FILE *fd;
        char line_buff[1024] = {0};
    
        sprintf(file,"/proc/%d/stat",p);
    
        fd = fopen (file, "r");
        fgets (line_buff, sizeof(line_buff), fd);
        sscanf(line_buff,"%u",&t.pid);
        char* q = get_items(line_buff,PROCESS_ITEM);
        sscanf(q,"%u %u %u %u",&t.utime,&t.stime,&t.cutime,&t.cstime);
    
        fclose(fd);
        return (t.utime + t.stime + t.cutime + t.cstime);
    }
    unsigned int get_cpu(pid_t p,int index)
    {
        unsigned int procputime;
    
        procputime = get_cpu_process_occupy(p);
        std::cout<<"procputime :"<<procputime<<endl;
    
        switch(index){
            case 1:
                total_cpu_time.clear();
                total_cpu_time.push_back(procputime);
                break;
            case 2:
                total_cpu_time.push_back(procputime);
                break;
            case 3:
                total_cpu_time.push_back(procputime);
                break;
            default:
                DSTREAM_WARN("index is errno");
                break;
        }
        return procputime;
    }
    unsigned int get_total_cpu(){
        int length=total_cpu_time.size();
        unsigned int total_time=0;
        if(length != 3){
            DSTREAM_WARN("get total cpu failed");
            return -1;
        }
        for(int i=0;i<length;i++){
            total_time+=total_cpu_time[i];
        }
        return total_time;
    }
    #ifndef __GET_MEM__
    #define __GET_MEM__
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <iostream>
    #include <unistd.h>
    #include <assert.h>
    #include <algorithm>
    #include <vector>
    #define VMRSS_LINE 15  //VMRSS line
    
    vector<int>total_memory;
    
    int get_phy_mem(const pid_t p);
    
    extern int get_mem(pid_t p);
    extern int get_total_memory();
    extern int get_total_mem();
    
    #endif
    //get_mem.cc
    #include "get_mem.h"
    int get_phy_mem(const pid_t p)
    {
        char file[64] = {0};
    
        FILE *fd;
        char line_buff[256] = {0};
        sprintf(file,"/proc/%d/status",p);
    
        fd = fopen (file, "r");
        int i;
        char name[32];
        int vmrss;
        for (i=0;i<VMRSS_LINE-1;i++)
        {
            fgets (line_buff, sizeof(line_buff), fd);
        }
        fgets (line_buff, sizeof(line_buff), fd);
        sscanf (line_buff, "%s %d", name,&vmrss);
        fclose(fd);
        return vmrss;
    }
    
    int get_mem(pid_t p,int index)
    {
        int procmemory;
        promemory=get_phy_mem(p);
        switch(index){
        case 1:
            total_memory.clear();
            total_memory.push_back(promemory);
            break;
        case 2:
            total_memory.push_back(promemory);
            break;
    
        case 3:
            total_memory.push_back(promemory);
            break;
        default:
            DSTREAM_WARN("index is errno");
            break;
        }
        return promemory;
    }
    
    //importer+aggregater+exporter
    int get_total_memory(){
        int length=total_memory.size();
    
        int total_mem=0;
        if(length != 3){
            DSTREAM_WARN("get total cpu failed");
            return -1;
        }
    
        for(int i=0;i<length;i++){
            total_mem+=total_memory[i];
        }
        return total_mem;
    }
    
    
    //total memory
    int get_all_mem()
    {
        char* file = "/proc/meminfo";
    
        FILE *fd;
        char line_buff[256] = {0};
        fd = fopen (file, "r");
        int i;
        char name[32];
        int memtotal;
        fgets (line_buff, sizeof(line_buff), fd);
        sscanf (line_buff, "%s %d", name,&memtotal);
        fclose(fd);
        return memtotal;
    }
  • 相关阅读:
    Go中的interface学习
    Go中的命名规范
    Go中的结构体
    Go中的文件读写
    Go包管理工具dep
    SpringBoot中读取配置文件的几种方式
    Go标准库--net/http学习
    centos7通过yum安装docker
    scala之构造器详解
    解决!!-- krb5-libs.x86_64被卸载,yum不能使用,ssh不能连接
  • 原文地址:https://www.cnblogs.com/13224ACMer/p/6827507.html
Copyright © 2020-2023  润新知