您的位置:首页 > 其它

ubuntu 利用proc 文件系统实现监听器

2018-03-07 11:28 656 查看
proc文件系统特定文件的关系

获取并显示主机名/proc/sys/kernel/hostname
获取并显示系统时间/proc/uptime
当前内存使用情况/proc/meminfo
显示系统的版本号/proc/sys/kernel/ostype ,

           /proc/sys/kernel/osrelease
显示cpu信息/proc/cpuinfo
  
显示系统所有进程的一些信息,包括pid,ppid,占用内存大小,优先级等等/proc/(pid)/stat,

              /proc/(pid)/statm
cpu使用率的图形化显示(2分钟内的历史纪录曲线)/proc/stat
内存和交换分区(swap)使用率的图形化显示(2分钟内的历史纪录曲线)/proc/meminfo
  
在状态栏显示当前cpu使用率/proc/stat

2.获取CPU使用率

在/proc/stat文件里获取相关信息,再利用相关算法计算出利用率,直接上代码

float MainWindow::CPU_usage(){
FILE *fp;
char buf[128];
char cpu[5];
static long int static_all=0;
static long int static_idle=0;
long int user,nice,sys,idle,iowait,irq,softirq;

long int all1,idle1;
float usage;

fp = fopen("/proc/stat","r");
if(fp == NULL)
{
perror("fopen:");
exit (0);
}

fgets(buf,sizeof(buf),fp);
sscanf(buf,"%s%d%d%d%d%d%d%d",cpu,&user,&nice,&sys,&idle,&iowait,&irq,&softirq);
/*
#if __DEBUG__
printf("%s,%d,%d,%d,%d,%d,%d,%d\n",cpu,user,nice,sys,idle,iowait,irq,softirq);
#endif
*/
all1 = user+nice+sys+idle+iowait+irq+softirq;
idle1 = idle;

usage = (float)(all1-static_all-(idle1-static_idle)) / (all1-static_all)*100 ;

static_all=all1;
static_idle=idle1;

fclose(fp);
return usage;
}

3.获取内存利用率和swap利用率

MemInfoStruct MainWindow::Mem_usage(){
FILE *fp;
char buf[128];
char titlename[10];
char kb[3];
long int memtotal,memactive,SwapTotal,SwapFree;

MemInfoStruct str;
float usage,SwapUsage;

fp = fopen("/proc/meminfo","r");
if(fp == NULL)
{
perror("fopen:");
exit (0);
}
for(int i=0;i<16;i++){
fgets(buf,sizeof(buf),fp);
qDebug()<<buf<<"end";
if(i==0){   //get memtotal
sscanf(buf,"%s%ld%s",titlename,&memtotal,kb);

}

else if(i==6){   //get memactive
sscanf(buf,"%s%ld%s",titlename,&memactive,kb);

}
else if(i==14){   //get memactive
sscanf(buf,"%s%ld%s",titlename,&SwapTotal,kb);

}
else if(i==15){   //get memactive
sscanf(buf,"%s%ld%s",titlename,&SwapFree,kb);

}
}
usage=(float)memactive/memtotal*100;
SwapUsage=(float)(SwapTotal-SwapFree)/SwapTotal;
str.Mem_usage=usage;
str.swap_usage=SwapUsage;
return str;
}


以上函数中返回值是一个包含内存利用率和swap利用率的结构体

struct MemInfoStruct
{
float Mem_usage;
float swap_usage;
};

4.返回os信息

const QString MainWindow::ret_osinfo(){
FILE *fp;
fp = fopen("/proc/sys/kernel/ostype","r");
char buf_type[10],buf_release[20];
if(fp==NULL){
perror("fopen:");
exit(0);
}
fgets(buf_type,sizeof(buf_type),fp);
fclose(fp);
fp=fopen("/proc/sys/kernel/osrelease","r");
if(fp==NULL){
perror("fopen:");
exit(0);
}
fgets(buf_release,sizeof(buf_release),fp);
QString ret_str=QString("%1 %2").arg(buf_type,buf_release);
ret_str.replace("\n","");
return ret_str;
}

5.获取时间有关的信息

//activate Time&Run Time
QString myText =openFIleReturnString("/proc/uptime");
QString tempText=myText;
myText="activate Time:"+myText.remove(myText.indexOf(" ",0),10);
ui->activateTimelabel->setText(myText);
tempText="Run Time:"+tempText.remove(0,myText.indexOf(" ",0));
tempText=tempText.remove(tempText.size()-1,1);

ui->RunTimelabel->setText(tempText);

//current Time
QDateTime current_date_time =QDateTime::currentDateTime();
QString current_date =current_date_time.toString("yyyy.MM.dd hh:mm:ss.zzz ddd");
ui->CurrentTimelabel->setText(current_date);

2.获取进程相关信息和相关操作

1.获取/proc文件夹中的所以文件名以用于获取每一个进程文件

vector<string> ps::getFiles(string cate_dir)
{
vector<string> files;//存放文件名

DIR *dir;
struct dirent *ptr;
char base[1000];

if ((dir=opendir(cate_dir.c_str())) == NULL)
{
perror("Open dir error...");
exit(1);
}

while ((ptr=readdir(dir)) != NULL)
{
if(strcmp(ptr->d_name,".")==0 || strcmp(ptr->d_name,"..")==0)    ///current dir OR parrent dir
continue;
else if(ptr->d_type == 8)    ///file
//printf("d_name:%s/%s\n",basePath,ptr->d_name);
files.push_back(ptr->d_name);
else if(ptr->d_type == 10)    ///link file
//printf("d_name:%s/%s\n",basePath,ptr->d_name);
continue;
else if(ptr->d_type == 4)    ///dir
{
files.push_back(ptr->d_name);
}
}
closedir(dir);

//排序,按从小到大排序
sort(files.begin(), files.end());
return files;
}

2.依次打开获取的文件,把进程信息显示在tablewidget当中

void ps::timerUpdate(){
FILE *fp;
char name[25],scan_temp[25];

string basePath="/proc";
vector<string> files=getFiles(basePath);
//    for (int i=0; i<files.size(); i++)
//    {
//        cout<<files[i]<<endl;
//    }

//    cout<<"end..."<<endl<<endl;

//set rowCount of table widget
ui->tableWidget->setRowCount(files.size());
int rowcounter=0;

for(int i=0;i<files.size();i++){

int pid,priority,rss,ppid;
string temp="/proc/"+files[i]+"/stat";
fp=fopen(temp.data(),"r");
if(fp == NULL)   //when pros by kill
{
continue;
}
else rowcounter++;

if(rowcounter>rowcounter_old) {
ui->tableWidget->setRowCount(files.size());
rowcounter_old=files.size();
}

//        fgets(buf,sizeof(buf),fp);
//        qDebug()<<buf;
for(int j=0;j<25;j++){
if(j==0) fscanf(fp,"%d",&pid);
else if(j==1) fscanf(fp,"%s",name);
else if(j==3) fscanf(fp,"%d",&ppid);
else if(j==17) fscanf(fp,"%d",&priority);
//else if(j==23) fscanf(fp,"%d",&rss);
else fscanf(fp,"%s",scan_temp);
}
fclose(fp);
temp=temp+"m";
fp=fopen(temp.data(),"r");
if(fp == NULL)   //when pros by kill
{
continue;
}

fscanf(fp,"%s%d",scan_temp,&rss);
rss=rss*4;
fclose(fp);
//qDebug()<<name<<pid<<ppid<<priority<<rss;

//insert in listWidget
QTableWidgetItem *item = new QTableWidgetItem();
QTableWidgetItem *item1 = new QTableWidgetItem();
QTableWidgetItem *item2 = new QTableWidgetItem();
QTableWidgetItem *item3 = new QTableWidgetItem();
QTableWidgetItem *item4 = new QTableWidgetItem();
item->setText(QString(name).remove("(").remove(")"));

item1->setText(QString::number(pid,10));
item2->setText(QString::number(ppid,10));
item3->setText(QString::number(rss,10));
item4->setText(QString::number(priority,10));

ui->tableWidget->setItem(i, 0, item);
ui->tableWidget->setItem(i, 1, item1);
ui->tableWidget->setItem(i, 2, item2);
ui->tableWidget->setItem(i, 3, item3);
ui->tableWidget->setItem(i, 4, item4);

}
ui->tableWidget->setRowCount(rowcounter);
rowcounter_old=rowcounter;

}

每隔1s更新上面函数

3.选中tablewidget中的一行并杀死那一行所在的进程

void ps::clickedKillPushButton()
{
if(ui->tableWidget->selectedItems().isEmpty()) return;
QMessageBox::StandardButton rb = QMessageBox::question(NULL, "Warning", "this maybe  will broke your system,are you sure to continue?", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
if(rb == QMessageBox::Yes)

c42e
{
QList<QTableWidgetItem*> items = ui->tableWidget->selectedItems();
QTableWidgetItem *item = items.at(1);
int pid=item->text().toInt();
kill(pid,SIGKILL);  //kill ps
}

}

4.查看选中一行的进程信息

void ps::clickedInfoPushButton()
{
if(ui->tableWidget->selectedItems().isEmpty()) return;
QList<QTableWidgetItem*> items = ui->tableWidget->selectedItems();
QTableWidgetItem *item = items.at(1);
int pid=item->text().toInt();
char datapath[30];
sprintf(datapath,"/proc/%d/status",pid);
//qDebug()<<datapath;
FILE *fp;
fp=fopen(datapath,"r");
QString infoStr;
char buf[128];
while(!feof(fp)){
fgets(buf,sizeof(buf),fp);
infoStr+=buf;
}
QMessageBox::information(this,"information",infoStr);
}

5.查询pid或者进程名并定位到那一行

void ps::clickedSearchPushButton()
{
QString text=ui->searchlineEdit->text();
if(text.isEmpty()) return;
for(int i=0;i<rowcounter_old;i++){
if(ui->tableWidget->item(i,0)->text()==text||ui->tableWidget->item(i,1)->text()==text){
ui->tableWidget->selectRow(i);
break;
}
}
}

3.绘制cpu和内存监控特效

懒得解释了直接上代码吧,每隔1s更新clockwidget类中的usage_value即可

//clockwidget.cpp
#include "clockwidget.h"
#include "ui_clockwidget.h"
#include <QTimer>
#include <qmath.h>
#include <QTime>
#include <QPainter>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <unistd.h>

clockWidget::clockWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::clockWidget)
{
ui->setupUi(this);
usage_value=0;
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(1000);
}

clockWidget::~clockWidget()
{
delete ui;
}

QRectF clockWidget::textRectF(double radius, int pointSize, double angle)
{
QRectF rectF;
rectF.setX(radius*qCos(angle*3.14/180.0) - pointSize*2);
rectF.setY(radius*qSin(angle*3.14/180.0) - pointSize/2.0);
rectF.setWidth(pointSize*4);
rectF.setHeight(pointSize);
return rectF;
}

void clockWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);

// 针位置 - 多边形
static const QPoint hourHand[3] = {
QPoint(7, 8),
QPoint(-7, 8),
QPoint(0, -30)
};
static const QPoint minuteHand[3] = {
QPoint(7, 8),
QPoint(-7, 8),
QPoint(0, -65)
};

static const QPoint secondHand[3] = {
QPoint(7, 8),
QPoint(-7, 8),
QPoint(0, -80)
};

// 针颜色
QColor hourColor(200, 100, 0, 200);
QColor minuteColor(0, 127, 127, 150);
QColor secondColor(0, 160, 230, 150);

int side = qMin(width(), height());
QTime time = QTime::currentTime();

QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
// 平移坐标系原点至中心点
painter.translate(width() / 2, height() / 2);
// 缩放
painter.scale(side / 200.0, side / 200.0);

// 绘制时针
painter.setPen(Qt::NoPen);
painter.setBrush(hourColor);

painter.save();
// 每圈360° = 12h 即:旋转角度 = 小时数 * 30°
painter.restore();

painter.setPen(hourColor);

// 绘制小时线 (360度 / 12 = 30度)
for (int i = 0; i < 12; ++i) {
painter.drawLine(88, 0, 96, 0);
painter.rotate(30.0);
}

int radius = 100;
QFont font = painter.font();
font.setBold(true);
painter.setFont(font);
int pointSize = font.pointSize();

// 绘制小时文本
int nHour = 0;
for (int i = 0; i < 11; ++i) {
nHour = i ;
//        if (nHour > 10)
//            nHour -= 10;
painter.drawText(textRectF(radius*0.8, pointSize, (i+4) * 30), Qt::AlignCenter, QString::number(nHour*10));
}

// 绘制分针
painter.setPen(Qt::NoPen);
painter.setBrush(minuteColor);

painter.save();
// 每圈360° = 60m 即:旋转角度 = 分钟数 * 6°
painter.restore();

painter.setPen(minuteColor);

// 绘制分钟线 (360度 / 60 = 6度)
for (int j = 0; j < 60; ++j) {
if ((j % 5) != 0)
painter.drawLine(92, 0, 96, 0);
painter.rotate(6.0);
}

// 绘制秒针
painter.setPen(Qt::NoPen);
painter.setBrush(secondColor);

painter.save();
// 每圈360° = 60s 即:旋转角度 = 秒数 * 6°
painter.rotate((float)300/100 * usage_value-150);         //input how %
painter.drawConvexPolygon(secondHand, 3);
painter.restore();
}

void clockWidget::set_usage(float usage){
usage_value=usage;
}

4.画历史曲线

利用QT插件qcustomplot画曲线很方便,qcustomplot的用法如下

从网上下载qcustomplot.h 和qcustomplot.cpp

加载到工程中 改.pro文件 第9行末加上 printsupport 即可,再编译一下没有报错就可以用

//graph.cpp
#include "graph.h"
#include "ui_graph.h"
#include <QVector>

#include <QTime>
#include <QTimer>
#include <time.h>

Graph::Graph(QWidget *parent) :
QWidget(parent),
ui(new Ui::Graph)
{
ui->setupUi(this);

QLinearGradient plotGradient;
//lotGradient.setStart(0, 0);
//plotGradient.setFinalStop(0, 350);
plotGradient.setColorAt(0, QColor(80, 80, 80));
//plotGradient.setColorAt(1, QColor(50, 50, 50));
ui->widget->setBackground(plotGradient);

//设置坐标颜色/坐标名称颜色
ui->widget->xAxis->setLabelColor(Qt::white);//文字颜色
ui->widget->yAxis->setLabelColor(Qt::white);
ui->widget->xAxis->setTickLabelColor(Qt::white);//坐标轴数字颜色
ui->widget->yAxis->setTickLabelColor(Qt::white);
ui->widget->xAxis->setBasePen(QPen(Qt::white, 1));//坐标轴颜色及宽度
ui->widget->yAxis->setBasePen(QPen(Qt::white, 1));
ui->widget->xAxis->setTickPen(QPen(Qt::white, 1));//主刻度
ui->widget->yAxis->setTickPen(QPen(Qt::white, 1));
ui->widget->xAxis->setSubTickPen(QPen(Qt::white, 1));//副刻度
ui->widget->yAxis->setSubTickPen(QPen(Qt::white, 1));

//设置属性可缩放,移动等
ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectAxes |
QCP::iSelectLegend | QCP::iSelectPlottables);

ui->Memwidget->setBackground(plotGradient);

//设置坐标颜色/坐标名称颜色
ui->Memwidget->xAxis->setLabelColor(Qt::white);//文字颜色
ui->Memwidget->yAxis->setLabelColor(Qt::white);
ui->Memwidget->xAxis->setTickLabelColor(Qt::white);//坐标轴数字颜色
ui->Memwidget->yAxis->setTickLabelColor(Qt::white);
ui->Memwidget->xAxis->setBasePen(QPen(Qt::white, 1));//坐标轴颜色及宽度
ui->Memwidget->yAxis->setBasePen(QPen(Qt::white, 1));
ui->Memwidget->xAxis->setTickPen(QPen(Qt::white, 1));//主刻度
ui->Memwidget->yAxis->setTickPen(QPen(Qt::white, 1));
ui->Memwidget->xAxis->setSubTickPen(QPen(Qt::white, 1));//副刻度
ui->Memwidget->yAxis->setSubTickPen(QPen(Qt::white, 1));

//设置属性可缩放,移动等
ui->Memwidget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectAxes |
QCP::iSelectLegend | QCP::iSelectPlottables);

ui->Swapwidget->setBackground(plotGradient);
ui->Swapwidget->xAxis->setLabelColor(Qt::white);//文字颜色
ui->Swapwidget->yAxis->setLabelColor(Qt::white);
ui->Swapwidget->xAxis->setTickLabelColor(Qt::white);//坐标轴数字颜色
ui->Swapwidget->yAxis->setTickLabelColor(Qt::white);
ui->Swapwidget->xAxis->setBasePen(QPen(Qt::white, 1));//坐标轴颜色及宽度
ui->Swapwidget->yAxis->setBasePen(QPen(Qt::white, 1));
ui->Swapwidget->xAxis->setTickPen(QPen(Qt::white, 1));//主刻度
ui->Swapwidget->yAxis->setTickPen(QPen(Qt::white, 1));
ui->Swapwidget->xAxis->setSubTickPen(QPen(Qt::white, 1));//副刻度
ui->Swapwidget->yAxis->setSubTickPen(QPen(Qt::white, 1));

//设置属性可缩放,移动等
ui->Swapwidget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectAxes |
QCP::iSelectLegend | QCP::iSelectPlottables);

connect(ui->RePaintButton,SIGNAL(clicked(bool)),this,SLOT(RePaint()));
}

Graph::~Graph()
{
delete ui;
}

void Graph::Graph_Show(QCustomPlot *CustomPlot,QVector<double> data)
{
QVector<double> temp(20);
for(int i=0;i<20;i++) temp[i]=i;
//设置画布颜色

CustomPlot->addGraph();//添加一条曲线
CustomPlot->graph(0)->setPen(QPen(Qt::green)); //0是曲线序号,添加的第一条是0,设置曲线颜色
CustomPlot->graph(0)->setData(temp,data); //输出各点的图像,x和y都是QVector类

CustomPlot->xAxis->setRange(0,20);//x轴范围
CustomPlot->yAxis->setRange(0,100);//y轴范围
CustomPlot->replot();//重绘
}

void Graph::Graph_Show(double cpu_usage,MemInfoStruct str)
{
CPUusage.append(cpu_usage);
if(CPUusage.size()>20) CPUusage.removeFirst();
Graph_Show(ui->widget,CPUusage);

Memusage.append(str.Mem_usage);
if(Memusage.size()>20) Memusage.removeFirst();
Graph_Show(ui->Memwidget,Memusage);

Swapusage.append(str.swap_usage);
if(Swapusage.size()>20) Swapusage.removeFirst();
Graph_Show(ui->Swapwidget,Swapusage);
}

void Graph::RePaint()
{
CPUusage.clear();
Memusage.clear();
Swapusage.clear();
}

5.主窗口中的其他功能

void MainWindow::clicked_PowerOffAction()
{
QMessageBox::StandardButton rb = QMessageBox::question(NULL, "Warning", "this will let your system power off,are you sure to continue?", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
if(rb == QMessageBox::Yes)
{
system("poweroff");
}
}

void MainWindow::clicked_NewProgressAction()
{
QString file_name = QFileDialog::getOpenFileName(NULL,"Open New Progress",".","*");
file_name="cd / \n"+file_name+" &";
qDebug()<<file_name;
QByteArray ba = file_name.toLatin1(); // must
system(ba.data());

}

以上就是监控器的组成了,具体代码从 http://download.csdn.net/download/arafatms/10273184下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ubuntu proc