进程控制模拟算法

这是一个C语言实现的操作系统进程管理的程序,包括进程创建、终止、调度、阻塞、唤醒、挂起和激活等功能,并实现了先来先服务(FCFS)、优先级调度和时间片轮转三种调度算法。程序还提供了查看进程控制块、改变优先级和查看所有进程的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include<stdio.h>
#include<stdlib.h>
#include<string>
#include <windows.h>
#include<tlhelp32.h>
#define N 10
struct pb
{
	int ko;
	int no;
	int cha;
};
typedef struct pb PCB;
PCB a[N];
int showallproc()
{
	PROCESSENTRY32 pe32;//用来存储进程信息的结构体
	pe32.dwSize = sizeof(pe32);
	HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);//获取进程快照
	if (hProcessSnap == INVALID_HANDLE_VALUE)
	{
		printf("调用失败\n");
		return 1;
	}
	BOOL bProc = Process32First(hProcessSnap, &pe32);
	while (bProc)
	{
		printf("%5d %s\n", pe32.th32ProcessID, pe32.szExeFile);//输出进程ID和进程名
		bProc = Process32Next(hProcessSnap, &pe32);
	}
	CloseHandle(hProcessSnap);
	return 0;
}
static int count = 1;
void create()   //创建
{
	static int pi = 1;
	int k, l = 0, m;
	printf("请输入创建的进程号:");
	scanf("%d", &m);
	for (k = 1; k <= N; k++)
		if (a[k].no == m)
			l = 1;
	if (l == 1)
	{
		printf("错误,进程创建重复!\n");
		create();
	}
	else
	{
		for (k = 1; k <= N; k++)
		{
			if (a[k].no == 0)
			{
				pi = k; break;
			}
		}
		a[pi].no = m;
		printf("\n输入优先级:");
		scanf("%d", &a[pi].ko);
		if (count > 1)            //首次进程状态为执行,之后为活动就绪
			a[pi++].cha = 3;
		else
			a[pi++].cha = 5;
		count++;
	}
}

int stopproc()
{
	DWORD ProcessID;
	printf("请输入想要终止的进程ID\n");
	scanf(" %d", &ProcessID);
	HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, ProcessID);//打开对应进程句柄
	if (hProcess == NULL)
	{
		printf("失败\n");
		return -1;
	}
	if (!TerminateProcess(hProcess, 0))//关闭进程
	{
		printf("关闭失败\n");
	}
	else
	{
		printf("关闭成功\n");
	}
	CloseHandle(hProcess);

	return 0;
}

void dispatch()   //调度
{
	int i, m, l = 0, j = 0, k, min = 10000;

	for (m = 1; m <= N; m++)
		if (a[m].cha == 5)
			l = m;
	if (l != 0)
	{
		printf("调度失败!");
		return;
	}
	else
		for (k = 1; k <= N; k++)
		{
			if (a[k].cha == 3)
				if (min > a[k].ko)
				{
					min = a[k].ko;
					i = k;
					j = 1;
				}
		}
	if (j)
		a[i].cha = 5;
	else if (j == 0)
		printf("调度失败!\n");

}

void block()   //阻塞
{
	int k, m, l = 0;
	printf("请输入已经创建的进程号:");
	scanf("%d", &m);
	for (k = 1; k <= N; k++)
		if (a[k].no == m)
			l = k;
	if (l != 0)
	{
		if (a[l].cha == 3 || 5)
			a[l].cha = 4;
		else if (a[l].cha == 1)
			a[l].cha = 2;
		else
			printf("阻塞失败!\n");
	}
	else
		printf("阻塞失败!");
}

void wakeup()   //唤醒
{
	int k, m, l = 0;
	printf("请输入已经创建的进程号:");
	scanf("%d", &m);
	for (k = 1; k <= N; k++)
		if (a[k].no == m)
			l = k;
	if (l != 0)
	{
		if (a[l].cha == 2)
			a[l].cha = 1;
		else if (a[l].cha == 4)
			a[l].cha = 3;
		else
			printf("唤醒失败!\n");
	}
	else
		printf("唤醒失败!");
}


void suspend()   //挂起
{
	int k, m, l = 0;
	printf("请输入已经创建的进程号:");
	scanf("%d", &m);
	for (k = 1; k <= N; k++)
		if (a[k].no == m)
			l = k;
	if (l != 0)
	{
		if (a[l].cha == 3 || 5)
			a[l].cha = 1;
		else if (a[l].cha == 4)
			a[l].cha = 2;
		else
			printf("错误!挂起失败\n");
	}
	else
		printf("错误!挂起失败!");
}

void active()   //激活
{
	int k, m, l = 0;
	printf("请输入已经创建的进程号:");
	scanf("%d", &m);
	for (k = 1; k <= N; k++)
		if (a[k].no == m)
			l = k;
	if (l != 0)
	{
		if (a[l].cha == 1)
			a[l].cha = 3;
		else if (a[l].cha == 2)
			a[l].cha = 4;
		else
			printf("激活失败!\n");
	}
	else
		printf("激活失败!");
}

void display()   //查看PCB功能模块
{
	int i;
	printf("\t\tPCB\t进程号\t优先级\t状态\n");
	for (i = 1; i <= 10; i++)
		printf("\t\t%d\t%d\t%d\t%d\n", i, a[i].no, a[i].ko, a[i].cha);
	printf("\t1-静止就绪  2--静止阻塞  3--活动就绪  4--活动阻塞  5--执行\n");
}

void change_KO()   //改变优先数
{
	int k, m, l = 0;
	printf("请输入已创建的进程号:");
	scanf("%d", &m);
	for (k = 1; k <= N; k++)
		if (a[k].no == m)
			l = k;
	if (l != 0)
	{
		printf("输入新的优先级:");
		scanf("%d", &a[l].ko);
		display();
	}
	else
		printf("失败!");
}
/********************这是先来先服务的程序*********************************/
struct fcfs {//定义先来先服务结构体、参数
	char name[10];
	float daodatime;//到达时间
	float fuwutime;//服务时间
	float kaishitime;//开始时间
	float wanchengtime;//完成时间
	float zhouztime;//周转时间
	float daiquantime;//带权周转时间
};
fcfs b[10000];
void input(fcfs* p, int N1)  //构造一个输入进程的信息的函数,定义结构体指针
{
	int i;
	for (i = 0; i <= N1 - 1; i++)
	{
		printf("输入第%d个进程的名字、到达时间、服务时间:\n", i + 1);
		scanf("%s%f%f", &p[i].name, &p[i].daodatime, &p[i].fuwutime);//把输入的信息保存到结构体指针所对应的内存中
	}

}//构造一个输出函数
void Print(fcfs* p, float daodatime, float fuwutime, float kaishitime, float wanchengtime, float zhouztime, float daiquantime, int N1)
{
	int k;
	printf("执行顺序:\n");
	printf("%s", p[0].name);
	for (k = 1; k < N1; k++)
	{
		printf("-->%s", p[k].name);
	}
	printf("\n进程的相关信息如下:\n");
	printf("\n名字\t到达\t服务\t开始\t完成\t周转\t带权周转\n");
	for (k = 0; k <= N1 - 1; k++)
	{
		printf("%s\t%-.2f\t%-.2f\t%-.2f\t%-.2f\t%-.2f\t%-.2f\t\n", p[k].name, p[k].daodatime, p[k].fuwutime, p[k].kaishitime, p[k].wanchengtime, p[k].zhouztime, p[k].daiquantime);
	} //题目中加入-.2是保留双精度的两位。一般f默认保留六位小数的。  
}
void sort(fcfs* p, int N1)//进程根据到达时间进行排序
{
	for (int i = 0; i <= N1 - 1; i++)
		for (int j = 0; j <= i; j++)
			if (p[i].daodatime < p[j].daodatime)//如果i的时间到达时间小于j的到达时间,就交换
			{
				fcfs temp;//在结构体中定义第三个变量进行交换
				temp = p[i];
				p[i] = p[j];
				p[j] = temp;
			}
}
//核心的运行阶段
void deal(fcfs* p, float daodatime, float fuwutime, float kaishitime, float wanchengtime, float zhouztime, float daiquantime, int N1)
{
	int k;
	for (k = 0; k <= N1 - 1; k++)
	{
		if (k == 0)//K=0,表示第一个进程到达
		{
			p[k].kaishitime = p[k].daodatime;//那么开始时间=到达时间
			p[k].wanchengtime = p[k].daodatime + p[k].fuwutime;//完成时间=到达时间+服务时间
		}
		else
		{
			p[k].kaishitime = p[k - 1].wanchengtime;//下一个进程的开始时间=上一个进程的完成时间
			p[k].wanchengtime = p[k - 1].wanchengtime + p[k].fuwutime;//完成时间=上一个进程的完成时间+服务时间
		}
	}
	for (k = 0; k <= N1 - 1; k++)//计算周转时间和带权周转时间
	{
		p[k].zhouztime = p[k].wanchengtime - p[k].daodatime;//周转时间=完成时间-到达时间
		p[k].daiquantime = p[k].zhouztime / p[k].fuwutime;//带权周转时间=周转时间/服务时间   
	}
}
void FCFS(fcfs* p, int N1)//定义先来先服务函数
{
	float daodatime = 0, fuwutime = 0, kaishitime = 0, wanchengtime = 0, zhouztime = 0, daiquantime = 0;//初始化变量为0
	sort(p, N1);//声明排序函数
	deal(p, daodatime, fuwutime, kaishitime, wanchengtime, zhouztime, daiquantime, N1);//声明运行函数
	Print(p, daodatime, fuwutime, kaishitime, wanchengtime, zhouztime, daiquantime, N1); //声明输出函数
}
/****************************这是优先服务调度算法的代码***********************************/
typedef struct PCB2
{
	char name[10];//进程名
	int runtime;//要求运行时间
	int frist;//定义优先数
	char zhuangtai; //定义状态,R为就绪,F为完成
};
struct PCB2 PCBcontrol[4];//定义进程控制块数组 
void youxian()//构造优先函数 
{
	int i, n;
	printf("请输入进程的个数:\n");
	scanf("%d", &n);
	printf("请输入进程的名字、优先权、运行时间\n");
	printf("\n");
	for (i = 0; i < n; i++)
	{
		printf("请输入第%d个进程的信息:\n", i + 1);
		scanf("%s%d%d", &PCBcontrol[i].name, &PCBcontrol[i].frist, &PCBcontrol[i].runtime);
		PCBcontrol[i].zhuangtai = 'R';//进程初始状态均为就绪
		getchar();//等待回车进入下一次运行
	}
}
int max_frist_process()//确定最大优先级进程子程序 
{
	int max = -10;//max为最大优先数,初始化为-10  
	int i, key;
	for (i = 0; i < 3; i++)
	{
		if (PCBcontrol[i].zhuangtai == 'r')//r表示正在运行
			return -1;//返回-1
		else
			if (max < PCBcontrol[i].frist && PCBcontrol[i].zhuangtai == 'R')//从就绪进程中选取优先数最大的进程
			{
				max = PCBcontrol[i].frist;//max存放每次循环中的最大优先数
				key = i;//将进程号赋给key
			}
	}
	if (PCBcontrol[key].zhuangtai == 'F')//具有最大优先数的进程若已运行完毕
		return -1;//则返回-1
	else
		return key;//将key作为返回值返回 
}
void show()//显示函数
{
	int i;
	printf("\n进程名  优先级 运行时间 当前状态\n");
	printf("*****************************************\n");
	for (i = 0; i < 3; i++)//依次显示每个进程的名、优先数、要求运行时间和状态
	{
		printf("  %s\t %d\t  %d\t   %s\t\n", &PCBcontrol[i].name, PCBcontrol[i].frist, PCBcontrol[i].runtime, &PCBcontrol[i].zhuangtai);
	}
	printf("\n请按回车键进行查看");
}
void run()//进程运行子程序
{
	int i, j;
	int t = 0;//t为运行次数
	for (j = 0; j < 3; j++)
	{
		t += PCBcontrol[j].runtime;
	}//运行次数即为各个进程运行时间之和 
	printf("\n进程没运行前,当前的状态是:\n");
	show(); //调用show()子程序显示运行前PCB的情况
	getchar();//等待回车进入下一次运行
	for (j = 0; j < t; j++)
	{
		while (max_frist_process() != -1)//具有最大优先数的进程没有运行完,让其运行
		{
			PCBcontrol[max_frist_process()].zhuangtai = 'r';//将其状态置为r,表示其正在运行
		}
		for (i = 0; i < 3; i++)
		{
			if (PCBcontrol[i].zhuangtai == 'r')
			{
				PCBcontrol[i].frist -= 1;//将当前运行进程的优先数减1
				PCBcontrol[i].runtime--;//要求运行时间减1
				{
					if (PCBcontrol[i].runtime == 0)
						PCBcontrol[i].zhuangtai = 'F';//运行完则将该进程状态置为结束
					else
						PCBcontrol[i].zhuangtai = 'R';//未运行完将其状态置为就绪
				}
				show();//显示每次运行后各PCB的情况
				getchar();//等待回车进入下一次运行
			}
		}
	}
}

/***********************这是算法时间片轮转法的代码*****************************************/
struct shijian {//定义时间片的结构体
	char name;  //定义进程名
	int daodatime;// 到达时间
	int fuwutime;  //服务时间
	int shengyutime;//剩余时间
	char* state;//所处状态
	struct shijian* next;
};
struct shijian* time()
{
	int a, i;
	struct shijian* head, * rear, * p, * q, * t;//定义队首、队尾、P是队尾指针、Q是队首指针和执行时间
	head = rear = NULL;//初始化队首和队尾为空 
	printf("请输入进程数目:");
	scanf("%d", &a);
	for (i = 0; i < a; i++)
	{
		p = (struct shijian*)malloc(sizeof(struct shijian)); //初始化一个空间给进程进入
		printf("输入第%d个进程的名字、到达时间、服务时间:\n", i + 1);
		scanf("%s%d%d", &p->name, &p->daodatime, &p->fuwutime);
		p->shengyutime = p->fuwutime;
		p->state = "就绪";
		if (rear == NULL) //当输入结束时,把P的数据放到队首,以便执行下一步
		{
			head = p;
			p->next = NULL;
			rear = p;
		}
		else  //否则执行时间就为空,队首变成Q
		{
			t = NULL;
			q = head;
			while (q && q->daodatime < p->daodatime)//当Q和Q的到达时间小于P的到达时间时,把执行时间给Q
			{
				t = q;
				q = q->next;
			}
			if (q == head)  //而当Q是队首时,则下一个队首变成P,以便每个进程都能够得到时间片
			{
				p->next = head;
				head = p;
			}
			else if (t == rear)  //当执行时间片到达队尾时(执行完时),返回给队首P
			{
				rear->next = p;
				p->next = NULL;
				rear = p;
			}
			else   //否则给队首P占用执行时间,P执行完后到Q
			{
				t->next = p;
				p->next = q;
			}
		}
	}
	return head;//返回队首
}
void output(struct shijian* head)//定义输出函数
{
	struct shijian* p, * t, * r;
	int num;
	printf("请输入时间片:");
	scanf("%d", &num);
	while (head != NULL) //当队首不为空时,把P给队首
	{
		r = p = head;
		while (p != NULL) //把执行时间给队首
		{
			t = head;
			p->shengyutime = p->shengyutime - num;  //P的剩余时间=剩余时间-时间片
			p->state = "运行"; //状态变成运行态
			if (p->shengyutime < 0) //当P运行完,即剩余时间小于0时,仍然把它当做0处理
				p->shengyutime = 0;
			printf("\n************程序开始运行*****************\n");
			printf("进程  到达时间 服务时间  剩余时间  当前状态\n");
			while (t != NULL)  //时间不为空时,输出当前进程的信息,并把时间片交给下一个进程
			{
				printf("%2c%8d%8d%14d%10s\n", t->name, t->daodatime, t->fuwutime, t->shengyutime, t->state);
				t = t->next;
			}
			getchar(); //按住回车键观看
			if (p->shengyutime == 0)//当队首的剩余时间为0时,先把队首改成P的下一个,然后释放内存,删除队首节点
			{
				if (p == head)
				{
					head = p->next;
					free(p);
					p = head;
				}
				else  //否则返回执行,把队尾的下一个指针变成P的下一个指针,队尾的位置移动到队首
				{
					r->next = p->next;
					p = r->next;
					r = p;
				}
			}
			else  //否则把队首的位置给队尾,把队首的状态显示为"就绪"状态
			{
				r = p;
				p->state = "就绪";
				p = p->next;
			}
		}
	}
}
void diaodusuanfa()
{
	int N1;
	int number;
	char Tishikuang;//提示框
	do {
		printf("    **                       输入 1-先来先服务                           *\n");
		printf("    **                       输入 2-时间片轮转法                         *\n");
		printf("    **                       输入 3-优先服务法                           *\n");
		printf("    **                       输入 0-退出该程序                           *\n");
		printf("\n提示:请根据自己的需求选择相应的操作数:\n");
		scanf("%d", &number);/*提示输入字母,用switch语句存入到case中,最后增加提示框是否继续*/
		switch (number)
		{
		case 0:
			break;
		case 1:
			printf("您选择的是**先来先服务调度**\n\n");
			printf("请输入进程的数量:\n");
			scanf("%d", &N1);
			input(b, N1);
			FCFS(b, N1);
			break;
		case 2:
			printf("\n您选择的是时间片轮转发调度\n\n");
			struct shijian* head; //定义时间片的队首结构体
			head = time(); //队首执行的时间
			output(head);//输出函数
			break;
		case 3:
			printf("\n您选择的是优先服务调度,本程序可提供3个进程的调度。\n\n");
			youxian();//初始化各个进程PCB 
			run();//进程调度模拟
			break;
		default:
			printf("\n你的输入有误,请确定是从0到3之间进行输入,O(∩_∩)O谢谢\n");
			break;
		}
		printf("\n是否继续操作(y/n) ?");
		fflush(stdin);
		Tishikuang = getchar();
	} while (Tishikuang == 'y' || Tishikuang == 'Y');
}

int main()
{
	int i;

	do
	{
		printf("\t\t**************功能模块 ***************\n");
		printf("\t\t*        1-----进程创建             *\n");
		printf("\t\t*        2-----进程撤消             *\n");
		printf("\t\t*        3-----调度                 *\n");
		printf("\t\t*        4-----阻塞                 *\n");
		printf("\t\t*        5-----唤醒                 *\n");
		printf("\t\t*        6-----挂起                 *\n");
		printf("\t\t*        7-----激活                 *\n");
		printf("\t\t*        8-----查看进程控制块       *\n");
		printf("\t\t*        9-----改变优先数           *\n");
		printf("\t\t*       10----查看进程              *\n");
		printf("\t\t*       11----调度算法模拟          *\n");
		printf("\t\t*        0-----退出                 *\n");
		printf("\t\t*************************************\n");
		printf("\t\t请选择0-10:");
		scanf("%d", &i);
		printf("\n");
		switch (i)
		{
		case 1: create(); break;
		case 2:stopproc(); break;
		case 3: dispatch(); break;
		case 4: block(); break;
		case 5: wakeup(); break;
		case 6: suspend(); break;
		case 7: active(); break;
		case 8: display(); break;
		case 9: change_KO(); break;
		case 10: showallproc(); break;
		case 11: diaodusuanfa(); break;
		case 0: exit(0);   //程序正常退出
		}
	}   while (i != 0);
	system("pause");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值