C++系统进程统计

题目内容

系统进程统计

设计一个程序,每秒统计一次当前系统的进程状况,并按照内存使用自多到少排序打印输出相关信息。对已经结束的进程,另外给出一个列表,并显示该进程的结束时间和持续时间。

基本要求

  1. 该题目要求使用两个链式线性表。一个链表存储当前活动进程,要求使用双向链表,排序要求是按照内存使用自多到少排序。另外一个链表存储已结束进程,要求使用单向链表,按照结束时间离当前时间的关系排序,最近的最前,最远的最后;
  2. 每秒在窗口内更新一次当前系统进程情况,输出内容包括:进程名,持续时间,内存使用情况;
  3. 每秒在窗口内更新一次已结束进程情况,输出内容包括:进程名,持续时间,结束时间;
  4. 注意进程在这两个链表中的切换,一个进程既可被结束,也可以过一段时间后再被运行。

程序说明

思路

  1. 创建三个链表:总进程链表(双向),用于记录所有存在的进程;已结束进程链表(单向);当前进程链表(双向),用于更新前两个链表。
  2. 总进程链表和当前进程链表的结点内容为进程名、持续时间、内存、PID(用于区分每个进程);已结束进程链表的结点内容为进程名、PID、持续时间、结束时间(为0时不会被打印出来)。
  3. 调用Window API函数获取当前系统进程作为总进程,更新总进程链表,再用总进程链表更新已结束进程链表。
  4. 按内存大小排序总进程链表,因为是第一遍,可作为当前进程输出。
  5. 进入每秒更新的循环体中。
  6. 获取当前进程,更新当前进程链表,首先通过与总进程链表比较寻找有无已结束的进程。若无,更新持续时间;若有,更新已结束进程链表该进程的结束时间,使其可以打印出来。
  7. 然后当前进程链表继续通过与总进程链表比较寻找进程是否在总进程链表中。若不在,添加到总进程链表和已结束进程链表;若在,即是进程被重启。
  8. 排序,输出。

实现方法

int CreateList(DLinkList&)

创建总进程链表和当前进程链表,用Window API函数获取当前所有进程,通过自带函数按顺序将每一个进程作为结点添加在链表中。双向链表设置为不循环,有头结点。

int CreateEndedList(SLinkList&, DLinkList)

创建已结束进程链表,复制总进程链表。有头结点,头结点的持续时间用来记录测试程序的总时间,用于更新信息。

int SortDList(DLinkList &),int SortSList(SLinkList&)

冒泡排序,分别按内存大小和结束时间排序

void ShowArray_D(DLinkList, SLinkList)

打印当前进程和已结束进程。

int UpdateTime(DLinkList&, DLinkList&, SLinkList&)

更新持续时间和结束时间。进入这个函数一次,就更新测试程序总时间。分外循环和内循环两部分,外循环每次取总进程链表的一个结点,内循环每次取当前进程链表的一个结点,即可比较出有无已结束进程。

  • 若有,在已结束进程链表中找到该结点位置,更新其结束时间使其能被打印;
  • 若无,更新该结点在总进程链表中的持续时间,并赋值给当前进程链表的结点。
int UpdateProgarm(DLinkList& L, DLinkList currentL, SLinkList& S)

更新重新调用的进程或新进程。分外循环和内循环两部分,外循环每次去当前进程链表的一个结点,内循环每次取总进程链表的一个结点,即可比较出有无重新调用进程或新进程。

  • 如果当前进程链表的结点不在总进程链表中,说明是新进程,更新总进程链表和已结束进程链表;
  • 如果当前进程链表在总进程链表中,并且在已结束进程链表中结束时间不为0,即为重新调用的进程,将其在已结束进程链表中结束时间重置为0,并将其在总进程链表中的持续时间重置为0。

程序源代码

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<windows.h>
#include<TLHELP32.h>
#include<iomanip>
#include<string>
#include"Psapi.h"
#include<ctime>
#pragma comment(lib,"Psapi.lib")
using namespace std;

typedef struct DLNode {
	//进程名
	char name[100];

	//持续时间
	int duration;

	//内存使用情况
	int memory;

	//ID
	int PID;

	DLNode *prior, *next;
}DLNode, *DLinkList;

typedef struct SLNode {
	//进程名
	char name[100];

	//持续时间
	int duration;

	//结束时间
	int endTime;

	//ID
	int PID;

	SLNode *next;
}SLNode, *SLinkList;


//获取内存
int PrintMemoryInfo(DWORD);

//创建当前进程链表
int CreateList(DLinkList&);

//创建已结束进程链表
int CreateEndedList(SLinkList&, DLinkList);

//按内存大小给进程排序
int SortDList(DLinkList &);

//按照结束时间排序
int SortSList(SLinkList&);

//统计已结束进程
int UpdateTime(DLinkList&, DLinkList&, SLinkList&);

//刷新后更新进程
int UpdateProgarm(DLinkList &, DLinkList, SLinkList&);

//根据PID,在储存结束时间的链表中查找该进程
SLinkList LocateOverList(SLinkList&, const int);

//显示当前进程
void ShowArray_D(DLinkList, SLinkList);

int main() {
	//L为总进程表,cuttentL为当前进程表
	DLinkList L;
	DLinkList currentL;

	//S中存储已结束进程
	SLinkList S;

	//创建该程序执行时得到的最初的进程表,用于与当前进程比对,来获取已结束进程
	CreateList(L);

	//创建结束进程表
	CreateEndedList(S, L);

	//排序
	SortDList(L);

	//打印
	ShowArray_D(L, S);
	
	while (1) {
		//每过1s获取一次当前进程
		Sleep(5000);

		//清屏
		system("cls");

		//获取当前进程表
		CreateList(currentL);

		//排序
		SortDList(currentL);

		//调整结束时间及持续时间
		UpdateTime(L, currentL, S);

		//调整重新调用的程序及新调用的程序
		UpdateProgarm(L, currentL, S);

		//排序
		SortSList(S);

		//打印
		ShowArray_D(currentL, S);
	}

	system("pause");
	return 0;
}

int PrintMemoryInfo(DWORD processID)
{
	//API
	HANDLE hProcess;
	PROCESS_MEMORY_COUNTERS pmc;
	hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
	if (hProcess == NULL)
		return 0;

	//GetProcessMemoryInfo()用于获取内存的使用情况
	if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc)))	
	{
		CloseHandle(hProcess);

		//pmc.WorkingSetSize就是程序在当前代码处的内存使用量
		return pmc.WorkingSetSize;
	}
}

int CreateList(DLinkList& D){
	//头结点
	D = (DLinkList)malloc(sizeof(DLNode));
	D->prior = NULL;
	D->next = NULL;

	//p在循环建立链表时,指向最后结点
	//q为新结点
	DLinkList p = D, q;

	//存放进程信息的结构体
	PROCESSENTRY32 temp; 
	temp.dwSize = sizeof(temp);

	//获取系统内的所有进程
	HANDLE hProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (INVALID_HANDLE_VALUE == hProcessSnapshot)
	{
		printf("未获得进程!\n");
		return 0;
	}

	//获取进程
	BOOL bMore = Process32First(hProcessSnapshot, &temp);
	while (bMore) {
		//获得当前进程的内存量
		int judge = PrintMemoryInfo(temp.th32ProcessID);
		if (judge) {
			//新进程的内容赋给新结点,接在双向链表最后
			q = (DLinkList)malloc(sizeof(DLNode));
			q->memory = judge /1024;
			strcpy_s(q->name, temp.szExeFile);
			q->PID = temp.th32ProcessID;
			q->duration = 0;
			p->next = q;
			q->prior = p;
			q->next = NULL;
			p = q;
		}
		bMore = Process32Next(hProcessSnapshot, &temp);
	}

	//清除hProcess句柄
	CloseHandle(hProcessSnapshot);
	return 1;
}

int CreateEndedList(SLinkList& S, DLinkList D)
{
	//把总进程链表所有内容赋给记录已结束进程链表
	S = (SLinkList)malloc(sizeof(SLNode));
	S->duration = 0;//总时间
	S->endTime = 0;//结束时间
	DLinkList  p_D =D->next;
	SLinkList p_S = S, q_S = (SLinkList)malloc(sizeof(SLNode));
	while (p_D){
		q_S = (SLinkList)malloc(sizeof(SLNode));
		strcpy_s(q_S->name, strlen(p_D->name) + 1, p_D->name);
		q_S->PID = p_D->PID;
		q_S->duration = 0;
		q_S->endTime = 0;
		p_S->next = q_S;
		p_S = p_S->next;
		p_D = p_D->next;
	}
	q_S->next = NULL;
	return 1;
}

int SortDList(DLinkList &D) {
	//统计结点数目
	int statisticNum = 0;
	DLinkList statistic = D->next;
	while (statistic) {
		statisticNum++;
		statistic = statistic->next;
	}

	//冒泡排序
	DLinkList q = D->next;
	DLinkList t = (DLinkList)malloc(sizeof(DLNode));
	//标记排序是否发生交换
	//若不发生交换
	//则排序完成
	int flag = 1;

	while (flag == 1 && statisticNum - 1 > 0)
	{
		q = D->next;
		//若没有发生交换
		//flag为0,则不会发生下一趟排序
		flag = 0;
		for (int i = 1; i < statisticNum; i++)
		{
			if (q->memory < q->next->memory)
			{
				flag = 1;
				strcpy_s(t->name, strlen(q->name) + 1, q->name);
				t->memory = q->memory;
				t->PID = q->PID;
				t->duration = q->duration;
				strcpy_s(q->name, strlen(q->next->name) + 1, q->next->name);
				q->memory = q->next->memory;
				q->PID = q->next->PID;
				q->duration = q->next->duration;
				strcpy_s(q->next->name, strlen(t->name) + 1, t->name);
				q->next->memory = t->memory;
				q->next->PID = t->PID;
				q->next->duration = t->duration;
			}
			q = q->next;
		}
		statisticNum--;
	}
	return 1;
}

int SortSList(SLinkList &S) {
	//记录结点数目
	int statisticNum = 0;
	SLinkList statistic = S->next;
	while (statistic) {
		statisticNum++;
		statistic = statistic->next;
	}

	//冒泡排序
	SLinkList q = S->next;
	SLinkList t = (SLinkList)malloc(sizeof(SLNode));
	//标记排序是否发生交换
	//若不发生交换
	//则排序完成
	int flag = 1;

	while (flag == 1 && statisticNum - 1 > 0)
	{
		q = S->next;
		//若没有发生交换
		//flag为0,则不会发生下一趟排序
		flag = 0;
		for (int i = 1; i < statisticNum; i++)
		{
			if (q->endTime < q->next->endTime)
			{
				flag = 1;
				strcpy_s(t->name, strlen(q->name) + 1, q->name);
				t->endTime = q->endTime;
				t->PID = q->PID;
				t->duration = q->duration;
				strcpy_s(q->name, strlen(q->next->name) + 1, q->next->name);
				q->endTime = q->next->endTime;
				q->PID = q->next->PID;
				q->duration = q->next->duration;
				strcpy_s(q->next->name, strlen(t->name) + 1, t->name);
				q->next->endTime = t->endTime;
				q->next->PID = t->PID;
				q->next->duration = t->duration;
			}
			q = q->next;
		}
		statisticNum--;
	}
	return 1;
}

void ShowArray_D(DLinkList D, SLinkList S) {
	cout.setf(ios::left);
	cout << setw(20) << "当前系统进程名" << '	' << "PID";
	cout.setf(ios::right, ios::left);
	cout<< '	' << setw(17) <<"内存使用情况" << '	' << "持续时间" << '	' << setw(20) <<endl;
	cout << "----------------------------------------------------------------" << endl;

	DLinkList  p = D->next;
	SLinkList s = S->next;
	
	//打印当前进程链表的内容
	while (p){
			char *nameSave = p->name;
			for (int i = 0; i < 20; i++) {
				cout << nameSave[i];
				if (nameSave[i] == '\0') {
					for (int j = i; j < 20; j++) {
						cout << " ";
					}
					break;
				}
			}

			cout.setf(ios::left);
			cout << '	' << p->PID;

			cout.setf(ios::right, ios::left);
			cout << '	' << setw(15) << p->memory << "KB";
			if (p->duration < 60)
				cout << '	' << p->duration << "s" << endl;
			if (p->duration >= 60)
				cout << '	' << p->duration / 60 << "m  " << p->duration % 60 << "s" << endl;

			p = p->next;
	}
	cout << endl;

	if (s) {
		cout.setf(ios::left);
		cout << setw(20) << "已结束进程名" << '	' << "PID";
		cout.setf(ios::right, ios::left);
		cout << '	' << setw(17) << "持续时间" << '	' << "结束时间" << '	' << setw(20) << endl;
		cout << "----------------------------------------------------------------" << endl;
	}
	
	//当链表未结束
	//已结束进程链表的结点的endTime值不为0,打印
	while(s && s->endTime != 0){
			char *nameSave1 = s->name;
			for (int i = 0; i < 20; i++) {
				cout << nameSave1[i];
				if (nameSave1[i] == '\0') {
					for (int j = i; j < 20; j++) {
						cout << " ";
					}
					break;
				}
			}

			cout.setf(ios::left);
			cout << '\t' << s->PID;

			cout.setf(ios::right, ios::left);
			if (s->duration < 60)
				cout << '	' << setw(15) <<s->duration << "s";
			if (s->duration >= 60)
				cout << '	' << setw(12) << s->duration / 60 << "m  " << s->duration % 60 << "s";


			cout.setf(ios::left, ios::right);

			if (s->endTime < 60)
				cout << '	' << s->endTime << "s" << endl;
			if (s->endTime >= 60)
				cout << '	' << s->endTime / 60 << "m  " << s->endTime % 60 << "s" << endl;
			s = s->next;
		
	}
}

SLinkList LocateOverList(SLinkList& S, const int PID)
{
	//在已结束进程中查找进程编号为PID的进程
	SLinkList p = S->next;
	while (p)
	{
		if (PID == p->PID)
			return p;
		p = p->next;
	}
	return NULL;
}

int UpdateTime(DLinkList &L, DLinkList &currentL, SLinkList &S) {
	//判断有无找到未结束进程
	int judge;

	SLinkList p_S = S->next;
	DLinkList p_L = L->next, p_currentL;

	//头结点用来记录调试时间
	S->duration += 1;
	
	while (p_L){
		//重置为1
		judge = 1;
		
		//寻找有无未结束进程
		p_currentL = currentL->next;
		while (p_currentL) {
			//该进程未结束
			if(p_currentL->PID == p_L->PID)
			{
				//找到,置为0
				judge = 0;
				break;
			}
			p_currentL = p_currentL->next;
		}

		//进程已结束
		if (judge)
		{
			//获取该结束进程在已结束进程链表的位置
			//更新结束时间
			p_S = LocateOverList(S, p_L->PID);

			//如果结束时间为0,更新结束时间
			//如果结束时间不为0,更新结束的持续时间
			if (p_S->endTime == 0){
				p_S->endTime = S->duration;
			}
			else{
				p_S->duration += 1;
			}
		}

		//进程未结束
		//更新当前进程的运行的持续时间
		else {
				p_L->duration += 1;
				p_currentL->duration = p_L->duration;
		}
		
		p_L = p_L->next;
	}
	return 1;
}

int UpdateProgarm(DLinkList& L, DLinkList currentL, SLinkList& S)
{
	//判断有无找到新进程
	int judge;

	//p_S为
	//q_S用于接新进程结点(已结束进程链表)
	//temp_S为新进程的结点(已结束进程链表)
	SLinkList p_S = S->next, q_S = S->next, temp_S = (SLinkList)malloc(sizeof(SLNode));

	//p_L用于对比当前进程是否为新进程
	//p_currentL为当前进程表的指针
	//q_L用于接新进程结点(总进程链表)
	//temp_L为新进程的结点(总进程链表)
	DLinkList p_L = L->next, p_currentL = currentL->next, q_L = L->next, temp_L = (DLinkList)malloc(sizeof(DLNode));

	//遍历当前进程表
	while (p_currentL){
		judge = 1;

		p_L = L->next;
		while (p_L){
			//该进程已在进程表L中
			if (p_currentL->PID == p_L->PID)
			{
				judge = 0;
				break;
			}
			p_L = p_L->next;
		}

		//进程不在L中,将其添加如L,S表中
		if (judge)
		{
			do{
				q_L = q_L->next;
			} while (q_L->next);
			temp_L = (DLinkList)malloc(sizeof(DLNode));
			temp_L->PID = p_currentL->PID;
			temp_L->memory = p_currentL->memory;
			temp_L->duration = 0;
			strcpy_s(temp_L->name, p_currentL->name);
			q_L->next = temp_L;
			temp_L->next = NULL;
			temp_L->prior = q_L;

			
			do{
				q_S = q_S->next;
			}while (q_S->next);
			temp_S = (SLinkList)malloc(sizeof(SLNode));
			temp_S->PID = p_currentL->PID;
			temp_S->duration = 0;
			temp_S->endTime = 0;
			strcpy_s(temp_S->name, p_currentL->name);
			q_S->next = temp_S;
			temp_S->next = NULL;
		}

		else {
			p_S = S->next;
			while (p_S)
			{
				if (p_currentL->PID == p_S->PID && p_S->endTime != 0)
				{
					//重新启用进程
					p_S->endTime = 0;
					
					p_currentL->duration = p_L->duration = 0;
					break;
				}
				p_S = p_S->next;
			}
		}

		p_currentL = p_currentL->next;
	} 
	return 1;
}

原文链接: https://www.cnblogs.com/wasi-991017/p/12267280.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    C++系统进程统计

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/192728

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月12日 下午6:09
下一篇 2023年2月12日 下午6:09

相关推荐