操作系统原理-模拟进程创建、终止、阻塞、唤醒原语——沐雨先生

本文详细介绍了如何使用C++实现一个简单的操作系统模拟器,涉及进程创建、阻塞、唤醒和终止功能,通过PCB数据结构和菜单驱动的用户交互,展示了操作系统中进程控制的核心概念和技术细节。
摘要由CSDN通过智能技术生成

一、实验题目: 模拟进程创建、终止、阻塞、唤醒原语

二、实验目的: 通过设计并调试创建、终止、阻塞、唤醒原语功能,有助于对操作系统中进程控制功能的理解,掌握操作系统模块的设计方法和工作原理。

三、实验环境:

1、硬件:PC机及其兼容机。

2、软件:Windows OS,MS—DOS OS,Turbo C 或 C++、VC++等。

四、实验内容:

1、设计创建、终止、阻塞、唤醒原语功能函数。

2、设计主函数,采用菜单结构(参见后面给出的流程图)。

3、设计“显示队列”函数,目的能将就绪、阻塞队列中的进程信息 显示在屏幕上,以供随时查看各队列中进程的变化情况。

五、算法流程图:

在这里插入图片描述

六、程序清单:

#include<stdio.h>
#include<string.h>
#include<windows.h>
int count=0;//记录进程数目

typedef struct PCB{
	char pname[10];//进程名
	int ppri;//优先级 1-低,2-中,3-高
	int pruntime;//运行时间
	int pstatus;//运行状态 1-阻塞,2运行,3就绪
	struct PCB *next;//指针,指向下一个PCB
}PCB;

void menu(){
	printf("---------OS实验一:模拟进程创建、阻塞、唤醒、终止原语---------\n");
	printf("----------------------------0.退出----------------------------\n");
	printf("----------------------------1.创建----------------------------\n");
	printf("----------------------------2.阻塞----------------------------\n");
	printf("----------------------------3.唤醒----------------------------\n");
	printf("----------------------------4.终止----------------------------\n");
	printf("----------------------------5.显示----------------------------\n");
	printf("---------------------请输入您需要的功能(0-5)------------------\n");
	printf("--------------------------------------------------------------\n");
	printf("各功能简要说明:\n");
	printf("创建:在本实验中,该功能仅实现建立 PCB,初始化 PCB,并将该 PCB放入就绪队列中。\n");
	printf("阻塞:在本实验中,实现的功能为,根据用户输入的进程名称查看该进程是否处在运行状态,若处在运行状态,修改该进程PCB的状态,并将该进程转入阻塞队列;若该进程处在其它状态,则给出相应的提示信息;若该进程不存在,也需要给出相应的提示信息。\n");
	printf("唤醒:功能类似阻塞功能,注意:若阻塞队列为空,则不能执行唤醒功能。\n");
	printf("终止:根据用户输入要结束的进程名称,从就绪队列、阻塞队列和正在运行的进程中找到相应的进程 PCB,并将该 PCB 从相应队列中删除。若该进程不存在,需要给出提示。\n");
	printf("显示:将就绪队列、阻塞队列中的进程列表和正在运行的进程显示出来。\n");
}


void run(PCB *head2,PCB *head3){//从就绪队列中选队首进程运行,保证有一个进程处于运行状态
	PCB *p=head3->next;
	if(p){
		head2->next=p;
		p->pstatus=2;
		head3->next=p->next;
		free(p);
	}
}


void insert(PCB *head3,PCB *temp){//将新创建的进程插入就绪队列
	PCB *p;
	p=head3;
	while(p->next!=NULL)//找尾结点
		p=p->next;
	p->next=temp;
	temp->next=NULL;
}


int check(PCB *head,PCB *temp){//检查temp进程与已有进程是否重复
	PCB *p=head;
	while(p->next){
		p=p->next;
		if(strcmp(p->pname,temp->pname)==0)
			return 0;
	}
	return 1;
}


void Delete(PCB *head,PCB *temp){/*head为链表头结点,temp为将要删除的结点*/
	PCB *p=head,*q=temp->next;
	while(p)//寻找temp的上一个节点
		if(p->next==temp){
			p->next=q;
			free(temp);
			return;
		}
		else
			p=p->next;
}


void create(PCB *head1,PCB *head2,PCB *head3){//创建进程
	int compare1,compare2,compare3;
	PCB *temp;//一个新节点
	temp=(PCB*)malloc(sizeof(PCB));
	system("cls");
	printf("---------------进程创建---------------\n");
	printf("请输入进程名:");
	scanf("%s,temp->pname");
	getchar();
	compare1=check(head1,temp);//检查进程是否与阻塞进程重复
	compare2=check(head2,temp);//检查进程是否与运行进程重复
	compare3=check(head3,temp);//检查进程是否与就绪进程重复
	if( !(compare1 && compare2 && compare3) && count<10 ){
		printf("已有进程中已有该名称进程,创建失败!");
		system("pause");
		return;
	}
	printf("\n请输入进程优先级(1-低,2-中,3-高):");
	scanf("%d",&temp->ppri);
	getchar();
	printf("\n请输入进程运行时间:");
	scanf("%d",&temp->pruntime);
	getchar();
	temp->pstatus=3;//将新创建进程放入就绪队列
	insert(head3,temp);
count++;
	system("pause");
	if(head2->next == NULL)
		run(head2,head3);
}


void block(PCB *head1,PCB *head2,PCB *head3){//阻塞进程函数
	char name[10];
	PCB *p,*q;
	system("cls");
	printf("---------------阻塞进程---------------\n");
	printf("请输入你要阻塞的进程名称:");
	scanf("%s",name);
	getchar();
	p=head1;
	p=p->next;
	while(p){//在阻塞进程中寻找pname为name的进程
		if(strcmp(p->pname,name)==0){
			printf("\n该进程已在阻塞队列中,不可重复放入\n");
			system("pause");
			return;
		}
		p=p->next;
	}

	p=head3->next;
	while(p){//在就绪进程中寻找pname为name的进程
		if(strcmp(p->pname,name)==0){
			printf("\n该进程在就绪队列中,无法放入\n");
			system("pause");
			return;
		}
		p=p->next;
	}

	p=head2->next;
	while(p){//在运行进程中寻找pname为name的进程
		if(strcmp(p->pname,name)==0){
			printf("\n该进程处于运行状态,准备将该进程放入阻塞队列\n");
			system("pause");
			p->pstatus=1;
			q=head1->next;
			while(q)
				q=q->next;
			q->next=p;
			head2->next=NULL;
			printf("已经将该进程放入阻塞队列,完成!\n");
			system("pause");
			run(head2,head3);//将执行进程阻塞,需要将cpu重新分配
			return;
		}
		p=p->next;
	}

	if(!p){
		printf("\n系统中无该进程\n");
		system("pause");
		return;
	}
}


void wakeup(PCB *head1,PCB *head2,PCB *head3){//唤醒进程
	char name[10];
	PCB *p,*q;
	system("cls");
	printf("\n---------------唤醒进程----------------\n");
	printf("\n输入你要唤醒的进程名称:");
	scanf("%s",name);
	getchar();
	p=head1;
	p=p->next;
	while(p){//在阻塞进程中寻找pname为name的进程
		if(strcmp(p->pname,name)==0){
			printf("\n该进程处于阻塞状态,准备将该进程放入就绪队列\n");
			system("pause");
			p->pstatus=3;
			q=head3->next;
			while(q)
				q=q->next;
			q->next=p;
			head2->next=NULL;
			printf("已经将该进程放入就绪队列,完成!\n");
			system("pause");
			return;
		}
		p=p->next;
	}	
	p=head2;
	p=p->next;
	while(p){//在运行进程中寻找pname为name的进程
		if(strcmp(p->pname,name)==0){
			printf("\n该进程在运行队列中\n");
			system("pause");
			return;
		}
		p=p->next;
	}
	p=head3;
	p=p->next;
	while(p){//在就绪进程中寻找pname为name的进程
		if(strcmp(p->pname,name)==0){
			printf("\n该进程在就绪队列中\n");
			system("pause");
			return;
		}
		p=p->next;
	}
	if(!p){
		printf("系统中无该进程名称\n");
		system("pause");
		return;
	}
}


void stop(PCB *head1,PCB *head2,PCB *head3){//终止进程函数
	char name[10];
	PCB *p;
	system("cls");
	printf("\n---------------终止进程----------------\n");
	printf("\n输入你要终止的进程名称:");
	scanf("%s",name);
	getchar();
	p=head1->next;
	while(p){//在阻塞进程中寻找pname为name的进程
		if(strcmp(p->pname,name)==0){
			Delete(head1,p);//调用删除结点函数
count--;
			printf("\n进程终止成功\n");
			system("pause");
			return;
		}
		p=p->next;
	}
	p=head2->next;
	while(p){//在运行进程中寻找pname为name的进程
		if(strcmp(p->pname,name)==0){
			Delete(head2,p);//调用删除结点函数
			count--;
printf("\n进程终止成功\n");
			run(head2,head3);
			system("pause");
			return;
		}
		p=p->next;
	}
	p=head3->next;
	while(p){//在就绪进程中寻找pname为name的进程
		if(strcmp(p->pname,name)==0){
			Delete(head3,p);//调用删除结点函数
			count--;
printf("\n进程终止成功\n");
			system("pause");
			return;
		}
		p=p->next;
	}
	if(!p){
		printf("进程队列中无该进程\n");
		system("pause");
	}
}


void show(PCB *head1,PCB *head2,PCB *head3){//显示队列进程
	int block=1,run=1,ready=1;
	PCB *p,*q;
	system("cls");
	p=head1;/*列出阻塞队列列表*/
	if(p->next==NULL){
		printf("阻塞队列中没有进程,请返回主界面创建进程\n");
		system("pause");
	}
	else{
		q=p->next;//指针指到第一个结点
		printf("\n--阻塞队列--\n");
		while(q){
			printf("%d)进程名:%s\n",block++,q->pname);
			printf("  进程优先级:%d\n",q->ppri);
			printf("  进程运行时间:%d\n",q->pruntime);
			q=q->next;
		}
	}
	printf("\n");

	p=head2;/*列出运行队列列表*/
	if(p->next==NULL){
		printf("运行队列中没有进程,请返回主界面创建进程\n");
		system("pause");
	}
	else{
		q=p->next;//指针指到第一个结点
		printf("\n--运行队列--\n");
		while(q){
			printf("%d)进程名:%s\n",run++,q->pname);
			printf("  进程优先级:%d\n",q->ppri);
			printf("  进程运行时间:%d\n",q->pruntime);
			q=q->next;
		}
	}
	printf("\n");

	p=head3;/*列出就绪队列列表*/
	if(p->next==NULL){
		printf("就绪队列中没有进程,请返回主界面创建进程\n");
		system("pause");
	}
	else{
		q=p->next;//指针指到第一个结点
		printf("\n--就绪队列--\n");
		while(q){
			printf("%d)进程名:%s\n",ready++,q->pname);
			printf("  进程优先级:%d\n",q->ppri);
			printf("  进程运行时间:%d\n",q->pruntime);
			q=q->next;
		}
	}
	printf("\n");
	printf("进程显示完毕");
	system("pause");
}


void main(){//主函数
	PCB *head1,*head2,*head3;//head1为阻塞队列,head2为运行队列(单核),head3为就绪队列
	head1=(PCB*)malloc(sizeof(PCB));
	head2=(PCB*)malloc(sizeof(PCB));
	head3=(PCB*)malloc(sizeof(PCB));
	head1->next=NULL;//无节点,置空
	head2->next=NULL;
	head3->next=NULL;
	if(!head1 || !head2 || !head3)//只有有一个队列申请空间失败,则进入if
	{	printf("申请空间失败,退出!");
		system("pause");
		exit(0);
	}
	while(true){
		int choose;
		system("cls");
		menu();
		scanf("%d",&choose);
		switch(choose){
			case 0:exit(0);break;
			case 1:create(head1,head2,head3);break;//创建新进程放入就绪队列
			case 2:block(head1,head2,head3);break;//阻塞运行进程
			case 3:wakeup(head1,head2,head3);break;//唤醒阻塞进程
			case 4:stop(head1,head2,head3);break;//终止的进程可能位于某一个队列
			case 5:show(head1,head2,head3);break;//显示三个队列的进程
			default:printf("输入错误");break;
		}
	}
}

七、程序中使用的数据结构及符号说明:

进程名用 P1,P2 标识
优先级(1-低,2-中,3-高)
运行时间
状态(1-阻塞,2运行,3就绪)
指针:指向下一个 PCB。

typedef struct PCB{
	char pname[10];//进程名
	int ppri;//优先级 1-低,2-中,3-高
	int pruntime;//运行时间
	int pstatus;//运行状态 1-阻塞,2运行,3就绪
	struct PCB *next;//指针,指向下一个PCB
}PCB;
int count=0;//记录进程数目
PCB *head1,*head2,*head3;//head1为阻塞队列,head2为运行队列(单核),head3为就绪队列

八、调试程序时出现问题说明及解决的方法:

  1. 定义PCB时,优先级和运行状态的各数字表示不同的意义,混淆导致程序不按预想的结果输出。
    解决方法:重复对照上下文的数字,一个一个函数修正以求正确。
  2. 程序除了create、block、wakeup、stop、show函数,还需要run、insert、check、Delete函数辅助。
  3. 起初用一个队列描述PCB,无法实现run时先运行就绪队列的首节点,阻塞运行进程是无法将其放入阻塞队列的尾结点。
    解决方法:建立三个PCB队列,分别表示就绪队列、运行队列、阻塞队列,实现顺序。
  4. 函数使用参数时,不知道用&head还是*head。
    解决方法:复习C语言中的值传递和地址传递。
  5. 使用各函数时总是参数不够,无法实现预想功能。
    解决方法:个别函数需要三个参数变量,即head1、head2和head3。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沐雨先生

如果真的帮助到你了再打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值