标签:
实验二 进程调度
一、 实验目的
1. 理解进程运行的并发性。
2. 理解处理器的三级调度。
3. 掌握先来先服务的进程调度算法。
4. 掌握短进程优先的进程调度算法。
5. 掌握时间片轮转的进程调度算法。
二、 实验设备
1. 安装windows或者linux操作系统的PC机
2. C程序编译环境
三、 实验内容
用c语言编程模拟实现至少一个操作系统的常见进程调度算法。常见的进程调度算法有先来先服务、短进程优先、时间片轮转法等。
四、 实验要求
1. 上机编写并调试进程调度的模拟程序。
2. 要把相应的程序代码及程序运行结果写入实验报告中。
//操作系统—进制控制模拟 #include<stdio.h> #include<stdlib.h> #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); }
操作系统实验二(调度算法模拟-先进先出-时间片轮转法-优先服务调度算法)
标签:
原文地址:http://blog.csdn.net/goodluckac/article/details/51510368