linux系统Qt实现简单的任务管理器

继续上次的操作系统课设,这次需要设计一个简单的任务管理器,大部分人选择GTK来实现,我剑走偏锋,使用Qt来完成这个任务。

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

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

首先需要下载一份Qt的SDK,这是Qt的英文官网:http://qt.nokia.com/,当然也有中文版的:http://qt.nokia.com/title-cn/

别问我为什么有个nokia,那是因为Qt是诺基亚开发的一个跨平台的C++图形用户界面应用程序框架。

Qt商业版只能试用30天,不过有GPL版的,可以免费使用。官网上还有一个非常不错的免费Qt集成开发环境Qt Creator IDE。我使用的就是这个软件:

打开相应的文件,读取所需要的信息,将其显示在控件上就可以了。

我采用的是Qt来实现图形界面。

 linux系统Qt实现简单的任务管理器

linux系统Qt实现简单的任务管理器

linux系统Qt实现简单的任务管理器

工程文件夹:

 linux系统Qt实现简单的任务管理器 

编译完成后的实现效果:

 linux系统Qt实现简单的任务管理器

linux系统Qt实现简单的任务管理器

linux系统Qt实现简单的任务管理器

linux系统Qt实现简单的任务管理器

linux系统Qt实现简单的任务管理器

这个实验总的来讲还是比较简单的,源码如下:

main.cpp

  1. #include <QtGui/QApplication> 
  2. #include "mainwindow.h" 
  3.  
  4. int main(int argc, char *argv[]) 
  5.     QApplication a(argc, argv); //应用程序类,每个应用程序有且只有一个 
  6.     MainWindow w; //实例化MainWindow类 
  7.     w.show(); //显示界面 
  8.     return a.exec(); //进入应用程序的循环中,直到程序退出 

mainwindow.h

  1. #ifndef MAINWINDOW_H 
  2. #define MAINWINDOW_H 
  3.  
  4. #include <QMainWindow> 
  5.  
  6. namespace Ui { 
  7.     class MainWindow; 
  8.  
  9. class MainWindow : public QMainWindow 
  10.     Q_OBJECT 
  11. public: 
  12.     explicit MainWindow(QWidget *parent = 0); 
  13.     ~MainWindow(); 
  14. private: 
  15.     Ui::MainWindow *ui; //界面资源类,所有的界面元素都是通过该类来调用 
  16.     QTimer *timer; //计时器 
  17.  
  18. private slots: 
  19.     void on_pushButton_pkill_clicked(); 
  20.     void on_pushButton_prefresh_clicked(); 
  21.     void on_pushButton_Model_install_clicked(); 
  22.     void on_pushButton_Model_remove_clicked(); 
  23.     void on_pushButton_Model_refresh_clicked(); 
  24.     void on_pushButton_reboot_clicked(); 
  25.     void on_pushButton_halt_clicked(); 
  26.     void on_tabWidget_INFO_currentChanged(int index); 
  27.     void timer_update_currentTabInfo(); 
  28.     //显示tab中的内容 
  29.     void show_tabWidgetInfo(int index); 
  30. }; 
  31.  
  32. #endif // MAINWINDOW_H 

mainwindow.cpp

  1. #include "mainwindow.h" 
  2. #include "ui_mainwindow.h" 
  3.  
  4. #include <QFile> 
  5. #include <QMessageBox> 
  6. #include <QDir> 
  7. #include <QListWidget> 
  8. #include <QListWidgetItem> 
  9. #include <QStringList> 
  10. #include <QTimer> 
  11.  
  12. int a0 = 0, a1 = 0, b0 = 0, b1 = 0; 
  13.  
  14. MainWindow::MainWindow(QWidget *parent) : //构造函数,初始化ui,计时器 
  15.     QMainWindow(parent), 
  16.     ui(new Ui::MainWindow) 
  17.     ui->setupUi(this); 
  18.     timer = new QTimer(this); 
  19.     QWidget::connect( timer, SIGNAL( timeout() ), this, SLOT( timer_update_currentTabInfo() ) ); 
  20.     QWidget::connect( ui->tabWidget_INFO, SIGNAL( currentChanged() ), 
  21.                       this, SLOT( on_tabWidget_currentChanged() ) ); 
  22.     timer->start(1000); 
  23.  
  24. MainWindow::~MainWindow() 
  25.     delete ui; 
  26.     delete timer; 
  27.  
  28. void MainWindow::timer_update_currentTabInfo() 
  29.     int index = ui->tabWidget_INFO->currentIndex(); 
  30.     //定时器只刷新内存tab页面,用于进度条动态显示 
  31.     if (index == 0) 
  32.     { 
  33.         show_tabWidgetInfo(index); 
  34.     } 
  35.  
  36. void MainWindow::show_tabWidgetInfo(int index) 
  37.     QString tempStr; //读取文件信息字符串 
  38.     QFile tempFile; //用于打开系统文件 
  39.     int pos; //读取文件的位置 
  40.  
  41.     if (index == 0) //内存資源 
  42.     { 
  43.         tempFile.setFileName("/proc/meminfo"); //打开内存信息文件 
  44.         if ( !tempFile.open(QIODevice::ReadOnly) ) 
  45.         { 
  46.             QMessageBox::warning(this, tr("warning"), tr("The meminfo file can not open!"), QMessageBox::Yes); 
  47.             return ; 
  48.         } 
  49.         QString memTotal; 
  50.         QString memFree; 
  51.         QString memUsed; 
  52.         QString swapTotal; 
  53.         QString swapFree; 
  54.         QString swapUsed; 
  55.         int nMemTotal, nMemFree, nMemUsed, nSwapTotal, nSwapFree, nSwapUsed; 
  56.  
  57.         while (1) 
  58.         { 
  59.             tempStr = tempFile.readLine(); 
  60.             pos = tempStr.indexOf("MemTotal"); 
  61.             if (pos != -1) 
  62.             { 
  63.                 memTotal = tempStr.mid(pos+10, tempStr.length()-13); 
  64.                 memTotal = memTotal.trimmed(); 
  65.                 nMemTotal = memTotal.toInt()/1024; 
  66.             } 
  67.             else if (pos = tempStr.indexOf("MemFree"), pos != -1) 
  68.             { 
  69.                 memFree = tempStr.mid(pos+9, tempStr.length()-12); 
  70.                 memFree = memFree.trimmed(); 
  71.                 nMemFree = memFree.toInt()/1024; 
  72.             } 
  73.             else if (pos = tempStr.indexOf("SwapTotal"), pos != -1) 
  74.             { 
  75.                 swapTotal = tempStr.mid(pos+11, tempStr.length()-14); 
  76.                 swapTotal = swapTotal.trimmed(); 
  77.                 nSwapTotal = swapTotal.toInt()/1024; 
  78.             } 
  79.             else if (pos = tempStr.indexOf("SwapFree"), pos != -1) 
  80.             { 
  81.                 swapFree = tempStr.mid(pos+10,tempStr.length()-13); 
  82.                 swapFree = swapFree.trimmed(); 
  83.                 nSwapFree = swapFree.toInt()/1024; 
  84.                 break; 
  85.             } 
  86.         } 
  87.  
  88.         nMemUsed = nMemTotal - nMemFree; 
  89.         nSwapUsed = nSwapTotal - nSwapFree; 
  90.  
  91.         memUsed = QString::number(nMemUsed, 10); 
  92.         swapUsed = QString::number(nSwapUsed, 10); 
  93.         memFree = QString::number(nMemFree, 10); 
  94.         memTotal = QString::number(nMemTotal, 10); 
  95.         swapFree = QString::number(nSwapFree, 10); 
  96.         swapTotal = QString::number(nSwapTotal, 10); 
  97.  
  98.         ui->label_RAM_Used->setText(memUsed+" MB"); 
  99.         ui->label_RAM_Left->setText(memFree+" MB"); 
  100.         ui->label_RAM_Total->setText(memTotal+" MB"); 
  101.         ui->label_SWAP_Used->setText(swapUsed+" MB"); 
  102.         ui->label_SWAP_Left->setText(swapFree+" MB"); 
  103.         ui->label_SWAP_Total->setText(swapTotal+" MB"); 
  104.  
  105.         ui->progressBar_RAM->setValue(nMemUsed*100/nMemTotal); 
  106.         ui->progressBar_SWAP->setValue(nSwapUsed*100/nSwapTotal); 
  107.  
  108.         tempFile.close(); //关闭内存信息文件 
  109.  
  110.   //wsj这段计算cpu使用率的方法有问题,使用另一篇中的方法:https://www.cnblogs.com/liushui-sky/p/9258101.html
  111.         int tt = 2; //取2个点采样计算cpu当前利用律 
  112.         int cpuInfo[2][7]; 
  113.         int cpuTotal[2][2]; 
  114.         while (tt) 
  115.         { 
  116.             tempFile.setFileName("/proc/stat"); //打开CPU使用状态信息 
  117.             if ( !tempFile.open(QIODevice::ReadOnly) ) 
  118.             { 
  119.                 QMessageBox::warning(this, tr("warning"), tr("The stat file can not open!"), QMessageBox::Yes); 
  120.                 return; 
  121.             } 
  122.             tempStr = tempFile.readLine(); 
  123.             for (int i = 0; i < 7; i++) 
  124.             { 
  125.                 cpuInfo[2-tt][i] = tempStr.section(" ", i+1, i+1).toInt(); 
  126.                 cpuTotal[1][2-tt] += cpuInfo[2-tt][i]; 
  127.                 if (i == 3) 
  128.                 { 
  129.                     cpuTotal[0][2-tt] += cpuInfo[2-tt][i]; 
  130.                 } 
  131.             } 
  132.             tt--; 
  133.             tempFile.close(); //关闭stat文件 
  134.         } 
  135.  
  136.         int a = cpuTotal[0][1] - cpuTotal[0][0]; 
  137.         int b = cpuTotal[1][1] - cpuTotal[1][0]; 
  138.         if (a < 0) 
  139.         { 
  140.             a = -a; 
  141.         } 
  142.         if (b < 0) 
  143.         { 
  144.             b = -b; 
  145.         } 
  146.         ui->progressBar_CPU->setValue(a*100/b); 
  147.  
  148.         tempFile.setFileName("/proc/stat"); 
  149.         if ( !tempFile.open(QIODevice::ReadOnly) ) 
  150.         { 
  151.             QMessageBox::warning(this, tr("warning"), tr("The stat file can not open!"), QMessageBox::Yes); 
  152.             return; 
  153.         } 
  154.  
  155.         tempStr = tempFile.readLine(); 
  156.         a0 = a1; 
  157.         b0 = b1; 
  158.         a1 = b1 = 0; 
  159.         int gg; 
  160.         for (int i = 0; i < 7; i++) 
  161.         { 
  162.             b1 += tempStr.section(" ", i+2, i+2).toInt(); 
  163.             gg = b1; 
  164.             if (i == 3) 
  165.             { 
  166.                 a1 += tempStr.section(" ", i+2, i+2).toInt(); 
  167.             } 
  168.         } 
  169.         int m, n; 
  170.         m = a1 - a0; 
  171.         n = b1 - b0; 
  172.         if (m < 0) 
  173.         { 
  174.             m = -m; 
  175.         } 
  176.         if (n < 0) 
  177.         { 
  178.             n = -n; 
  179.         } 
  180.         ui->progressBar_CPU->setValue( (n-m)*100/n ); 
  181.         tempFile.close(); //关闭stat文件 
  182.     } 
  183.  
  184.     else if (index == 1) //进程信息 
  185.     { 
  186.         ui->listWidget_process->clear(); 
  187.         QDir qd("/proc"); 
  188.         QStringList qsList = qd.entryList(); 
  189.         QString qs = qsList.join(" "); 
  190.         QString id_of_pro; 
  191.         bool ok; 
  192.         int find_start = 3; 
  193.         int a, b; 
  194.         int nProPid; //进程PID 
  195.         int number_of_sleep = 0, number_of_run = 0, number_of_zombie = 0; 
  196.         int totalProNum = 0; //进程总数 
  197.         QString proName; //进程名 
  198.         QString proState; //进程状态 
  199.         QString proPri; //进程优先级 
  200.         QString proMem; //进程占用内存 
  201.         QListWidgetItem *title = new QListWidgetItem("PID " + QString::fromUtf8("名称") + " " + 
  202.                                                      QString::fromUtf8("状态") + " " + 
  203.                                                      QString::fromUtf8("优先级") + " " + 
  204.                                                      QString::fromUtf8("占用内存"), ui->listWidget_process); 
  205.         //循环读取进程 
  206.         while (1) 
  207.         { 
  208.             //获取进程PID 
  209.             a = qs.indexOf(" ", find_start); 
  210.             b = qs.indexOf(" ", a+1); 
  211.             find_start = b; 
  212.             id_of_pro = qs.mid(a+1, b-a-1); 
  213.             totalProNum++; 
  214.             nProPid = id_of_pro.toInt(&ok, 10); 
  215.             if(!ok) 
  216.             { 
  217.                 break; 
  218.             } 
  219.  
  220.             //打开PID所对应的进程状态文件 
  221.             tempFile.setFileName("/proc/" + id_of_pro + "/stat"); 
  222.             if ( !tempFile.open(QIODevice::ReadOnly) ) 
  223.             { 
  224.                 QMessageBox::warning(this, tr("warning"), tr("The pid stat file can not open!"), QMessageBox::Yes); 
  225.                 return; 
  226.             } 
  227.             tempStr = tempFile.readLine(); 
  228.             if (tempStr.length() == 0) 
  229.             { 
  230.                 break; 
  231.             } 
  232.             a = tempStr.indexOf("("); 
  233.             b = tempStr.indexOf(")"); 
  234.             proName = tempStr.mid(a+1, b-a-1); 
  235.             proName.trimmed(); //删除两端的空格 
  236.             proState = tempStr.section(" ", 2, 2); 
  237.             proPri = tempStr.section(" ", 17, 17); 
  238.             proMem = tempStr.section(" ", 22, 22); 
  239.  
  240.             switch ( proState.at(0).toLatin1() ) 
  241.             { 
  242.                 case 'S':   number_of_sleep++; break; //Sleep 
  243.                 case 'R':   number_of_run++; break; //Running 
  244.                 case 'Z':   number_of_zombie++; break; //Zombie 
  245.                 default :   break; 
  246.             } 
  247.  
  248.             if (proName.length() >= 12) 
  249.             { 
  250.                 QListWidgetItem *item = new QListWidgetItem(id_of_pro + " " + 
  251.                                                             proName + " " + 
  252.                                                             proState + " " + 
  253.                                                             proPri + " " + 
  254.                                                             proMem, ui->listWidget_process); 
  255.             } 
  256.             else 
  257.             { 
  258.                 QListWidgetItem *item = new QListWidgetItem(id_of_pro + " " + 
  259.                                                             proName + " " + 
  260.                                                             proState + " " + 
  261.                                                             proPri + " " + 
  262.                                                             proMem, ui->listWidget_process); 
  263.             } 
  264.         } 
  265.         QString temp; 
  266.         temp = QString::number(totalProNum, 10); 
  267.         ui->label_pNum->setText(temp); 
  268.         temp = QString::number(number_of_run, 10); 
  269.         ui->label_pRun->setText(temp); 
  270.         temp = QString::number(number_of_sleep, 10); 
  271.         ui->label_pSleep->setText(temp); 
  272.         temp = QString::number(number_of_zombie, 10); 
  273.         ui->label_pZombie->setText(temp); 
  274.  
  275.         tempFile.close(); //关闭该PID进程的状态文件 
  276.     } 
  277.  
  278.     else if (index == 2) //模块信息 
  279.     { 
  280.         ui->listWidget_model->clear(); 
  281.         tempFile.setFileName("/proc/modules"); //打开模块信息文件 
  282.         if ( !tempFile.open(QIODevice::ReadOnly) ) 
  283.         { 
  284.             QMessageBox::warning(this, tr("warning"), tr("The modules file can not open!"), QMessageBox::Yes); 
  285.             return ; 
  286.         } 
  287.         //设置模块首行项目 
  288.         QListWidgetItem *title = new QListWidgetItem( QString::fromUtf8("名称") + " " + 
  289.                                                       QString::fromUtf8("使用内存数") + " " + 
  290.                                                       QString::fromUtf8("使用次數"), ui->listWidget_model); 
  291.  
  292.         QString mod_Name, mod_Mem, mod_Num; 
  293.         //循环读取文件内容,查找需要的信息 
  294.         while (1) 
  295.         { 
  296.             tempStr = tempFile.readLine(); 
  297.             if (tempStr.length() == 0) 
  298.             { 
  299.                 break; 
  300.             } 
  301.             mod_Name = tempStr.section(" ", 0, 0); 
  302.             mod_Mem = tempStr.section(" ", 1, 1); 
  303.             mod_Num = tempStr.section(" ", 2, 2); 
  304.             if (mod_Name.length() > 10) 
  305.             { 
  306.                 QListWidgetItem *item = new QListWidgetItem(mod_Name + " " + 
  307.                                                             mod_Mem + " " + 
  308.                                                             mod_Num, ui->listWidget_model); 
  309.             } 
  310.             else 
  311.             { 
  312.                 QListWidgetItem *item = new QListWidgetItem(mod_Name + " " + 
  313.                                                             mod_Mem + " " + 
  314.                                                             mod_Num, ui->listWidget_model); 
  315.             } 
  316.         } 
  317.         tempFile.close(); //关闭模块信息文件 
  318.     } 
  319.  
  320.     else if (index == 3) //系统信息 
  321.     { 
  322.         //int ok; 
  323.         tempFile.setFileName("/proc/cpuinfo"); //打开CPU信息文件 
  324.         if ( !tempFile.open(QIODevice::ReadOnly) ) 
  325.         { 
  326.             QMessageBox::warning(this, tr("warning"), tr("The cpuinfo file can not open!"), QMessageBox::Yes); 
  327.             return; 
  328.         } 
  329.  
  330.         //循环读取文件内容,查找需要的信息 
  331.         while (1) 
  332.         { 
  333.             tempStr = tempFile.readLine(); 
  334.             pos = tempStr.indexOf("model name"); 
  335.             if (pos != -1) 
  336.             { 
  337.                 pos += 13; //跳过前面的"model name:"所占用的字符 
  338.                 QString *cpu_name = new QString( tempStr.mid(pos, tempStr.length()-13) ); 
  339.                 ui->label_CPUName->setText(*cpu_name); 
  340.             } 
  341.             else if (pos = tempStr.indexOf("vendor_id"), pos != -1) 
  342.             { 
  343.                 pos += 12; //跳过前面的"vendor_id:"所占用的字符 
  344.                 QString *cpu_type = new QString( tempStr.mid(pos, tempStr.length()-12) ); 
  345.                 ui->label_CPUType->setText(*cpu_type); 
  346.             } 
  347.             else if (pos = tempStr.indexOf("cpu MHz"), pos != -1) 
  348.             { 
  349.                 pos += 11; //跳过前面的"cpu MHz:"所占用的字符 
  350.                 QString *cpu_frq = new QString( tempStr.mid(pos, tempStr.length()-11) ); 
  351.                 double cpufrq = cpu_frq->toDouble(); //4核CPU 
  352.                 cpu_frq->setNum(cpufrq*4); 
  353.                 ui->label_CPUFrequency->setText(*cpu_frq + " HZ"); 
  354.             } 
  355.             else if (pos = tempStr.indexOf("cache size"), pos!=-1) 
  356.             { 
  357.                 pos += 13; //跳过前面的"cache size:"所占用的字符 
  358.                 QString *cache_size = new QString( tempStr.mid(pos, tempStr.length()-16) ); 
  359.                 int cachesize = cache_size->toInt(); //4核CPU 
  360.                 cache_size->setNum(cachesize*4); 
  361.                 ui->label_CatheCapacity->setText(*cache_size + " KB"); 
  362.             } 
  363.             else //跳过其他的内容 
  364.             { 
  365.             } 
  366.         } 
  367.         tempFile.close(); //关闭CPU信息文件 
  368.  
  369.         //打开操作系统信息文件 
  370.         tempFile.setFileName("/proc/version"); 
  371.         if ( !tempFile.open(QIODevice::ReadOnly) ) 
  372.         { 
  373.             QMessageBox::warning(this, tr("warning"), tr("The version file can not open!"), QMessageBox::Yes); 
  374.             return ; 
  375.         } 
  376.         tempStr = tempFile.readLine(); 
  377.         pos = tempStr.indexOf("version"); 
  378.         QString *os_version = new QString( tempStr.mid(0, pos-1) ); 
  379.         ui->label_SystemType->setText(*os_version); 
  380.  
  381.         int pos1 = tempStr.indexOf("("); 
  382.         QString *os_type = new QString( tempStr.mid(pos, pos1-pos-1) ); 
  383.         ui->label_SystemVersion->setText(*os_type); 
  384.  
  385.         pos = tempStr.indexOf("gcc version"); 
  386.         pos1 = tempStr.indexOf("#"); 
  387.         QString *gcc_info = new QString( tempStr.mid(pos+12, pos1-pos-14) ); 
  388.         ui->label_GCCVersion->setText(*gcc_info); 
  389.  
  390.         tempFile.close(); //关闭操作系统信息文件 
  391.     } 
  392.  
  393.     else //说明 
  394.     { 
  395.     } 
  396.     return; 
  397.  
  398. void MainWindow::on_pushButton_halt_clicked() 
  399.     system("halt"); 
  400.  
  401. void MainWindow::on_pushButton_reboot_clicked() 
  402.     system("reboot"); 
  403.  
  404.  
  405. void MainWindow::on_tabWidget_INFO_currentChanged(int index) 
  406.     show_tabWidgetInfo(index); //显示tab中的内容 
  407.     return ; 
  408.  
  409. void MainWindow::on_pushButton_pkill_clicked() 
  410.     //获得进程号 
  411.     QListWidgetItem *item = ui->listWidget_process->currentItem(); 
  412.     QString pro = item->text(); 
  413.     pro = pro.section(" ", 0, 0); 
  414.     system("kill " + pro.toLatin1()); 
  415.     QMessageBox::warning(this, tr("kill"), QString::fromUtf8("该进程已被杀死!"), QMessageBox::Yes); 
  416.     //回到进程信息tab表 
  417.     show_tabWidgetInfo(1); 
  418.  
  419. void MainWindow::on_pushButton_prefresh_clicked() 
  420.     show_tabWidgetInfo(1); 
  421.  
  422. void MainWindow::on_pushButton_Model_install_clicked() 
  423.     show_tabWidgetInfo(2); //安装模块还不知道如何实现 
  424.  
  425. void MainWindow::on_pushButton_Model_remove_clicked() 
  426.     show_tabWidgetInfo(2); //卸载模块还不知道如何实现 
  427.  
  428. void MainWindow::on_pushButton_Model_refresh_clicked() 
  429.     show_tabWidgetInfo(2); 

转自http://blog.51cto.com/rangercyh/521262