前言 

  前段时间因为项目需求,需要实时获取系统当前的运行状态,遂查阅了不少资料,基于/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. gcc -c xx.c 选项讲解

    -c选项表示编译.汇编指定的源文件(也就是编译源文件),但是不进行链接.使用-c选项可以将每一个源文件编译成对应的目标文件. 目标文件是一种中间文件或者临时文件,如果不设置该选项,gcc 一般不会保留 ...

  2. CodeForces - 697B

    这道题看见就觉得是道水题,想着随便写写就能A了,然后就开始上手直接模拟,然后就被数据打脸了. 后面就困了一个多小时,各种改,最后还是看了题解发现了scanf的多种用法. 题目大概意思就是说: 给一个  ...

  3. DispatcherServlet和ContextLoaderListener,还有spring+servlet3.0 无web.xml启动问题

    上篇提到: 关于spring +springmvc中两个spring应用上下文(DispatcherServlet和ContextLoaderListener)的问题,挺让人迷糊的. 他们都是加载Be ...

  4. screen模式下鼠标无法滚动【问题】

    忍了很久, 终于查到原因了. 回滚模式: CTRL+A (释放), [ 切换模式: CTRL+ C 参考: https://serverfault.com/questions/206303/how-t ...

  5. memory barrier 内存栅栏 并发编程

    并发编程 memory barrier (内存栅栏) CPU级 1.CPU中有多条流水线,执行代码时,会并行进行执行代码,所以CPU需要把程序指令 分配给每个流水线去分别执行,这个就是乱序执行: 2. ...

  6. iOS 类似外卖 两个tableView联动

    在伯乐在线上看到一个挺好玩的文章,自己也参考文章实现了一下. 效果实现如图所示: 具体实现的内容可以参考原文,参考文章:<iOS 类似美团外卖 app 两个 tableView 联动效果实现&g ...

  7. druid yml

    application-db.yml pagehelper: helperDialect: mysql reasonable: true supportMethodsArguments: true p ...

  8. day34-进程

    #进程是程序的运行,程序不运行不产生进程. #1.进程的并行与并发: # 并行:是指两者同时执行,比如赛跑,两人都在不停的往前跑.(资源够用,比如三个线程,四核的cpu) # 并发:是指资源有限的情况 ...

  9. day23-logging模块

    # logging日志记录的两个内容:1.有5种级别的日志记录模式.2.两种配置方式:basicconfig.logger对象. # logging的作用: #1.排错的时候需要打印很多细节来帮助排错 ...

  10. 2017Google开发者大会

    2017年12月14日有幸去上海跨国采购中心参加了2017Google开发者大会,这个大会有很多很有意思的展会以及技术分享.主题涵盖 Android.移动网络.Firebase.机器学习.云服务.AR ...