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; }
编程实现获取linux服务器cpu、内存和磁盘使用率