模拟进程_2
害,我又来了,对昨天发布的博客中程序的一些地方做了改善。写这个也没有别的目的,就是想记录一下自己在大学的一些学习成果。可能以后再看会觉得很搞笑,很低智。但这作为学习阶段的一个记录,我觉得还是不错的,至少现阶段觉得不错。。。。哈!
一、运行结果
初始设置:
菜单页面:
运行结果:
二、源代码
代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
struct pcb{
char name;//外部名称
int pid;//内部编号
int s;//状态 -1空闲 0就绪 1运行
int job;//工作量
int jobn;
int cur;//尾
int ts;//开始时间
int tf; //结束时间
};
// 初始化数组
void init(struct pcb *pcb,int n){
int i=0;
while(i<(n-1)){
pcb[i].s=-1;//-1表示空闲态
pcb[i].job=999999;
pcb[i].pid=i;//赋予内部值
pcb[i].cur=i+1;
//printf("--%d--",pcb[i].pid);//检错
//printf("*%d*",pcb[i].cur);//检错
i++;
}
pcb[i].pid=i;//最后一个pcb块赋予内部值
pcb[i].job=99999;
pcb[i].cur=-999;
}
// 测试空值函数
int space_number(struct pcb *pcb){
int i,j;
i=0;
j=0;
while(pcb[i].cur>=0){
//printf("%d -> ",pcb[i].pid);//检错
i = pcb[i].cur;
j++;
}
printf("\n\n");
printf("\t\t\t\t space剩余%d .",j);
return j;
}
//找出空值尾部函数
int space_last(struct pcb *pcb){
int i,j;
i=0;
j=0;
while(pcb[i].cur>=0){
//printf("%d -> ",pcb[i].pid);//检错
i = pcb[i].cur;
}
//printf("space最后一个pcb块为%d",pcb[i].pid);//检错
return i;
}
// 输出测试空值函数
void test_space(struct pcb *pcb){
int i,j;
i=0;
printf("\n\n");
while(pcb[i].cur>=0){
printf("%d -> ",pcb[i].pid);
i = pcb[i].cur;
}
printf("%d >>>",pcb[i].pid);
printf("遍历完成!\n");
printf("\n\n");
}
//测试ready函数
int ready_number(struct pcb *pcb,int ready){
int j=0;
printf("ready里的pcb内部标号为:");
while(pcb[ready].cur!=-999){
ready=pcb[ready].cur;
j++;
//printf("11");//检错
}
printf("ready有:%d",j);//检错
return j;
}
//输出测试ready里的pcb块函数
void test_ready(struct pcb *pcb,int ready){
printf("\n\n");
printf("\n ready里的pcb内部标号为:\n");
while(pcb[ready].cur!=-999){
ready=pcb[ready].cur;//去除ready里头部
printf("pid: %d ",pcb[ready].pid);
printf("s: %d ",pcb[ready].s);
printf("name: %c ",pcb[ready].name);
printf("ts: %d ",pcb[ready].ts);
printf("job: %d -->> ",pcb[ready].job);
//printf("11");//检错
}
printf("****遍历完成****\n");
printf("\n\n");
}
void show_ready(struct pcb *pcb,int ready){
printf("\n ready里的进程详细信息:\n");
while(pcb[ready].cur!=-999){
ready=pcb[ready].cur;//去除ready里头部
printf("name: %c ",pcb[ready].name);
printf("pid: %d ",pcb[ready].pid);
printf("s: %d ",pcb[ready].s);
printf("ts: %d ",pcb[ready].ts);
printf("job: %d ",pcb[ready].job);
printf("cur: %d -->> ",pcb[ready].cur);
//printf("11");//检错
}
printf("展示完成\n\n");
}
//创建就绪态pcb函数
int creat_pcb(struct pcb *pcb,int space,int ready,int c){//指明space的头部,ready的头部
printf("\n\n");
char pcb_name;
int previous_1,previous_2,pcb_job;
while(pcb[space].cur!=-999){
// printf("12");//检错
previous_1=space;
space=pcb[space].cur;
}
while(pcb[ready].cur!=-999){
//printf("233333");//检错
ready=pcb[ready].cur;
}
if(pcb[space].pid==0){
printf("\t\t\t\t--空闲pcb块不够,无法创建新进程--\n");
}
else{
c=c+2;//系统时间+2 代表创建进程所需时间为2
printf("\t\t\t\t请输入要创建的进程的名称:");
getchar();
scanf("%c",&pcb_name);
printf("\t\t\t\t请输入要创建的进程的工作量:");
getchar();
scanf("%d",&pcb_job);
pcb[previous_1].cur=-999;//space拿下来的pcb的前一个pcb的cur赋值为-999
pcb[ready].cur=space;//ready尾部cur赋值链接新的pcb
pcb[space].cur=-999;//ready新的pcb作为尾部后,cur赋值为-999
pcb[space].name=pcb_name;
pcb[space].job=pcb_job;
pcb[space].jobn=pcb_job;
pcb[space].s=0;
pcb[space].ts=c; //新创建的pcb的就绪开始时间ts
}
return c;
printf("\n\n");
}
//调度就绪态到运行态函数
int ready_to_run(struct pcb *pcb,int ready_head,int space_last,int time,int c){
printf("\n\n");
//一次运行一个时间片给一个进程使用 满足导员要求
int ready_last,ready_front,ready_tail,T;
float W;
if(pcb[ready_head].cur==-999){
printf("\n无可运行的进程\n");
return c;
}
else{
ready_front=pcb[ready_head].pid;//保留头部的地址位置
ready_last=pcb[ready_head].cur;//排除ready头部
pcb[ready_last].job=(pcb[ready_last].job-time);//运行一个时间片
pcb[ready_last].s=1;//状态转化为运行态
if(pcb[ready_last].job<=0){//判断
pcb[ready_last].s=-1;//回复状态为空闲态
c=c+pcb[ready_last].job+time;//系统时间(不必等时间片全部用光)
pcb[ready_last].tf=c;//tf等于结束时的系统时间
pcb[space_last].cur=pcb[ready_last].pid;//空闲块末尾回收运行完的进程
pcb[ready_front].cur=pcb[ready_last].cur;//ready里更改去除pcb块前面一个pcb块的cur
pcb[ready_last].cur=-999;//空闲块尾部的cur赋值-999
T=pcb[ready_last].tf-pcb[ready_last].ts;//周转时间
W=((pcb[ready_last].tf-pcb[ready_last].ts)*1.0/pcb[ready_last].jobn);//带权周转时间
printf("\t\t\t\t<ts: %d ",pcb[ready_last].ts);
printf("tf: %d>",pcb[ready_last].tf);
printf("\n\t\t\t\tpid:%d name: %c 运行完成--",pcb[ready_last].pid,pcb[ready_last].name);
printf("周转时间:%d | 带权周转时间:%.2f\n",T,W);
}
else{//运行完一次后就放到ready的尾部
ready_tail=pcb[ready_last].pid;
c=c+time;
if(pcb[ready_tail].cur!=-999){//ready里是否只有一个pcb块
while(pcb[ready_tail].cur!=-999){
ready_tail=pcb[ready_tail].cur;//向下跳
}
pcb[ready_last].s=0;//状态转化为就绪态ready
c=c+2;//运行态向就绪态转换所废时间
pcb[ready_front].cur=pcb[ready_last].cur;//ready头部指向当前pcb块的下一跳
pcb[ready_tail].cur=pcb[ready_last].pid;//ready尾部指向当前pcb块
pcb[ready_last].cur=-999;//尾部赋值
}
}
}
//一次运行多个时间片,直到一个进程完成后结束
/*int j=0,ready_last,ready_last_ssp,ready_front,T,xpz=1;//先来先服务的
struct pcb bijiao;
float W;
bijiao.job=999999;
ready_last=ready_head;//ready的头部pcb
while(pcb[ready_last].cur!=-999){//先来先服务算法
ready_front=pcb[ready_last].pid;//保留前一个的地址位置
ready_last=pcb[ready_last].cur;//除去头部第一个
//printf("*name: %c ->",pcb[ready_last].name);//输出进程外部名字,检错
pcb[ready_last].s=1;//运行态
c=c+2;//就绪态向运行态转变花费的时间
if(pcb[ready_last].job>=time){
pcb[ready_last].job=(pcb[ready_last].job-time);//运行时间片
c=c+time;
}else{
pcb[ready_last].job=(pcb[ready_last].job-time);
if(pcb[ready_last].job<=0){//判断
pcb[ready_last].s=-1;//回复状态为空闲态
c=c+pcb[ready_last].job+time;//系统时间(不必等时间片全部用光)
pcb[ready_last].tf=c;//tf等于结束时的系统时间
pcb[space_last].cur=pcb[ready_last].pid;//空闲块末尾回收运行玩的进程
pcb[ready_front].cur=pcb[ready_last].cur;//ready里更改去除pcb块前面一个pcb块的cur
pcb[ready_last].cur=-999;//空闲块尾部的cur赋值-999
T=pcb[ready_last].tf-pcb[ready_last].ts;//周转时间
W=((pcb[ready_last].tf-pcb[ready_last].ts)*1.0/pcb[ready_last].jobn);//带权周转时间
printf("<ts: %d ",pcb[ready_last].ts);
printf("tf: %d>",pcb[ready_last].tf);
printf("\npid:%d name: %c 运行完成--",pcb[ready_last].pid,pcb[ready_last].name);
printf("周转时间:%d | 带权周转时间:%.2f\n",T,W);
}
}
}*/
printf("\n\n");
return c;
}
// 主函数
void main(){
int ssp,N/*申请pcb的数目*/,a/*就绪态头部位置偏移*/,i/*space的头部pid*/,j/*ready的头部pid*/,space_rest/*space中剩余空闲pcb数目*/,
xpz/*小瓶子*/,aa/*普通变量*/,bb/*接收space中最后一个pcb的下标*/,time/*时间片*/,c=0/*系统时间轴*/;
printf("请输入申请的pcb块的数量:");
scanf("%d",&N);
getchar();
struct pcb pcb[N],*ready,*space,*run;
init(pcb,N);//初始化进程
test_space(pcb);//测试space中的cur
printf("指定就绪态态头部的pcb块编号(1-%d):",(N-1));
scanf("%d",&a);
printf("\n");
printf("设置时间片大小:");
scanf("%d",&time);
printf("\n");
system("cls");
if(a<N&&a>0){
space= pcb+0;
i=space->pid;
ready = pcb+a;
j=ready->pid;
pcb[a-1].cur=pcb[a].cur;//更改space中就绪态前一个pcb中cur的值
pcb[a].cur=-999;//就绪态头部是cur赋值为-999
while(ssp!=-1){
printf("\n");
printf("\t\t\t\t**********************************************\n");
printf("\t\t\t\t---------------------菜单---------------------\n");
printf("\t\t\t\t|1.遍历space中的pcb块\t");
printf("2.遍历ready中的pcb块 |\n");
printf("\t\t\t\t|3.创建新的进程\t\t");
printf("4.调用运行进程 |\n");
printf("\t\t\t\t|5.查看进程情况\t\t");
printf("6.清除屏幕 |\n");
printf("\t\t\t\t|7.退出程序\t\t");
printf(" |\n");
printf("\t\t\t\t----------------------------------------------\n");
printf("\t\t\t\t********************孙苏平***********************\n");
printf("\t\t\t\t请选择功能:");
getchar();
scanf("%d",&ssp);
switch(ssp){
case 1:{
test_space(pcb);
break;
}
case 2:{
test_ready(pcb,j);
break;
}
case 3:{
space_rest=space_number(pcb);
printf("请输入创建的进程数目:");
scanf("%d",&xpz);
if(xpz<=space_rest){
for(aa=1;aa<=xpz;aa++)
c=creat_pcb(pcb,i,j,c); //创建进程,并返回花费时间
}
else{
printf("\t\t\t\t空闲pcb块不够多,无法创建新进程!\n");
}
break;
}
case 4:{
bb=space_last(pcb);
c=ready_to_run(pcb,j,bb,time,c);
test_ready(pcb,j);
break;
}
case 5:{
show_ready(pcb,j);
break;
}
case 6:{
system("cls");
break;
}
case 7:{
ssp=-1;
break;
}
default:{
printf("\t\t\t\t不规范,请重新选择!");
break;
}
}
}
}
else{
printf("\t\t\t\t值不规范,程序将自动退出!");
}
}
三、总结
这是在之前那一篇的基础上修改过来的,调用一次仅仅运行一个进程,进程的时间片用完后就回到就绪态的队尾。因为之前写的源程序是运行一次后就将整个就绪态里的进程都运行,直到全部运行完一遍后或者遇到工作完成的pcb块时才停止工作。然后,被老师说应该要一次运行一个程序才好,就在此基础上做了改进。