设为首页 收藏本站
查看: 744|回复: 0

[经验分享] 编程实现获取linux服务器cpu、内存和磁盘使用率

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2014-7-2 10:09:18 | 显示全部楼层 |阅读模式
proc文件系统介绍

/proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为内核与进程提供通信的接口。用户和应用程序可以通过/proc得到系统的信息,并可以改变内核的某些参数。由于系统的信息,如进程,是动态改变的,所以用户或应用程序读取/proc目录中的文件时,proc文件系统是动态从系统内核读出所需信息并提交的。
/proc目录中有一些以数字命名的目录,它们是进程目录。系统中当前运行的每一个进程在/proc下都对应一个以进程号为目录名的目录/proc/pid,它们是读取进程信息的接口。此外,在Linux 2.6.0-test6以上的版本中/proc/pid目录中有一个task目录,/proc/pid/task目录中也有一些以该进程所拥有的线程的线程号命名的目录/proc/pid/task/tid,它们是读取线程信息的接口。

CPU使用率

要想计算CPU使用率,首先要了解文件/proc/stat中的内容,如下是本人所使用服务器中该文件中的内容:


CPU 以及CPU0、CPU1、CPU2、CPU3、CPU4中每行的每个参数意思(以第一行为例)解释:
user (28201) :从系统启动开始累计到当前时刻,用户态的CPU时间(单位:jiffies) ,不包含 nice值为负进程。1jiffies=0.01秒
nice (389) :从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间(单位:jiffies)
system (10975) :从系统启动开始累计到当前时刻,核心时间(单位:jiffies)
idle (6552431) :从系统启动开始累计到当前时刻,除硬盘IO等待时间以外其它等待时间(单位:jiffies)
iowait (19704) :从系统启动开始累计到当前时刻,硬盘IO等待时间(单位:jiffies) ,
irq (0) :从系统启动开始累计到当前时刻,硬中断时间(单位:jiffies)
softirq (208): 从系统启动开始累计到当前时刻,软中断时间(单位:jiffies)

获取cpu使用率的方法:

    1、记录某个时刻cpu的使用情况

    2、等上一个时间段

    3、再记录此刻的cpu使用情况

    4、计算总的时间片

    把第一次的所有cpu使用情况求和,得到j1,把第二次的所有cpu使用情况求和,得到j2,则j2-j1得到这个时间段的所有时间片。即total=j2-j1=第二次的所有列的和-第一次的所有列的和

    5、计算idle时间

    idle对应第五列的数据,用第二次的减去第一次的即可,idle=第二次的第五列-第一次的第五列

    6、计算cpu使用率

    ate=(total-idle)/total

在代码里实现如下所示:



    SysCPUInfo*   
    _GetHostCPUInfo()  
    {  
        SysCPUInfo *cpuinfo = (SysCPUInfo *)malloc(sizeof(SysCPUInfo));  
        if (cpuinfo == NULL)  
          err_dump("_GetCPUInfo: malloc struct SysCPUInfo error");  
      
        FILE    *fd;  
        char    buff[256];  
        memset(buff, '\0', 256);  
      
        fd = fopen("/proc/stat", "r");  
        fgets(buff, sizeof(buff), fd);  
      
        sscanf(buff, "%s %lu %lu %lu %lu", cpuinfo->name, &cpuinfo->user, &cpuinfo->nic,   
                    &cpuinfo->system, &cpuinfo->idle);  
        fclose(fd);  
        return cpuinfo;  
    }  
      
    float  
    _CalculateHostCPURate(SysCPUInfo *first, SysCPUInfo *second)  
    {  
        unsigned long   old_CPU_Time, new_CPU_Time;  
        unsigned long   usr_Time_Diff, sys_Time_Diff, nic_Time_Diff;  
        float           cpu_use = 0.0;  
      
        old_CPU_Time = (unsigned long)(first->user + first->nic + first->system + first->idle);  
        new_CPU_Time = (unsigned long)(second->user + second->nic + second->system + second->idle);  
      
        usr_Time_Diff = (unsigned long)(second->user - first->user);  
        sys_Time_Diff = (unsigned long)(second->system - first->system);  
        nic_Time_Diff = (unsigned long)(second->nic -first->nic);  
      
        if ((new_CPU_Time - old_CPU_Time) != 0)  
          cpu_use = (float)100*(usr_Time_Diff + sys_Time_Diff + nic_Time_Diff)/(new_CPU_Time - old_CPU_Time);  
        else  
          cpu_use = 0.0;  
        return cpu_use;  
    }  
      
    float  
    GetHostCPURate()  
    {  
        float cpu_rate;  
        SysCPUInfo *first, *second;  
        first = _GetHostCPUInfo();  
        sleep(10);  
        second = _GetHostCPUInfo();  
      
        cpu_rate = _CalculateHostCPURate(first, second);  
      
        /* clean auxiliary memory */  
        free(first);  
        free(second);  
        first = second = NULL;  
      
        return cpu_rate;  
    }  

内存使用率

内存使用率的计算比较方便,可以直接调用Linux系统的一个库函数sysinfo(),该函数返回如下的一个结构体:



    struct sysinfo {  
                   long uptime;             /* Seconds since boot */  
                   unsigned long loads[3];  /* 1, 5, and 15 minute load averages */  
                   unsigned long totalram;  /* Total usable main memory size */  
                   unsigned long freeram;   /* Available memory size */  
                   unsigned long sharedram; /* Amount of shared memory */  
                   unsigned long bufferram; /* Memory used by buffers */  
                   unsigned long totalswap; /* Total swap space size */  
                   unsigned long freeswap;  /* swap space still available */  
                   unsigned short procs;    /* Number of current processes */  
                   unsigned long totalhigh; /* Total high memory size */  
                   unsigned long freehigh;  /* Available high memory size */  
                   unsigned int mem_unit;   /* Memory unit size in bytes */  
                   char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding for libc5 */  
               };  

该结构体中freeram表示可用内存的大小,totalram表示总内存大小。所以通过这两个值就可以计算内存使用率了。代码实现如下所示:



    SysMemInfo *  
    GetHostMemInfo()  
    {  
        SysMemInfo *memInfo = (SysMemInfo *)malloc(sizeof(SysMemInfo));  
        if (NULL == memInfo)  
          err_dump("GetMemInfo: malloc SysMemInfo Struct error");  
      
        struct sysinfo tmp;  
        int ret = 0;  
        ret = sysinfo(&tmp);  
        if (ret == 0) {  
            memInfo->MemFree = (unsigned long)tmp.freeram/(1024*1024);  
            memInfo->MemTotal = (unsigned long)tmp.totalram/(1024*1024);  
        } else {  
            err_dump("GetMemInfo: sysinfo() error");  
        }  
        return memInfo;  
    }  

磁盘利用率

本来打算通过读文件/proc/partitions来获取磁盘分区的使用情况,不过这样只可以获取分区的大小,使用情况是无法获取的。不过可以通过读取文件/etc/mtab来读取系统中所有文件系统的信息。然后统计所有文件系统占用的磁盘总大小和可以磁盘的总大小,这样就可以计算出系统中文件系统的总磁盘利用率。代码实现如下所示:


    SysDiskInfo *  
    GetHostDiskInfo()  
    {  
        SysDiskInfo *sys_disk_info = (SysDiskInfo *)malloc(sizeof(SysDiskInfo));  
        DiskInfo        *disk_info;  
        struct statfs   fs_info;  
        struct mntent   *mnt_info;  
        FILE            *fh;  
        float           percent;  
        unsigned long   sum_Total = 0, total_free = 0;  
      
        if ((fh = setmntent("/etc/mtab", "r")) == NULL) {  
            printf("Cannot open /etc/mtab file!:%s\n",strerror(errno));  
            return NULL;  
        }  
      
        while ((mnt_info = getmntent(fh)) != NULL) {  
            if (statfs(mnt_info->mnt_dir, &fs_info) < 0) {  
                continue;  
            }  
              
            if ((disk_info = (DiskInfo *)malloc(sizeof(DiskInfo))) == NULL) {  
                continue;  
            }  
      
            if (strcmp(mnt_info->mnt_type, "proc") &&  
                strcmp(mnt_info->mnt_type, "devfs") &&  
                strcmp(mnt_info->mnt_type, "usbfs") &&  
                strcmp(mnt_info->mnt_type, "sysfs") &&  
                strcmp(mnt_info->mnt_type, "tmpfs") &&  
                strcmp(mnt_info->mnt_type, "devpts") &&  
                strcmp(mnt_info->mnt_type, "fusectl") &&  
                strcmp(mnt_info->mnt_type, "debugfs") &&  
                strcmp(mnt_info->mnt_type, "binfmt_misc") &&  
                strcmp(mnt_info->mnt_type, "fuse.gvfs_fuse_daemon")&&  
                strcmp(mnt_info->mnt_type, "securityfs")) {  
                if (fs_info.f_blocks != 0) {  
                    percent = ((float)fs_info.f_blocks - (float)fs_info.f_bfree * 100.0/  
                                (float)fs_info.f_blocks);  
                } else {  
                    percent = 0;  
                }  
            } else {  
                continue;  
            }  
              
            strcpy(disk_info->type, mnt_info->mnt_type);  
            strcpy(disk_info->device, mnt_info->mnt_fsname);  
            strcpy(disk_info->mntpnt, mnt_info->mnt_dir);  
      
            unsigned long block_size = fs_info.f_bsize/1024;  
            disk_info->blocks = fs_info.f_blocks * block_size / 1024;  
            disk_info->bfree = fs_info.f_bfree * block_size / 1024;  
            disk_info->availiable_disk = fs_info.f_bavail * block_size / 1024;  
            disk_info->bused = (fs_info.f_blocks - fs_info.f_bfree) * block_size / 1024;  
            disk_info->bused_percent = percent;  
              
            sum_Total += disk_info->blocks;  
            total_free += disk_info->availiable_disk;  
      
            /* clean auxiliary memory */  
            free(disk_info);  
            disk_info = NULL;  
        }  
        sys_disk_info->Disk_Total = sum_Total/1024;  
        sys_disk_info->Disk_Free = total_free/1024;  
        return sys_disk_info;  
    }  







运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-21434-1-1.html 上篇帖子: QEMU-KVM创建虚拟机自动指定IP的配置 下篇帖子: 解决VTune错误.../lib64/libstdc++.so.6: version `GLIBCXX_3.4.14' not found... 服务器 linux
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表