C++ Qt 获取和显示进程信息
#include <QDebug>
#include <QDir>
#include <QStandardItem>
#include <QDateTime>
#include <fstream>
#include <string>
#include <cstring>
void MainWindow::get_process_info(int total_diff)
{
struct dirent *ptr;
DIR *dir;
std::ifstream input;
dir = opendir('/proc');
int i = 0;
int total_threads = 0;
int cnt = 0;
while((ptr = readdir(dir)) != NULL) {
if (is_digit(ptr->d_name)) {
// qDebug() << ptr->d_name << endl;
model->setItem(i, 5, new QStandardItem(ptr->d_name));
model->item(i, 5)->setTextAlignment(Qt::AlignCenter);
char filename[20] = '/proc/';
strcat(filename, ptr->d_name);
input.open(strcat(filename, '/stat'));
if (input.is_open()) {
cnt++;
std::string name; // process name
int pid; // process id
char state; // process state : 'RSDZTW'
int ppid, pgid, sid, tty_nr, tty_pgrp, flags, min_flt;
int cmin_flt, maj_flt, cmaj_flt, priority, nice;
long utime, stime, cutime, cstime;
int num_threads, zero;
unsigned long long start_time;
input >> pid >> name >> state >> ppid >> pgid >> sid >> tty_nr \
>> tty_pgrp >> flags >> min_flt >> cmin_flt >> maj_flt \
>> cmaj_flt >> utime >> stime >> cutime >> cstime >> priority \
>> nice >> num_threads >> zero >> start_time;
// discard the parentheses
char* tmp = (char*)name.c_str();
int len = strlen(tmp);
tmp[len - 1] = '\0';
model->setItem(i, 0, new QStandardItem(tmp+1));
// num threads
if (this->state == CPU) {
model->setItem(i, 3, new QStandardItem(QString::number(num_threads)));
model->item(i, 3)->setTextAlignment(Qt::AlignCenter);
} else {
model->setItem(i, 4, new QStandardItem(QString::number(num_threads)));
model->item(i, 4)->setTextAlignment(Qt::AlignCenter);
}
total_threads += num_threads;
if (this->state == CPU) {
// display process state
switch (state) {
case 'R':
model->setItem(i, 4, new QStandardItem('运行'));
break;
case 'S':
model->setItem(i, 4, new QStandardItem('休眠'));
break;
case 'D':
model->setItem(i, 4, new QStandardItem('TASK_UNINTERRUPTIBLE'));
break;
case 'T':
model->setItem(i, 4, new QStandardItem('停止'));
break;
case 'Z':
model->setItem(i, 4, new QStandardItem('Zombie'));
break;
case 'W':
model->setItem(i, 4, new QStandardItem('Paging'));
break;
default:
break;
}
model->item(i, 4)->setTextAlignment(Qt::AlignCenter);
// compute processes' CPU rate
if (total_diff == 0) {
model->setItem(i, 1, new QStandardItem('00.00%'));
} else {
int total_process = utime + stime + cutime + cstime;
if (process_map->find(pid) != process_map->end()) {
int total_pro_diff = total_process - (*process_map)[pid];
float rate = total_pro_diff * 8.0 / total_diff;
QString temp = tr('%1%').arg(QString::number(rate * 100, 'f', 2));
if (temp.length() < 6) {
temp = tr('0%1').arg(temp);
}
model->setItem(i, 1, new QStandardItem(temp));
} else {
model->setItem(i, 1, new QStandardItem('00.00%'));
}
(*process_map)[pid] = total_process;
}
model->item(i, 1)->setTextAlignment(Qt::AlignCenter);
// process runing time
std::ifstream uptime;
uptime.open('/proc/uptime');
if (uptime.is_open()) {
float total_time;
uptime >> total_time;
start_time = (int)(total_time - start_time * 1.0 / CLK_TCK);
// qDebug() << pid << '\t' << start_time << endl;
QDateTime time = QDateTime::fromTime_t(start_time, Qt::UTC, -8 * 60 * 60);
QString s_time = time.toString('hh:mm:ss');
model->setItem(i, 2, new QStandardItem(s_time));
uptime.close();
model->item(i, 2)->setTextAlignment(Qt::AlignCenter);
}
}
input.close();
// username
char filename2[20] = '/proc/';
strcat(filename2, ptr->d_name);
std::ifstream input2;
input2.open(strcat(filename2, '/status'));
if (input2.is_open()) {
int j = 0;
char buffer[100];
while (j < 7) {
j++;
input2.getline(buffer, 100);
}
std::string s_uid;
int uid;
input2 >> s_uid >> uid;
if (username_dict->find(uid) != username_dict->end()) {
std::string user = (*username_dict)[uid];
//qDebug() << pid << '\t' << user.c_str();
model->setItem(i, 6, new QStandardItem(user.c_str()));
}
else {
model->setItem(i, 6, new QStandardItem('nobody'));
}
model->item(i, 6)->setTextAlignment(Qt::AlignLeft);
if (this->state == MEM) {
j = 0;
while (j < 9) {
j++;
input2.getline(buffer, 100);
}
std::string tmp;
int vmsize, vmrss;
input2 >> tmp >> vmsize;
input2.getline(buffer, 100);
input2.getline(buffer, 100);
input2.getline(buffer, 100);
input2.getline(buffer, 100);
input2 >> tmp >> vmrss;
float rate = vmrss * 100.0 / this->mem_size;
QString temp = tr('%1%').arg(QString::number(rate, 'f', 2));
if (temp.length() < 6) {
temp = tr('0%1').arg(temp);
}
model->setItem(i, 1, new QStandardItem(temp));
model->setItem(i, 2, new QStandardItem(get_proper_unit(vmsize).c_str()));
model->setItem(i, 3, new QStandardItem(get_proper_unit(vmrss).c_str()));
model->item(i, 1)->setTextAlignment(Qt::AlignCenter);
//model->sort(1, Qt::DescendingOrder);
}
input2.close();
} else {
qDebug() << tr('Cannot open status: %1!').arg(ptr->d_name) << endl;
}
} else {
qDebug() << tr('Cannot open %1!').arg(ptr->d_name) << endl;
i--;
}
i++;
}
}
if (this->state == CPU) {
ui->right_2->setText(tr('进程\t %1').arg(i));
ui->right_3->setText(tr('线程\t %1').arg(total_threads));
}
model->sort(1, Qt::DescendingOrder);
// qDebug() << 'now: ' << cnt << 'last:' << this->num_processes << 'rows:' << model->rowCount();
if (cnt < this->num_processes) {
int diff= this->num_processes - cnt;
model->removeRows(model->rowCount() - diff, diff);
}
this->num_processes = cnt;
}
代码功能:
这段代码实现了在 Qt 应用程序中获取和显示系统进程信息的功能。它通过读取 /proc 虚拟文件系统中的文件来获取进程的 CPU 使用率、内存使用率、状态、运行时间、用户名等信息,并将其显示在一个表格视图中。
代码解释:
-
获取进程列表: 代码首先打开
/proc目录,并遍历其中的所有条目。对于每个条目,它会检查其名称是否为数字(表示进程 ID),如果是,则将其视为一个进程。 -
读取进程信息: 对于每个进程,代码会打开
/proc/[pid]/stat和/proc/[pid]/status文件来读取进程的详细信息,例如进程名称、状态、CPU 使用时间、内存使用量等。 -
计算 CPU 使用率: 代码使用两次读取
/proc/[pid]/stat文件的结果,计算出进程在两次读取之间的时间间隔内的 CPU 使用率。 -
获取用户名: 代码读取
/proc/[pid]/status文件中的用户 ID,并将其转换为相应的用户名。 -
显示进程信息: 代码将获取到的进程信息存储在一个
QStandardItemModel对象中,并将其显示在一个表格视图中。
代码亮点:
- 使用 Qt 框架提供的类和函数来简化代码编写。
- 使用
/proc虚拟文件系统来获取进程信息,避免了使用系统调用。 - 计算并显示了进程的 CPU 使用率、内存使用率、状态、运行时间、用户名等详细信息。
- 使用表格视图来显示进程信息,方便用户查看和管理进程。
注意事项:
- 这段代码需要在 Linux 系统上运行。
- 代码中使用了一些 Qt 框架特有的类和函数,需要对 Qt 框架有一定的了解才能理解。
- 代码中没有进行错误处理,实际应用中需要添加相应的错误处理代码。
原文地址: https://www.cveoy.top/t/topic/AJD 著作权归作者所有。请勿转载和采集!