实验目的:
1 理解操作系统内核与应用程序的差别,哪些信号和操作是操作系统内核能捕捉到而应用程序无法捕捉到的?可以用什么样的操作去代替?
2 理解操作系统如何完成进程的控制(创建、撤消、阻塞、唤醒)
3 理解操作系统是如何利用进程控制块来管理和控制进程的?
程序功能:
1 提供触发进程创建、撤销、阻塞、唤醒的界面和操作
2 完成进程的创建、撤销、阻塞、唤醒功能
3 界面能在每次操作后分别显示当前处于就绪态、阻塞态、运行态进程的状态、优先权、进程id
4 实现进程调度的模拟,用基于优先权的调度算法实现进程调度。
程序功能实现:
通过界面选项选择进程创建、撤销、阻塞、唤醒操作。
就绪队列,阻塞队列、运行队列通过全局变量的结构体指针实现。
创建函数通过全局变量分配唯一进程ID,进程需要运行时间,优先级手动输入。时间片大小默认为5。
#include <stdio.h>
#include <stdlib.h>
#include<windows.h>
/*进程控制块结构体*/
struct task_struct
{
int id; //进程id
int state; //-1就绪, 0运行, >0 阻塞(本程序默认为1,不区分阻塞队列)
int priority; //优先级
int needtime; //运行完毕所需时间
int arrivedtime; //已运行时间
int slicetime; //时间片剩余时间,初始化为5
struct task_struct* next;
};
/*进程队列*/
struct task_struct* runnableTask; //运行
struct task_struct* unrunnableTask; //就绪
struct task_struct* stoppedTask; //阻塞
//进程id控制,每次自增1
int id = 1;
/*函数名声明*/
void taskController();
void createTask();
void stopTask();
void awakeTask();
void runTask();
void showTask();
void scheduleTask();
void getBigPriorityTask();
void deleteTask();
int main()
{
runnableTask = NULL;
unrunnableTask = NULL;
stoppedTask = NULL;
printf("进程模拟\n");
while(1)
{
taskController();
}
return 0;
}
/*
本函数模拟进程控制程序
本函数执行一次运行,当前执行进程时间片减一
本函数创建进程不占当前执行进程时间
*/
void taskController()
{
char select;
printf("本函数为进程控制函数\n");
printf(" 1.创建进程\n");
printf(" 2.阻塞当前进程\n");
printf(" 3.唤醒选定进程\n");
printf(" 4.撤销进程\n");
printf(" 5.无操作\n");
printf(" 6.退出\n");
printf("\n请输入你的选择(1--6):");
do
{
select=getchar();
}
while(select!='1'&&select!='2'&&select!='3'&&select!='4' &&select!='5' &&select!='6');
switch(select)
{
case '1':
createTask();
break;
case '2':
stopTask();
break;
case '3':
awakeTask();
break;
case '4':
deleteTask();
break;
case '5':
break;
case '6':
exit(0);
break;
default:
return ;
}
runTask();
showTask();
}
/*
创建进程,新创建进程添加到就绪进程队尾
*/
void createTask()
{
printf("\n\n\n\n创建进程开始\n");
if(unrunnableTask == NULL) //判断是否已有就绪进程 //判断是否为首指针
{
unrunnableTask = malloc(sizeof(struct task_struct));
unrunnableTask->id = id++;
printf("进程优先级:\n");
scanf("%d",&unrunnableTask->priority);
printf("进程运行需要的时间:\n");
scanf("%d",&unrunnableTask->needtime);
unrunnableTask->arrivedtime=0;
unrunnableTask->state=-1;
unrunnableTask->slicetime=0;
unrunnableTask->next = NULL;
}
else
{
struct task_struct* test = unrunnableTask;
while(test->next != NULL)
{
test = test->next;
}
test->next = malloc(sizeof(struct task_struct));
test->next->id = id++;
printf("进程优先级:\n");
scanf("%d",&test->next->priority);
printf("进程运行需要的时间:\n");
scanf("%d",&test->next->needtime);
test->next->arrivedtime=0;
test->next->state=-1;
test->next->next = NULL;
test->next->slicetime=0;
test = test->next;
}
}
/*
撤销内存程序
*/
void deleteTask()
{
//撤销运行进程
char select;
printf("撤销运行进程输入Y/y,不撤销输入N/n。\n");
do
{
select=getchar();
}
while(select!='y'&&select!='n'&&select!='Y'&&select!='N');
if(select=='y' || select=='Y')//进行撤销
{
free(runnableTask);
runnableTask = NULL;
scheduleTask();
return ;
}
//撤销阻塞进程
printf("撤销阻塞进程输入Y/y,不撤销输入N/n。\n");
do
{
select=getchar();
}
while(select!='y'&&select!='n'&&select!='Y'&&select!='N');
if(select=='y' || select=='Y')//选择撤销
{
struct task_struct* test = stoppedTask;
while(test != NULL) //循环输出阻塞进程信息
{
printf("本进程信息为\n");
printf("\n 进程名 优先级 需要时间 已用时间 剩余时间片 进程状态 \n");
printf("%8d %8d %8d %10d %10d %10d \n",test->id,test->priority,test->needtime,test->arrivedtime, test->slicetime, test->state);
printf("撤销本进程输入Y/y,不撤销输入N/n。\n");
do
{
select=getchar();
}
while(select!='y'&&select!='n'&&select!='Y'&&select!='N');
if(select=='y' || select=='Y') //选择撤销该进程
{
//从进程队列删除撤销进程
if(stoppedTask == test) //判断是否为队首
{
stoppedTask=test->next;
}
else //撤销进程非队首
{
struct task_struct* test3 = stoppedTask;
while(test3->next != test)
{
test3 = test3->next;
}
test3->next = test->next;
}
free(test);
scheduleTask();
return ;
}
}
}
//撤销就绪进程
printf("撤销就绪进程输入Y/y,不撤销输入N/n。\n");
do
{
select=getchar();
}
while(select!='y'&&select!='n'&&select!='Y'&&select!='N');
if(select=='y' || select=='Y')//选择撤销
{
struct task_struct* test = unrunnableTask;
while(test != NULL) //循环输出阻塞进程信息
{
printf("本进程信息为\n");
printf("\n 进程名 优先级 需要时间 已用时间 剩余时间片 进程状态 \n");
printf("%8d %8d %8d %10d %10d %10d \n",test->id,test->priority,test->needtime,test->arrivedtime, test->slicetime, test->state);
printf("撤销本进程输入Y/y,不撤销输入N/n。\n");
do
{
select=getchar();
}
while(select!='y'&&select!='n'&&select!='Y'&&select!='N');
if(select=='y' || select=='Y') //选择撤销该进程
{
//从进程队列删除撤销进程
if(unrunnableTask == test) //判断是否为队首
{
unrunnableTask=test->next;
}
else //撤销进程非队首
{
struct task_struct* test2 = unrunnableTask;
while(test2->next != test)
{
test2 = test2->next;
}
test2->next = test->next;
}
free(test);
scheduleTask();
return ;
}
}
}
}
/*
阻塞进程程序
*/
void stopTask()
{
if(runnableTask == NULL)
{
printf("无运行进程!\n");
return ;
}
runnableTask->state = 1; //阻塞进程状态默认为1,将进程放入阻塞队列由runTask实现
}
/*
唤醒程序,唤醒优先级最大的进程,若有优先级相同进程,唤醒先进入队列的进程
*/
void awakeTask()
{
//无阻塞进程,退出
if(stoppedTask == NULL)
{
printf("无阻塞进程!\n");
return ;
}
int max = -100;
struct task_struct* test = stoppedTask;
while(test != NULL)
{
if(max < test->priority)
{
max = test->priority;
}
test = test->next;
}
if(max == stoppedTask->priority) //判断是否为队首
{
//将进程放入就绪队列中
if(unrunnableTask == NULL)//判断就绪队列是否为空
{
unrunnableTask = stoppedTask;
unrunnableTask->state=0;
stoppedTask = stoppedTask->next;
unrunnableTask->next = NULL;
}
else//放到就绪队列队尾
{
struct task_struct* test2 = unrunnableTask;
while(test2->next != NULL)
{
test2 = test2->next;
}
stoppedTask = stoppedTask->next;
test2->next = stoppedTask;
test2->next->state=-1;
test2->next->next=NULL;
}
}
else //唤醒进程不在队首
{
//确定应唤醒进程在阻塞进程队列的位置
struct task_struct* test3 = stoppedTask;
while(test3->next->priority != max)
{
test3 = test3->next;
}
//将进程放入就绪队列中
if(unrunnableTask == NULL) //判断就绪队列是否为空
{
unrunnableTask = test3->next;
unrunnableTask->state=-1;
test3->next = test3->next->next;
unrunnableTask->next=NULL;
}
else //放到就绪队列队尾
{
printf("test3");
struct task_struct* test2 = unrunnableTask;
while(test2->next != NULL)
{
test2 = test2->next;
}
test2->next = test3->next;
test2->next->state=-1;
test3->next = test3->next->next;
test2->next->next=NULL;
}
}
scheduleTask();
}
/*
模拟运行运行状态进程
运行进程时间片时间减1
已用时间加1
判断是否启动进程调度程序
*/
void runTask()
{
printf("\n\n\n\n运行进程开始\n");
if(runnableTask != NULL)
{
printf("进程运行中……\n");
runnableTask->arrivedtime += 1;
runnableTask->slicetime -= 1;
if(runnableTask->arrivedtime == runnableTask->needtime) //当运行进程完成
{
printf("当前运行进程执行完毕\n");
printToScreen(runnableTask);
printf("运行进程执行完毕,执行进程调度程序\n");
free(runnableTask);
runnableTask = NULL;
scheduleTask();
}
else if(runnableTask->slicetime == 0) //当运行进程时间片用完
{
//改变进程优先级,运行进程优先级-1,阻塞进程优先级+2
runnableTask->priority -= 1;
//将运行完进程放回就绪进程
if(unrunnableTask == NULL)
{
unrunnableTask = runnableTask;
unrunnableTask->state=-1;
}
else
{
struct task_struct* test = unrunnableTask;
test->priority += 2;
while(test->next != NULL)
{
test = test->next;
test->priority += 2;
}
test->next = runnableTask;
test->next->state = -1;
test->next->next=NULL;
}
runnableTask = NULL;
printf("运行进程时间片用完,执行进程调度程序\n");
scheduleTask();
}
else if(runnableTask->state > 0) //当运行进程被阻塞
{
//将被阻塞进程放入阻塞进程
if(stoppedTask == NULL)
{
stoppedTask = runnableTask;
stoppedTask->state=1;
stoppedTask->next=NULL;
}
else
{
struct task_struct* test = stoppedTask;
while(test->next != NULL)
{
test = test->next;
}
test->next = runnableTask;
test->next->state=1;
test->next->next=NULL;
}
runnableTask = NULL;
printf("运行进程被阻塞,执行进程调度程序\n");
scheduleTask();
}
}
else
{
printf("无正在运行进程,调用进程调度程序\n");
scheduleTask();
}
}
/*
模拟进程调度程序
*/
void scheduleTask()
{
if(runnableTask==NULL||runnableTask->slicetime==0||runnableTask->needtime==runnableTask->arrivedtime||runnableTask->state>0) //判断是否符合切换运行进程条件
{
printf("\n\n\n\n运行调度开始\n");
if(unrunnableTask != NULL) //判断有无就绪进程
{
if(runnableTask==NULL||runnableTask->slicetime==0||runnableTask->needtime==runnableTask->arrivedtime||runnableTask->state>0)
{
getBigPriorityTask();
}
else //运行进程队列不需切换进程但进入
{
printf("进程调度程序出现未知错误\n");
}
}
else //无就绪进程
{
printf("无就绪进程可供调度\n");
}
}
else
{
printf("进入进程调度程序错误\n");
}
}
/*
对进程排序,并将最大优先级的进程给运行进程
*/
void getBigPriorityTask()
{
int max = -100;
struct task_struct* test = unrunnableTask;
while(test != NULL)
{
if(max < test->priority)
{
max = test->priority;
}
test = test->next;
}
if(max == unrunnableTask->priority) //判断是否为队首
{
runnableTask = unrunnableTask;
runnableTask->state=0;
unrunnableTask = unrunnableTask->next;
runnableTask->next = NULL;
runnableTask->slicetime=5;
}
else
{
test = unrunnableTask;
while(test->next != NULL)
{
if(test->next->priority == max)
{
runnableTask=test->next;
runnableTask->state=0;
test->next = test->next->next;
runnableTask->next = NULL;
runnableTask->slicetime=5;
}
break;
}
}
}
/*
显示进程状态
*/
void showTask()
{
printf("----------运行进程----------\n");
if(runnableTask != NULL)
{
printToScreen(runnableTask);
}
printf("----------就绪进程----------\n");
if(unrunnableTask != NULL)
{
printToScreen(unrunnableTask);
}
printf("----------阻塞进程----------\n");
if(stoppedTask != NULL)
{
printToScreen(stoppedTask);
}
}
/*
向屏幕输出进程状态
*/
void printToScreen(struct task_struct* test)
{
printf("\n 进程名 优先级 需要时间 已用时间 剩余时间片 进程状态 \n");
while(test != NULL)
{
printf("%8d %8d %8d %10d %10d %10d \n",test->id,test->priority,test->needtime,test->arrivedtime, test->slicetime, test->state);
test = test->next;
}
}