linux设置自动运行任务管理器,自己实现Linux系统任务管理器(附源码)

一、前言

之前在操作系统课程中,使用Java实现的任务管理器,使用了Swing界面、Runtime、Process相关类。文章总结和程序下载在下面:

虽然基本功能实现了,Java跨平台的特性,也使得这个应用在Linux上跑,但是在实现这个版本之后就已经感觉到Java对操作系统信息的提取与封装是有限的,Process包含的进程信息有限,且操作不方便。

因此最近在Linux课程中,决定用Qt界面+Linux方式实现自己的Linux版任务管理器。在程序设计之前,有必要先了解下Linux系统进程信息提取方式,因为这种“Linux方式”不像Java的Process类封装那样,不管底层,只管调用  process.getInputStream();去读取流。

二、Linux下/proc目录简介

Linux内核提供了一种通过 /proc 文件系统,在运行时访问内核内部数据结构、改变内核设置的机制。proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为访问系统内核数据的操作提供接口。

系统中当前运行的每一个进程都有对应的一个目录在/proc下,以进程的 PID号为目录名,它们是读取进程信息的接口。而self目录则是读取进程本身的信息接口,是一个link。

直接打开自己安装的Linux系统,进入/proc,可以看到很多数字命名的文件夹;文件夹名的数字,代表当前运行的一个进程的PID,它是读取进程信息的接口。

Linux下/proc下其他重要目录

/proc/cpuinfo     --cpu的信息

/proc/devices     --已经加载的设备并分类

/proc/modules     --所有加载到内核的模块列表

/proc/stat        --所有的CPU活动信息,可采点计算cpu的利用率

/proc/version     --Linux内核版本和gcc版本

三、Qt实现Linux版任务管理器

用户和应用程序可以通过/proc得到系统的信息,并可以改变内核的某些参数。由于系统的信息是动态改变的,所以用户或应用程序读取proc文件时,proc文件系统是动态从系统内核读出所需信息并提交的。

我们要显示系统信息,只需进行相应的文件操作就行了。

Qt的发展势头相当猛,qt的可移植性相当强,现在应用程序做界面基本都用Qt。Qt是诺基亚开发的一个跨平台的C++图形用户界面应用程序框架。Qt商业版只能试用30天,不过有GPL版的,可以免费使用。有一个非常不错的免费Qt集成开发环境QtCreator IDE。Linux版任务管理器采用的是Qt来实现图形界面。

步骤:

1、Linux下安装Qt Creator,打开新建一个工程,工程目录下,相关文件会有6个,具体见下图--工程文件夹:

0818b9ca8b590ca3270a3433284dd417.png

编译完成后的实现效果:

“内存信息”模块:

0818b9ca8b590ca3270a3433284dd417.png

“进程信息”模块:

0818b9ca8b590ca3270a3433284dd417.png

“模块信息”模块:

0818b9ca8b590ca3270a3433284dd417.png

“系统信息”模块:

0818b9ca8b590ca3270a3433284dd417.png

“关于”模块:

0818b9ca8b590ca3270a3433284dd417.png

完整源码如下:

main.cpp    工程运行的入口,创建工程时自动创建的,不需要修改。

#include

#include "mainwindow.h"

int main(int argc, char *argv[])

{

QApplication a(argc, argv);

MainWindow w;

w.show();

return a.exec();

}

mainwindow.h  工程头文件,定义资源和事件响应函数声明。

#ifndef MAINWINDOW_H

#define MAINWINDOW_H

#include

#include

#include

#include

#include

namespace Ui {

class MainWindow;

}

class MainWindow : public QMainWindow

{

Q_OBJECT

public:

explicit MainWindow(QWidget *parent = 0);

~MainWindow();

private:

Ui::MainWindow *ui;//界面资源类,所有的界面元素都是通过该类来调用

QTimer *timer; //计时器

private slots:

void on_pushButton_pkill_clicked();

void on_pushButton_prefresh_clicked();

void on_pushButton_Model_install_clicked();

void on_pushButton_Model_remove_clicked();

void on_pushButton_Model_refresh_clicked();

void on_pushButton_reboot_clicked();

void on_pushButton_halt_clicked();

void on_tabWidget_INFO_currentChanged(int index);

void timer_update_currentTabInfo();

//显示tab中的内容

void show_tabWidgetInfo(int index);

};

#endif // MAINWINDOW_H

mainwindow.cpp  工程最重要的源文件,完成主要的业务逻辑。

#include "mainwindow.h"

#include "ui_mainwindow.h"

#include

#include

#include

int a0 = 0, a1 = 0, b0 = 0, b1 = 0;

MainWindow::MainWindow(QWidget *parent) :

QMainWindow(parent),

ui(new Ui::MainWindow)

{

ui->setupUi(this);

timer = new QTimer(this);

QWidget::connect( timer, SIGNAL( timeout() ), this, SLOT( timer_update_currentTabInfo() ) );//ui控件-事件响应

QWidget::connect( ui->tabWidget_INFO, SIGNAL( currentChanged() ),

this, SLOT( on_tabWidget_currentChanged() ) );

timer->start(1000);

}

MainWindow::~MainWindow()

{

delete ui;

delete timer;

}

void MainWindow::timer_update_currentTabInfo()

{

int index = ui->tabWidget_INFO->currentIndex();

//定时器只刷新内存tab页面,用于进度条动态显示

if (index == 0)

{

show_tabWidgetInfo(index);

}

}

void MainWindow::show_tabWidgetInfo(int index)

{

QString tempStr; //读取文件信息字符串

QFile tempFile; //用于打开系统文件

int pos; //读取文件的位置

if (index == 0) //内存資源

{

tempFile.setFileName("/proc/meminfo"); //打开内存信息文件

if ( !tempFile.open(QIODevice::ReadOnly) )

{

QMessageBox::warning(this, tr("warning"), tr("The meminfo file can not open!"), QMessageBox::Yes);

return ;

}

QString memTotal;

QString memFree;

QString memUsed;

QString swapTotal;

QString swapFree;

QString swapUsed;

int nMemTotal, nMemFree, nMemUsed, nSwapTotal, nSwapFree, nSwapUsed;

while (1)

{

tempStr = tempFile.readLine();

pos = tempStr.indexOf("MemTotal");

if (pos != -1)

{

memTotal = tempStr.mid(pos+10, tempStr.length()-13);

memTotal = memTotal.trimmed();

nMemTotal = memTotal.toInt()/1024;

}

else if (pos = tempStr.indexOf("MemFree"), pos != -1)

{

memFree = tempStr.mid(pos+9, tempStr.length()-12);

memFree = memFree.trimmed();

nMemFree = memFree.toInt()/1024;

}

else if (pos = tempStr.indexOf("SwapTotal"), pos != -1)

{

swapTotal = tempStr.mid(pos+11, tempStr.length()-14);

swapTotal = swapTotal.trimmed();

nSwapTotal = swapTotal.toInt()/1024;

}

else if (pos = tempStr.indexOf("SwapFree"), pos != -1)

{

swapFree = tempStr.mid(pos+10,tempStr.length()-13);

swapFree = swapFree.trimmed();

nSwapFree = swapFree.toInt()/1024;

break;

}

}

nMemUsed = nMemTotal - nMemFree;

nSwapUsed = nSwapTotal - nSwapFree;

memUsed = QString::number(nMemUsed, 10);

swapUsed = QString::number(nSwapUsed, 10);

memFree = QString::number(nMemFree, 10);

memTotal = QString::number(nMemTotal, 10);

swapFree = QString::number(nSwapFree, 10);

swapTotal = QString::number(nSwapTotal, 10);

ui->label_RAM_Used->setText(memUsed+" MB");

ui->label_RAM_Left->setText(memFree+" MB");

ui->label_RAM_Total->setText(memTotal+" MB");

ui->label_SWAP_Used->setText(swapUsed+" MB");

ui->label_SWAP_Left->setText(swapFree+" MB");

ui->label_SWAP_Total->setText(swapTotal+" MB");

ui->progressBar_RAM->setValue(nMemUsed*100/nMemTotal);

ui->progressBar_SWAP->setValue(nSwapUsed*100/nSwapTotal);

tempFile.close(); //关闭内存信息文件

int tt = 2; //取2个点采样计算cpu当前利用律

int cpuInfo[2][7];

int cpuTotal[2][2];

while (tt)

{

tempFile.setFileName("/proc/stat"); //打开CPU使用状态信息

if ( !tempFile.open(QIODevice::ReadOnly) )

{

QMessageBox::warning(this, tr("warning"), tr("The stat file can not open!"), QMessageBox::Yes);

return;

}

tempStr = tempFile.readLine();

for (int i = 0; i < 7; i++)

{

cpuInfo[2-tt][i] = tempStr.section(" ", i+1, i+1).toInt();

cpuTotal[1][2-tt] += cpuInfo[2-tt][i];

if (i == 3)

{

cpuTotal[0][2-tt] += cpuInfo[2-tt][i];

}

}

tt--;

tempFile.close(); //关闭stat文件

}

int a = cpuTotal[0][1] - cpuTotal[0][0];

int b = cpuTotal[1][1] - cpuTotal[1][0];

if (a < 0)

{

a = -a;

}

if (b < 0)

{

b = -b;

}

ui->progressBar_CPU->setValue(a*100/b);

tempFile.setFileName("/proc/stat"); //linux下用/proc/stat文件来计算cpu的利用率

//这个文件包含了所有CPU活动的信息,该文件中的所有值都是从系统启动开始累计到当前时刻。

if ( !tempFile.open(QIODevice::ReadOnly) )

{

QMessageBox::warning(this, tr("warning"), tr("The stat file can not open!"), QMessageBox::Yes);

return;

}

tempStr = tempFile.readLine();

a0 = a1;

b0 = b1;

a1 = b1 = 0;

int gg;

for (int i = 0; i < 7; i++)

{

b1 += tempStr.section(" ", i+2, i+2).toInt();

gg = b1;

if (i == 3)

{

a1 += tempStr.section(" ", i+2, i+2).toInt();

}

}

int m, n;

m = a1 - a0;

n = b1 - b0;

if (m < 0)

{

m = -m;

}

if (n < 0)

{

n = -n;

}

ui->progressBar_CPU->setValue( (n-m)*100/n );

tempFile.close(); //关闭stat文件

}

else if (index == 1) //进程信息

{

ui->listWidget_process->clear();

QDir qd("/proc");

QStringList qsList = qd.entryList();

QString qs = qsList.join("\n");

QString id_of_pro;

bool ok;

int find_start = 3;

int a, b;

int nProPid; //进程PID

int number_of_sleep = 0, number_of_run = 0, number_of_zombie = 0;

int totalProNum = 0; //进程总数

QString proName; //进程名

QString proState; //进程状态

QString proPri; //进程优先级

QString proMem; //进程占用内存

QListWidgetItem *title = new QListWidgetItem("PID\t" + QString::fromUtf8("名称") + "\t\t" +

QString::fromUtf8("状态") + "\t" +

QString::fromUtf8("优先级") + "\t" +

QString::fromUtf8("占用内存"), ui->listWidget_process);

//循环读取进程

while (1)

{

//获取进程PID

a = qs.indexOf("\n", find_start);

b = qs.indexOf("\n", a+1);

find_start = b;

id_of_pro = qs.mid(a+1, b-a-1);

totalProNum++;

nProPid = id_of_pro.toInt(&ok, 10);

if(!ok)

{

break;

}

//打开PID所对应的进程状态文件

tempFile.setFileName("/proc/" + id_of_pro + "/stat");

if ( !tempFile.open(QIODevice::ReadOnly) )

{

QMessageBox::warning(this, tr("warning"), tr("The pid stat file can not open!"), QMessageBox::Yes);

return;

}

tempStr = tempFile.readLine();

if (tempStr.length() == 0)

{

break;

}

a = tempStr.indexOf("(");

b = tempStr.indexOf(")");

proName = tempStr.mid(a+1, b-a-1);

proName.trimmed(); //删除两端的空格

proState = tempStr.section(" ", 2, 2);

proPri = tempStr.section(" ", 17, 17);

proMem = tempStr.section(" ", 22, 22);

switch ( proState.at(0).toLatin1() )

{

case 'S': number_of_sleep++; break; //Sleep

case 'R': number_of_run++; break; //Running

case 'Z': number_of_zombie++; break; //Zombie

default : break;

}

if (proName.length() >= 12)

{

QListWidgetItem *item = new QListWidgetItem(id_of_pro + "\t" +

proName + "\t" +

proState + "\t" +

proPri + "\t" +

proMem, ui->listWidget_process);

}

else

{

QListWidgetItem *item = new QListWidgetItem(id_of_pro + "\t" +

proName + "\t\t" +

proState + "\t" +

proPri + "\t" +

proMem, ui->listWidget_process);

}

}

QString temp;

temp = QString::number(totalProNum, 10);

ui->label_pNum->setText(temp);

temp = QString::number(number_of_run, 10);

ui->label_pRun->setText(temp);

temp = QString::number(number_of_sleep, 10);

ui->label_pSleep->setText(temp);

temp = QString::number(number_of_zombie, 10);

ui->label_pZombie->setText(temp);

tempFile.close(); //关闭该PID进程的状态文件

}

else if (index == 2) //模块信息

{

ui->listWidget_model->clear();

//sys/module 是一个 sysfs 目录层次, 包含当前加载模块的信息. /proc/moudles 是旧式的, 那种信息的单个文件版本. 其中的条目包含了模块名, 每个模块占用的内存数量, 以及使用计数. 另外的字串追加到每行的末尾来指定标志, 对这个模块当前是活动的.

tempFile.setFileName("/proc/modules"); //打开模块信息文件

if ( !tempFile.open(QIODevice::ReadOnly) )

{

QMessageBox::warning(this, tr("warning"), tr("The modules file can not open!"), QMessageBox::Yes);

return ;

}

//设置模块首行项目

QListWidgetItem *title = new QListWidgetItem( QString::fromUtf8("名称") + "\t\t\t" +

QString::fromUtf8("使用内存数") + "\t\t" +

QString::fromUtf8("使用次數"), ui->listWidget_model);

QString mod_Name, mod_Mem, mod_Num;

//循环读取文件内容,查找需要的信息

while (1)

{

tempStr = tempFile.readLine();

if (tempStr.length() == 0)

{

break;

}

mod_Name = tempStr.section(" ", 0, 0);

mod_Mem = tempStr.section(" ", 1, 1);

mod_Num = tempStr.section(" ", 2, 2);

if (mod_Name.length() > 10)

{

QListWidgetItem *item = new QListWidgetItem(mod_Name + "\t\t" +

mod_Mem + "\t\t" +

mod_Num, ui->listWidget_model);

}

else

{

QListWidgetItem *item = new QListWidgetItem(mod_Name + "\t\t\t" +

mod_Mem + "\t\t" +

mod_Num, ui->listWidget_model);

}

}

tempFile.close(); //关闭模块信息文件

}

else if (index == 3) //系统信息

{

//int ok;

tempFile.setFileName("/proc/cpuinfo"); //打开CPU信息文件

if ( !tempFile.open(QIODevice::ReadOnly) )

{

QMessageBox::warning(this, tr("warning"), tr("The cpuinfo file can not open!"), QMessageBox::Yes);

return;

}

//循环读取文件内容,查找需要的信息

while (1)

{

tempStr = tempFile.readLine();

//QMessageBox::warning(this, tr("msg"), tempStr, QMessageBox::Yes);

if(tempStr==NULL){//文件读完,跳出

break;

}

pos = tempStr.indexOf("model name");

if (pos != -1)

{

pos += 13; //跳过前面的"model name:"所占用的字符

QString *cpu_name = new QString( tempStr.mid(pos, tempStr.length()-13) );

ui->label_CPUName->setText(*cpu_name);

}

else if (pos = tempStr.indexOf("vendor_id"), pos != -1)

{

pos += 12; //跳过前面的"vendor_id:"所占用的字符

QString *cpu_type = new QString( tempStr.mid(pos, tempStr.length()-12) );

ui->label_CPUType->setText(*cpu_type);

}

else if (pos = tempStr.indexOf("cpu MHz"), pos != -1)

{

pos += 11; //跳过前面的"cpu MHz:"所占用的字符

QString *cpu_frq = new QString( tempStr.mid(pos, tempStr.length()-11) );

double cpufrq = cpu_frq->toDouble(); //4核CPU

cpu_frq->setNum(cpufrq*4);

ui->label_CPUFrequency->setText(*cpu_frq + " HZ");

}

else if (pos = tempStr.indexOf("cache size"), pos!=-1)

{

pos += 13; //跳过前面的"cache size:"所占用的字符

QString *cache_size = new QString( tempStr.mid(pos, tempStr.length()-16) );

int cachesize = cache_size->toInt(); //4核CPU

cache_size->setNum(cachesize*4);

ui->label_CatheCapacity->setText(*cache_size + " KB");

}

else //跳过其他的内容

{

}

}

tempFile.close(); //关闭CPU信息文件

//打开操作系统信息文件

tempFile.setFileName("/proc/version");

if ( !tempFile.open(QIODevice::ReadOnly) )

{

QMessageBox::warning(this, tr("warning"), tr("The version file can not open!"), QMessageBox::Yes);

return ;

}

tempStr = tempFile.readLine();

pos = tempStr.indexOf("version");

QString *os_version = new QString( tempStr.mid(0, pos-1) );

ui->label_SystemType->setText(*os_version);

int pos1 = tempStr.indexOf("(");

QString *os_type = new QString( tempStr.mid(pos, pos1-pos-1) );

ui->label_SystemVersion->setText(*os_type);

pos = tempStr.indexOf("gcc version");

pos1 = tempStr.indexOf("#");

QString *gcc_info = new QString( tempStr.mid(pos+12, pos1-pos-14) );

ui->label_GCCVersion->setText(*gcc_info);

tempFile.close(); //关闭操作系统信息文件

}

else //说明

{

}

return;

}

void MainWindow::on_pushButton_halt_clicked()

{

system("halt");

}

void MainWindow::on_pushButton_reboot_clicked()

{

system("reboot");

}

void MainWindow::on_tabWidget_INFO_currentChanged(int index)

{

show_tabWidgetInfo(index); //显示tab中的内容

return ;

}

//杀死进程

void MainWindow::on_pushButton_pkill_clicked()

{

//获得进程号

QListWidgetItem *item = ui->listWidget_process->currentItem();

QString pro = item->text();

pro = pro.section("\t", 0, 0);

system("kill " + pro.toLatin1());

QMessageBox::warning(this, tr("kill"), QString::fromUtf8("该进程已被杀死!"), QMessageBox::Yes);

//回到进程信息tab表

show_tabWidgetInfo(1);

}

//刷新进程信息

void MainWindow::on_pushButton_prefresh_clicked()

{

show_tabWidgetInfo(1);

}

void MainWindow::on_pushButton_Model_install_clicked()

{

show_tabWidgetInfo(2); //安装模块还不知道如何实现

QMessageBox::warning(this, tr("tip"), tr("安装模块还不知道如何实现"), QMessageBox::Yes);

}

void MainWindow::on_pushButton_Model_remove_clicked()

{

show_tabWidgetInfo(2);

//卸载模块还不知道如何实现

QMessageBox::warning(this, tr("tip"), tr("卸载模块还不知道如何实现"), QMessageBox::Yes);

}

void MainWindow::on_pushButton_Model_refresh_clicked()

{

show_tabWidgetInfo(2);

QMessageBox::warning(this, tr("tip"), tr("刷新模块还不知道如何实现"), QMessageBox::Yes);

}

Mainwindow.ui 工程界面文件。

MainWindow

0

0

605

438

MainWindow

0

-10

611

341

WaitCursor

QTabWidget::Triangular

3

false

内存信息

内存信息

内存信息

0

0

591

81

CPU

50

30

431

23

24

0

30

66

17

CPU:

0

80

591

231

内存和交换分区

50

50

431

23

24

50

140

431

23

24

0

50

66

17

内存:

0

140

66

17

交换

50

80

66

17

Used:

200

80

66

17

Left:

380

80

66

17

Total:

380

170

66

17

Total:

50

170

66

17

Used:

200

170

66

17

Left:

90

80

66

17

0

240

80

66

17

0

420

80

66

17

0

420

170

66

17

0

90

170

66

17

0

240

170

66

17

0

进程信息

0

0

421

271

20

280

98

27

kill

170

280

98

27

refresh

430

30

66

17

进程数:

490

30

66

17

0

430

60

66

17

运行数:

430

100

66

17

睡眠数:

430

140

66

17

浆死数:

490

60

66

17

0

490

100

66

17

0

490

140

66

17

0

模块信息

20

280

98

27

Install

180

280

98

27

Romove

350

280

98

27

refresh

0

0

561

271

系统信息

0

0

591

171

处理器信息

50

30

66

17

CPU名称:

50

60

66

17

CPU类型:

50

90

66

17

CPU频率:

50

120

81

17

Cache大小:

140

30

321

17

未知

140

60

151

17

未知

140

90

66

17

未知

140

120

66

17

未知

0

180

591

121

操作系统信息

70

30

111

17

操作系统类型:

70

60

111

17

操作系统版本:

70

90

111

17

GCC编译器:

190

30

151

17

未知

190

60

281

17

未知

190

90

291

17

未知

关于

20

30

66

17

项目名:

100

30

191

17

Linux下Qt实现任务管理器

100

70

191

17

ljheee

20

70

66

17

作者:

100

110

191

17

2017-4-10

20

110

66

17

时间:

100

150

191

17

QQ554278334

20

150

66

17

联系:

380

340

98

27

reboot

500

340

98

27

shutdown

0

0

605

26

SysMontior

TopToolBarArea

false

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值