继续上次的操作系统课设,这次需要设计一个简单的任务管理器,大部分人选择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实现简单的任务管理器_职场_02

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

工程文件夹:

linux系统Qt实现简单的任务管理器_休闲_04

 

 

 

编译完成后的实现效果:

linux系统Qt实现简单的任务管理器_休闲_05

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

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

linux系统Qt实现简单的任务管理器_职场_08

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

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

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.         int tt = 2; //取2个点采样计算cpu当前利用律 
  111.         int cpuInfo[2][7]; 
  112.         int cpuTotal[2][2]; 
  113.         while (tt) 
  114.         { 
  115.             tempFile.setFileName("/proc/stat"); //打开CPU使用状态信息 
  116.             if ( !tempFile.open(QIODevice::ReadOnly) ) 
  117.             { 
  118.                 QMessageBox::warning(this, tr("warning"), tr("The stat file can not open!"), QMessageBox::Yes); 
  119.                 return
  120.             } 
  121.             tempStr = tempFile.readLine(); 
  122.             for (int i = 0; i < 7; i++) 
  123.             { 
  124.                 cpuInfo[2-tt][i] = tempStr.section(" ", i+1, i+1).toInt(); 
  125.                 cpuTotal[1][2-tt] += cpuInfo[2-tt][i]; 
  126.                 if (i == 3) 
  127.                 { 
  128.                     cpuTotal[0][2-tt] += cpuInfo[2-tt][i]; 
  129.                 } 
  130.             } 
  131.             tt--; 
  132.             tempFile.close(); //关闭stat文件 
  133.         } 
  134.  
  135.         int a = cpuTotal[0][1] - cpuTotal[0][0]; 
  136.         int b = cpuTotal[1][1] - cpuTotal[1][0]; 
  137.         if (a < 0) 
  138.         { 
  139.             a = -a; 
  140.         } 
  141.         if (b < 0) 
  142.         { 
  143.             b = -b; 
  144.         } 
  145.         ui->progressBar_CPU->setValue(a*100/b); 
  146.  
  147.         tempFile.setFileName("/proc/stat"); 
  148.         if ( !tempFile.open(QIODevice::ReadOnly) ) 
  149.         { 
  150.             QMessageBox::warning(this, tr("warning"), tr("The stat file can not open!"), QMessageBox::Yes); 
  151.             return
  152.         } 
  153.  
  154.         tempStr = tempFile.readLine(); 
  155.         a0 = a1; 
  156.         b0 = b1; 
  157.         a1 = b1 = 0; 
  158.         int gg; 
  159.         for (int i = 0; i < 7; i++) 
  160.         { 
  161.             b1 += tempStr.section(" ", i+2, i+2).toInt(); 
  162.             gg = b1; 
  163.             if (i == 3) 
  164.             { 
  165.                 a1 += tempStr.section(" ", i+2, i+2).toInt(); 
  166.             } 
  167.         } 
  168.         int m, n; 
  169.         m = a1 - a0; 
  170.         n = b1 - b0; 
  171.         if (m < 0) 
  172.         { 
  173.             m = -m; 
  174.         } 
  175.         if (n < 0) 
  176.         { 
  177.             n = -n; 
  178.         } 
  179.         ui->progressBar_CPU->setValue( (n-m)*100/n ); 
  180.         tempFile.close(); //关闭stat文件 
  181.     } 
  182.  
  183.     else if (index == 1) //进程信息 
  184.     { 
  185.         ui->listWidget_process->clear(); 
  186.         QDir qd("/proc"); 
  187.         QStringList qsList = qd.entryList(); 
  188.         QString qs = qsList.join("\n"); 
  189.         QString id_of_pro; 
  190.         bool ok; 
  191.         int find_start = 3; 
  192.         int a, b; 
  193.         int nProPid; //进程PID 
  194.         int number_of_sleep = 0, number_of_run = 0, number_of_zombie = 0; 
  195.         int totalProNum = 0; //进程总数 
  196.         QString proName; //进程名 
  197.         QString proState; //进程状态 
  198.         QString proPri; //进程优先级 
  199.         QString proMem; //进程占用内存 
  200.         QListWidgetItem *title = new QListWidgetItem("PID\t" + QString::fromUtf8("名称") + "\t\t" + 
  201.                                                      QString::fromUtf8("状态") + "\t" + 
  202.                                                      QString::fromUtf8("优先级") + "\t" + 
  203.                                                      QString::fromUtf8("占用内存"), ui->listWidget_process); 
  204.         //循环读取进程 
  205.         while (1) 
  206.         { 
  207.             //获取进程PID 
  208.             a = qs.indexOf("\n", find_start); 
  209.             b = qs.indexOf("\n", a+1); 
  210.             find_start = b; 
  211.             id_of_pro = qs.mid(a+1, b-a-1); 
  212.             totalProNum++; 
  213.             nProPid = id_of_pro.toInt(&ok, 10); 
  214.             if(!ok) 
  215.             { 
  216.                 break
  217.             } 
  218.  
  219.             //打开PID所对应的进程状态文件 
  220.             tempFile.setFileName("/proc/" + id_of_pro + "/stat"); 
  221.             if ( !tempFile.open(QIODevice::ReadOnly) ) 
  222.             { 
  223.                 QMessageBox::warning(this, tr("warning"), tr("The pid stat file can not open!"), QMessageBox::Yes); 
  224.                 return
  225.             } 
  226.             tempStr = tempFile.readLine(); 
  227.             if (tempStr.length() == 0) 
  228.             { 
  229.                 break
  230.             } 
  231.             a = tempStr.indexOf("("); 
  232.             b = tempStr.indexOf(")"); 
  233.             proName = tempStr.mid(a+1, b-a-1); 
  234.             proName.trimmed(); //删除两端的空格 
  235.             proState = tempStr.section(" ", 2, 2); 
  236.             proPri = tempStr.section(" ", 17, 17); 
  237.             proMem = tempStr.section(" ", 22, 22); 
  238.  
  239.             switch ( proState.at(0).toLatin1() ) 
  240.             { 
  241.                 case 'S':   number_of_sleep++; break//Sleep 
  242.                 case 'R':   number_of_run++; break//Running 
  243.                 case 'Z':   number_of_zombie++; break//Zombie 
  244.                 default :   break
  245.             } 
  246.  
  247.             if (proName.length() >= 12) 
  248.             { 
  249.                 QListWidgetItem *item = new QListWidgetItem(id_of_pro + "\t" + 
  250.                                                             proName + "\t" + 
  251.                                                             proState + "\t" + 
  252.                                                             proPri + "\t" + 
  253.                                                             proMem, ui->listWidget_process); 
  254.             } 
  255.             else 
  256.             { 
  257.                 QListWidgetItem *item = new QListWidgetItem(id_of_pro + "\t" + 
  258.                                                             proName + "\t\t" + 
  259.                                                             proState + "\t" + 
  260.                                                             proPri + "\t" + 
  261.                                                             proMem, ui->listWidget_process); 
  262.             } 
  263.         } 
  264.         QString temp; 
  265.         temp = QString::number(totalProNum, 10); 
  266.         ui->label_pNum->setText(temp); 
  267.         temp = QString::number(number_of_run, 10); 
  268.         ui->label_pRun->setText(temp); 
  269.         temp = QString::number(number_of_sleep, 10); 
  270.         ui->label_pSleep->setText(temp); 
  271.         temp = QString::number(number_of_zombie, 10); 
  272.         ui->label_pZombie->setText(temp); 
  273.  
  274.         tempFile.close(); //关闭该PID进程的状态文件 
  275.     } 
  276.  
  277.     else if (index == 2) //模块信息 
  278.     { 
  279.         ui->listWidget_model->clear(); 
  280.         tempFile.setFileName("/proc/modules"); //打开模块信息文件 
  281.         if ( !tempFile.open(QIODevice::ReadOnly) ) 
  282.         { 
  283.             QMessageBox::warning(this, tr("warning"), tr("The modules file can not open!"), QMessageBox::Yes); 
  284.             return ; 
  285.         } 
  286.         //设置模块首行项目 
  287.         QListWidgetItem *title = new QListWidgetItem( QString::fromUtf8("名称") + "\t\t\t" + 
  288.                                                       QString::fromUtf8("使用内存数") + "\t\t" + 
  289.                                                       QString::fromUtf8("使用次數"), ui->listWidget_model); 
  290.  
  291.         QString mod_Name, mod_Mem, mod_Num; 
  292.         //循环读取文件内容,查找需要的信息 
  293.         while (1) 
  294.         { 
  295.             tempStr = tempFile.readLine(); 
  296.             if (tempStr.length() == 0) 
  297.             { 
  298.                 break
  299.             } 
  300.             mod_Name = tempStr.section(" ", 0, 0); 
  301.             mod_Mem = tempStr.section(" ", 1, 1); 
  302.             mod_Num = tempStr.section(" ", 2, 2); 
  303.             if (mod_Name.length() > 10) 
  304.             { 
  305.                 QListWidgetItem *item = new QListWidgetItem(mod_Name + "\t\t" + 
  306.                                                             mod_Mem + "\t\t" + 
  307.                                                             mod_Num, ui->listWidget_model); 
  308.             } 
  309.             else 
  310.             { 
  311.                 QListWidgetItem *item = new QListWidgetItem(mod_Name + "\t\t\t" + 
  312.                                                             mod_Mem + "\t\t" + 
  313.                                                             mod_Num, ui->listWidget_model); 
  314.             } 
  315.         } 
  316.         tempFile.close(); //关闭模块信息文件 
  317.     } 
  318.  
  319.     else if (index == 3) //系统信息 
  320.     { 
  321.         //int ok; 
  322.         tempFile.setFileName("/proc/cpuinfo"); //打开CPU信息文件 
  323.         if ( !tempFile.open(QIODevice::ReadOnly) ) 
  324.         { 
  325.             QMessageBox::warning(this, tr("warning"), tr("The cpuinfo file can not open!"), QMessageBox::Yes); 
  326.             return
  327.         } 
  328.  
  329.         //循环读取文件内容,查找需要的信息 
  330.         while (1) 
  331.         { 
  332.             tempStr = tempFile.readLine(); 
  333.             pos = tempStr.indexOf("model name"); 
  334.             if (pos != -1) 
  335.             { 
  336.                 pos += 13; //跳过前面的"model name:"所占用的字符 
  337.                 QString *cpu_name = new QString( tempStr.mid(pos, tempStr.length()-13) ); 
  338.                 ui->label_CPUName->setText(*cpu_name); 
  339.             } 
  340.             else if (pos = tempStr.indexOf("vendor_id"), pos != -1) 
  341.             { 
  342.                 pos += 12; //跳过前面的"vendor_id:"所占用的字符 
  343.                 QString *cpu_type = new QString( tempStr.mid(pos, tempStr.length()-12) ); 
  344.                 ui->label_CPUType->setText(*cpu_type); 
  345.             } 
  346.             else if (pos = tempStr.indexOf("cpu MHz"), pos != -1) 
  347.             { 
  348.                 pos += 11; //跳过前面的"cpu MHz:"所占用的字符 
  349.                 QString *cpu_frq = new QString( tempStr.mid(pos, tempStr.length()-11) ); 
  350.                 double cpufrq = cpu_frq->toDouble(); //4核CPU 
  351.                 cpu_frq->setNum(cpufrq*4); 
  352.                 ui->label_CPUFrequency->setText(*cpu_frq + " HZ"); 
  353.             } 
  354.             else if (pos = tempStr.indexOf("cache size"), pos!=-1) 
  355.             { 
  356.                 pos += 13; //跳过前面的"cache size:"所占用的字符 
  357.                 QString *cache_size = new QString( tempStr.mid(pos, tempStr.length()-16) ); 
  358.                 int cachesize = cache_size->toInt(); //4核CPU 
  359.                 cache_size->setNum(cachesize*4); 
  360.                 ui->label_CatheCapacity->setText(*cache_size + " KB"); 
  361.             } 
  362.             else //跳过其他的内容 
  363.             { 
  364.             } 
  365.         } 
  366.         tempFile.close(); //关闭CPU信息文件 
  367.  
  368.         //打开操作系统信息文件 
  369.         tempFile.setFileName("/proc/version"); 
  370.         if ( !tempFile.open(QIODevice::ReadOnly) ) 
  371.         { 
  372.             QMessageBox::warning(this, tr("warning"), tr("The version file can not open!"), QMessageBox::Yes); 
  373.             return ; 
  374.         } 
  375.         tempStr = tempFile.readLine(); 
  376.         pos = tempStr.indexOf("version"); 
  377.         QString *os_version = new QString( tempStr.mid(0, pos-1) ); 
  378.         ui->label_SystemType->setText(*os_version); 
  379.  
  380.         int pos1 = tempStr.indexOf("("); 
  381.         QString *os_type = new QString( tempStr.mid(pos, pos1-pos-1) ); 
  382.         ui->label_SystemVersion->setText(*os_type); 
  383.  
  384.         pos = tempStr.indexOf("gcc version"); 
  385.         pos1 = tempStr.indexOf("#"); 
  386.         QString *gcc_info = new QString( tempStr.mid(pos+12, pos1-pos-14) ); 
  387.         ui->label_GCCVersion->setText(*gcc_info); 
  388.  
  389.         tempFile.close(); //关闭操作系统信息文件 
  390.     } 
  391.  
  392.     else //说明 
  393.     { 
  394.     } 
  395.     return
  396.  
  397. void MainWindow::on_pushButton_halt_clicked() 
  398.     system("halt"); 
  399.  
  400. void MainWindow::on_pushButton_reboot_clicked() 
  401.     system("reboot"); 
  402.  
  403.  
  404. void MainWindow::on_tabWidget_INFO_currentChanged(int index) 
  405.     show_tabWidgetInfo(index); //显示tab中的内容 
  406.     return ; 
  407.  
  408. void MainWindow::on_pushButton_pkill_clicked() 
  409.     //获得进程号 
  410.     QListWidgetItem *item = ui->listWidget_process->currentItem(); 
  411.     QString pro = item->text(); 
  412.     pro = pro.section("\t", 0, 0); 
  413.     system("kill " + pro.toLatin1()); 
  414.     QMessageBox::warning(this, tr("kill"), QString::fromUtf8("该进程已被杀死!"), QMessageBox::Yes); 
  415.     //回到进程信息tab表 
  416.     show_tabWidgetInfo(1); 
  417.  
  418. void MainWindow::on_pushButton_prefresh_clicked() 
  419.     show_tabWidgetInfo(1); 
  420.  
  421. void MainWindow::on_pushButton_Model_install_clicked() 
  422.     show_tabWidgetInfo(2); //安装模块还不知道如何实现 
  423.  
  424. void MainWindow::on_pushButton_Model_remove_clicked() 
  425.     show_tabWidgetInfo(2); //卸载模块还不知道如何实现 
  426.  
  427. void MainWindow::on_pushButton_Model_refresh_clicked() 
  428.     show_tabWidgetInfo(2);