前言 

  前段时间因为项目需求,需要实时获取系统当前的运行状态,遂查阅了不少资料,基于/proc目录下的部分文件,实现了系统CPU、内存、网络和磁盘的实时监测。

一、CPU使用情况获取

  获取CPU使用情况是从/proc/stat文件中获取的,/proc/stat 包含了系统启动以来的许多关于kernel和系统的统计信息,其中包括CPU运行情况、中断统计、启动时间、上下文切换次数、运行中的进程等等信息

  

cpu  1149770 0 309685 239871041 7 0 0 0
cpu0 1149770 0 309685 239871041 7 0 0 0
intr 0
swap 0 0 ctxt 892809418
btime 1525518899
processes 379246
procs_running 1
procs_blocked 0

“cpu” 这行展示所有CPU在user-sapce、kernel mode上的一些时间,接着是各个CPU的统计情况。
“intr” 这行 展示系统中断的信息,第一个为自系统启动以来,发生的所有的中断的次数;然后每个数对应一个特定的中断自系统启动以来所发生的次数。
的中断自系统启动以来所发生的次数。
“ctxt” 这行展示自系统启动以来CPU发生的上下文交换的次数。
“btime”这行展示从系统启动到现在为止的时间(以Epoch时间开始计算, 1970-01-01 00:00:00 +0000 (UTC)),单位为秒。
 
“processes” 这行展示自系统启动以来所创建的任务的个数目(total_forks)。
“procs_running” 这行显示当前运行队列的任务的数目。
“procs_blocked” 这行显示当前被阻塞的任务的数目。

  计算CPU占用率的话,只需要关注第一行即可,各参数含义如下:

  

user

从系统启动开始累计到当前时刻,用户态的CPU时间,不包含nice值为负进程。

nice

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

system

从系统启动开始累计到当前时刻,核心时间

idle

从系统启动开始累计到当前时刻,除IO等待时间以外其它等待时间

iowait

从系统启动开始累计到当前时刻,IO等待时间

irq

从系统启动开始累计到当前时刻,硬中断时间

softirq

从系统启动开始累计到当前时刻,软中断时间

  因为/proc/stat中的数值都是从系统启动开始累计到当前时刻的积累值,所以需要在不同时间点t1和t2取值进行比较运算,当两个时间点的间隔较短时(我取的是1s),就可以把这个计算结果看作是CPU的即时利用率。

  CPU的即时利用率的计算公式:

  CPU在t1到t2时间段总的使用时间 = ( user2+ nice2+ system2+ idle2+ iowait2+ irq2+ softirq2) - ( user1+ nice1+ system1+ idle1+ iowait1+ irq1+ softirq1)

  CPU在t1到t2时间段空闲使用时间 = (idle2 - idle1)

  CPU在t1到t2时间段即时利用率 =  1 - CPU空闲使用时间 / CPU总的使用时间

  源码

void get_cpuinfo(CPU_PACKED &cpuinfo)
{
char buff[256] = {0};
ifstream in("/proc/stat");
if (!in)
{
cout << "get cpu info failed" << endl;
return;
} in.getline(buff, sizeof(buff));
stringstream ss(buff);
ss >> cpuinfo.name;
ss >> cpuinfo.user;
ss >> cpuinfo.nice;
ss >> cpuinfo.system;
ss >> cpuinfo.idle;
ss >> cpuinfo.iowait;
ss >> cpuinfo.irq;
ss >> cpuinfo.softirg; in.close();
}
double calc_cpuoccupy(CPU_PACKED cpuinfo1, CPU_PACKED cpuinfo2)
{
double info1d = cpuinfo1.user + cpuinfo1.nice + cpuinfo1.system + cpuinfo1.idle + cpuinfo1.softirg + cpuinfo1.iowait + cpuinfo1.irq;
double info2d = cpuinfo2.user + cpuinfo2.nice + cpuinfo2.system + cpuinfo2.idle + cpuinfo2.softirg + cpuinfo2.iowait + cpuinfo2.irq; double sub1 = cpuinfo1.idle;
double sub2 = cpuinfo2.idle;
double cpu_use; if ((sub1 - sub2) != 0)
cpu_use = 100.0 - ((sub2 - sub1) / (info2d - info1d)) * 100.0;
else
cpu_use = 0; //double cpu_use = cpuinfo1.user/info1d;
return cpu_use;
}

二、内存使用情况

  内存使用情况是从/proc/meminfo文件中获取的

[root ~]# cat /proc/meminfo
MemTotal: 1048576 kB
MemFree: 927940 kB
Cached: 31468 kB
Buffers: 0 kB
Active: 46764 kB
Inactive: 50516 kB
Active(anon): 32312 kB
Inactive(anon): 33500 kB
Active(file): 14452 kB
Inactive(file): 17016 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 131072 kB
SwapFree: 86620 kB
Dirty: 16 kB
Writeback: 0 kB
AnonPages: 65812 kB
Shmem: 164 kB
Slab: 23172 kB
SReclaimable: 6552 kB
SUnreclaim: 16620 kB

  这里关注的是MemTotal、MemFree和Cached三个值,使用中的内存 = MemTotal-MemFree-Cached

void calc_memoccupy(MEM_PACKED &meminfo)
{
char buff[256] = {0};
string name;
unsigned long free_mem;
unsigned long cached;
int index = 0;
ifstream in("/proc/meminfo");
if (!in)
{
cout << "get cpu info failed" << endl;
return;
} stringstream ss;
while (!in.eof() && index < 4)
{
in.getline(buff, sizeof(buff));
ss.str("");
ss << buff;
if (index == 0)
{
ss >> name;
ss >> meminfo.total_mem;
}
else if (index == 1)
{
ss >> name;
ss >> free_mem;
}
else if (index == 3)
{
ss >> name;
ss >> cached;
}
index++;
} meminfo.used_mem = meminfo.total_mem - free_mem - cached; in.close();
}

 三、网络传输(上传和下载的速度)

  网络使用情况是从/proc/net/dev文件中获取的

[root ~]# cat /proc/net/dev
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
lo: 4057260174 245081 0 0 0 0 0 0 4057260174 245081 0 0 0 0 0 0
venet0: 21610450920 22790055 0 0 0 0 0 0 22011662266 22005133 0 148 0 0 0 0

  网络上传和下载速度是根据网卡venet0单位时间(1s)内发收的字节数计算出来的

void read_netdev(unsigned long &ups, unsigned long &downs)
{
ifstream in("/proc/net/dev");
if (!in)
{
cout << "get network info failed" << endl;
return;
}
string line;
std::vector<string> lines;
while (!in.eof())
{
getline(in, line);
if (in.fail())
break;
lines.push_back(line);
}
vector<string> items = splitstring(lines[lines.size() - 1]);
ups = atol(items[1].c_str());
downs = atol(items[9].c_str()); in.close();
} void calc_netspeed(NET_PACKED &netinfo)
{
unsigned long ups1, ups2, downs1, downs2;
read_netdev(ups1, downs1);
sleep(1);
read_netdev(ups2, downs2); netinfo.upspeed = (float)(ups2 - ups1);
netinfo.downspeed = (float)(downs2 - downs1);
}

 四、硬盘使用情况

  硬盘使用情况分两部分:硬盘空间使用情况和硬盘实时的读写情况。

  硬盘的使用情况可以通过statfs()函数获取,读写速度是通过单位时间(1s)内读写的扇区个数来计算的

   [root ~]# cat /proc/diskstats
1 0 ram0 0 0 0 0 0 0 0 0 0 0 0
1 1 ram1 0 0 0 0 0 0 0 0 0 0 0
1 2 ram2 0 0 0 0 0 0 0 0 0 0 0
1 3 ram3 0 0 0 0 0 0 0 0 0 0 0
1 4 ram4 0 0 0 0 0 0 0 0 0 0 0
1 5 ram5 0 0 0 0 0 0 0 0 0 0 0
1 6 ram6 0 0 0 0 0 0 0 0 0 0 0
1 7 ram7 0 0 0 0 0 0 0 0 0 0 0
1 8 ram8 0 0 0 0 0 0 0 0 0 0 0
1 9 ram9 0 0 0 0 0 0 0 0 0 0 0
1 10 ram10 0 0 0 0 0 0 0 0 0 0 0
1 11 ram11 0 0 0 0 0 0 0 0 0 0 0
1 12 ram12 0 0 0 0 0 0 0 0 0 0 0
1 13 ram13 0 0 0 0 0 0 0 0 0 0 0
1 14 ram14 0 0 0 0 0 0 0 0 0 0 0
1 15 ram15 0 0 0 0 0 0 0 0 0 0 0
7 0 loop0 0 0 0 0 0 0 0 0 0 0 0
7 1 loop1 0 0 0 0 0 0 0 0 0 0 0
7 2 loop2 0 0 0 0 0 0 0 0 0 0 0
7 3 loop3 0 0 0 0 0 0 0 0 0 0 0
7 4 loop4 0 0 0 0 0 0 0 0 0 0 0
7 5 loop5 0 0 0 0 0 0 0 0 0 0 0
7 6 loop6 0 0 0 0 0 0 0 0 0 0 0
7 7 loop7 0 0 0 0 0 0 0 0 0 0 0
8 0 sda 30526 2009 1087215 193416 115412736 102258023 1811485376 87116184 0 18093240 87295592
8 1 sda1 22754 483028 5686677 45493256
8 2 sda2 166 662 8265 66120
8 3 sda3 6528 570989 123499806 987893792
8 4 sda4 2887 30896 88516083 708124240
9 0 md0 0 0 0 0 0 0 0 0 0 0 0

  

void calc_rwspeed(unsigned long &readsectors, unsigned long &writesectors)
{
ifstream in("/proc/diskstats");
if (!in)
{
cout << "get disk speed info failed with Reason:" << strerror(errno) << endl;
return;
}
string line;
while (!in.eof())
{
getline(in, line);
size_t pos = line.find("sda");
if (pos < line.size())
{
line = line.substr(pos + 4, line.size());
break;
}
} vector<string> items = splitstring(line);
readsectors = atol(items[2].c_str());
writesectors = atol(items[6].c_str()); in.close();
} void calc_diskoccupy(string path, DISK_PACKED &diskinfo)
{
struct statfs disk;
if (statfs(path.c_str(), &disk) == -1)
{
cout << "Failed to get disk info with Reason:" << strerror(errno) << endl;
return;
} diskinfo.total_disk = disk.f_blocks * disk.f_bsize;
diskinfo.avail_disk = disk.f_bavail * disk.f_bsize;
diskinfo.free_disk = disk.f_bfree * disk.f_bsize; unsigned long reads1, writes1, reads2, writes2;
calc_rwspeed(reads1, writes1);
sleep(1);
calc_rwspeed(reads2, writes2); diskinfo.read_speed = (reads2 - reads1) * disk.f_bsize;
diskinfo.write_speed = (writes2 - writes1) * disk.f_bsize;
}

  完整代码详见我的Gihub

添砖加瓦:Linux系统监测的更多相关文章

  1. linux:关于Linux系统中 CPU Memory IO Network的性能监测

    我们知道:系统优化是一项复杂.繁琐.长期的工作.通常监测的子系统有以下这些:CPUMemoryIO Network 下面是常用的监测工具 Linux 系统包括很多子系统(包括刚刚介绍的CPU,Memo ...

  2. shell脚本 Linux系统安全监测

    一.简介 源码地址 日期:2018/4/12 介绍:监测当前Linux系统的安全配置,并给出建议 效果图: 二.使用 适用:centos6+ 语言:中文 注意:无 下载 wget https://ra ...

  3. linux系统带宽监测脚本

    服务器可能经常遇到服务器出带宽跑满,不知如何查询被哪个进程占用的情况,有一款开源的英文软件iftop功能比较强大可以查询相关信息,可能刚接触linux系统的朋友不太会使用,在此写了一个功能比较简单无需 ...

  4. 监测linux系统负载与CPU、内存、硬盘、用户数的shell脚本

    本节主要内容: 利用Shell脚本来监控Linux系统的负载.CPU.内存.硬盘.用户登录数. 一.linux系统告警邮件脚本 # vim /scripts/sys-warning.sh #!/bin ...

  5. Linux 性能监测:工具

    一个完整运行的 Linux 系统包括很多子系统(介绍,CPU,Memory,IO,Network,-),监测和评估这些子系统是性能监测的一部分.我们往往需要宏观的看整个系统状态,也需要微观的看每个子系 ...

  6. Linux /dev目录详解和Linux系统各个目录的作用

    Linux /dev目录详解(转http://blog.csdn.net/maopig/article/details/7195048) 在linux下,/dev目录是很重要的,各种设备都在下面.下面 ...

  7. Linux系统下fd分配的方法

    最近几天在公司里写网络通讯的代码比较多,自然就会涉及到IO事件监测方法的问题.我惊奇的发现select轮训的方法在那里居然还大行其道.我告诉他们现在无论在Linux系统下,还是windows系统下,s ...

  8. linux性能监测与优化

    top命令命令功能top命令可以实时动态地查看系统的整体运行情况,是一个综合了多方信息的监测系统性能和运行信息的实用工具.命令语法top(选项)选项说明-b:以批处理模式操作;-d:屏幕刷新间隔时间. ...

  9. Linux就这个范儿 第16章 谁都可以从头再来--从头开始编译一套Linux系统 nsswitch.conf配置文件

    Linux就这个范儿 第16章 谁都可以从头再来--从头开始编译一套Linux系统  nsswitch.conf配置文件 朋友们,今天我对你们说,在此时此刻,我们虽然遭受种种困难和挫折,我仍然有一个梦 ...

随机推荐

  1. 3.docker machine 连接 aliyun 远程docker 服务器

    1.在aliyun ecs 创建docker 服务器 docker-machine create -d aliyunecs machine-aliyunecs 2.远程连接 docker 获取客户端 ...

  2. 剑指offer【11】- 矩形覆盖

    题目:我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形.请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? 在分析前不知道是什么序列,所以先看了n=1,n=2,n=3,n= ...

  3. intellij debug模式提示 Method breakpoints may dramatically slow down debugging

    之前不小心打了一个断点,然后项目长时间不能启动,保持一个加载的状态,并且提示Method breakpoints may dramatically slow down debugging,百度之后才知 ...

  4. jQuery篇

    jQuery 1.为什么使用jQuery? js中window onload事件只能出现一次,如果出现多次,后面的事件会覆盖掉前面的事件 js代码容错差 简单的动画效果实现很繁琐,例如简单的动画渐变效 ...

  5. vs strcore.cpp(156) 内存泄漏

    在一个静态函数的线程回调中,一个cstring的对象没释放. 遇到这种问题: 1.查看所有的指针对象,有没有合适的回收 2.查看代码的malloc,看看有没有free 3.一点一点注释代码,定位位置

  6. bzoj5104 Fib数列(BSGS+二次剩余)

    快AFO了才第一次写二次剩余的题…… 显然应该将Fn写成通项公式(具体是什么写起来不方便而且大家也都知道),设t=((1+√5)/2)n,T=√5N,然后可以得到t-(-1)t/t=√5N,两边同时乘 ...

  7. CentOS下图形界面安装_Orcaale 11g

    1.安装说明 使用到的工具: 软件名称 版本 软件包 系统 centOS6.8 CentOS-6.8-x86_64-bin-DVD1.iso 数据库 ORACLE11g linux.x64_11gR2 ...

  8. axios 模拟同步请求

    axios本身没有同步请求,但是我们很多情况下必须得需要同步请求.那么应该怎么做? 上网查了一些资料有人说用es6的 async +  assert 我不知道有没有效果,因为我的功能中是没啥效果的. ...

  9. python_8_集合

    1.集合:可变集合set,不可变集合frozenset,集合是无序不重复的 set('hello') set9[1,2,3,4]) set((1,2,3)) 2.添加元素 > add:将元素整体 ...

  10. F5中设置OA通过F5进行访问设置