操作系统作业02
来源:互联网 发布:tcl网络电视怎么打开 编辑:程序博客网 时间:2024/05/22 01:21
操作系统作业02
题目
请编写一个程序,模拟若干进程调度执行的情况。假设进程的状态分为执行和就绪两种。每个进程以其PCB为代表即可,无需创建真正的进程。
以链表的方式组织PCB,分为三个队列: freeQueue:一个空白PCB队列 readyQueue:一个就绪队列
runningQueue:一个执行队列程序开始运行时,用户输入进程数量n,以及每个进程需要运行的时间t0/t1/…/tn。程序从空白PCB队列中取出PCB创建进程,插入readyQueue。
进程的调度采用随机的方式,即从就绪队列中随机选择一个进程投入运行(就是将该PCB中的状态变量赋值为“运行”)。相应的修改其所在队列,并且原来处于运行态的进程需要转变为“就绪”态,插入readyQueue。
假设时间片是2,进程每次调度运行后,其还需运行的时间应该减少2,直至为0,即表示该进程执行完毕。需要回收PCB到freeQueue。
每次发生调度的时候,需要打印信息示例: Sched: P0(Running -> Ready), P3(Ready -> Running)
Running: P3 Ready: P1->P2->P0
上述信息表示调度时P0处于运行态,选择P3运行,P0进程的PCB进入就绪队列,并且在队尾。就绪队列是按照队列节点次序输出进程名称。
示例片段代码:#define free 0
#define ready 1
#define running 2
#define ts 2 /* time slice */ struct PCB {
int pid; /* 进程ID */
int pstate; /* 进程状态 */
char pname; / 映象名称 */
int ptime; /* 剩余运行时间 */
struct PCB pnext; / 下一个PCB */ }
代码实现
#include<stdio.h>#include<malloc.h>#include <string.h>#include<stdlib.h>#include<time.h>#define free 0#define ready 1#define running 2#define ts 2 /* time slice */struct PCB { int pid; /* 进程ID */ int pstate; /* 进程状态 */ char pname[20]; /* 映象名称 */ int ptime; /* 剩余运行时间 */ struct PCB *pnext; /* 下一个PCB */};/*产生随机数并用于随机调度*/int PCBchange(int isEmpty[],int run,int PCB_num){ int lrun = rand()%PCB_num; while(run==lrun || isEmpty[lrun]<0){ //获取随机调度目标id,并防止重复 lrun = rand()%PCB_num; } return lrun;}/*在就绪队列查找调度目标并完成切换*/struct PCB * findAndSwitch(int Id,struct PCB * tp,struct PCB * sp){ struct PCB * getP; struct PCB * temp; getP = tp; //寻找调度进程的位置 while(getP->pnext!=NULL&&getP->pnext->pid != Id){ getP = getP->pnext; } /*就绪队列以及运行队列的进程切换*/ temp = getP->pnext; if(temp->pnext!=NULL){ getP->pnext = temp->pnext; //readyQueue链表操作 }else{ getP->pnext = NULL; } getP = sp->pnext; sp->pnext = temp; //连接到running链表中 temp->pnext = NULL; //清零后续位 return getP;}/*输出readyQueue*/void outputReady(struct PCB* tp){ struct PCB* getP; printf("Ready:"); if(tp->pnext!= NULL){ getP = tp->pnext; printf("%s",getP->pname); //输出首个元素 getP = getP->pnext; while(getP!=NULL){ //循环输出后续元素 printf("->%s",getP->pname); getP = getP->pnext; } printf("\n"); }else printf("NULL\n");}int main(){ struct PCB * freeQueue = (struct PCB*)malloc(sizeof(struct PCB)); struct PCB * readyQueue = (struct PCB*)malloc(sizeof(struct PCB)); struct PCB * runningQueue = (struct PCB*)malloc(sizeof(struct PCB)); struct PCB * temp; //辅助操作指针 struct PCB * getP; //同上 int PCB_num; //储存进程数量 char str[10]; //初始化各进程name int isEmpty[50]={0}; //记录各进程是否执行完毕的数组 int i=0; //辅助参数 int run=-1; //储存随机调度目标id int counter = 0; //记录已运行完毕进程的数量 int isComplete=1; //主循环是否继续的标志位 srand((unsigned) time(NULL)); //产生种子用于随机调度 /*初始化POB*/ runningQueue->pnext = NULL; printf("请输入进程数量:"); scanf("%d",&PCB_num); printf("请依次输入每个进程运行耗时:"); getP = freeQueue; for(i;i<PCB_num;i ){ temp = (struct PCB*)malloc(sizeof(struct PCB)); //请求动态储存空间 temp->pid = i; //记录id temp->pstate = 0; //初始化状态 sprintf(str, "%d" , i); //name操作 memset(temp->pname, 0, 20); //初始化字符串 temp->pname[0] = 'P'; strcat(temp->pname, str); scanf("%d",&(temp->ptime)); //输入进程运行所需时间 temp->pnext = NULL; //初始化pnext指针 getP->pnext = temp; //链表连接 getP = getP->pnext; isEmpty[i] = i; //初始化记录数组 } /*转换到就绪队列*/ readyQueue->pnext = freeQueue->pnext; //进入就绪队列 freeQueue->pnext = NULL; /*运行并随机调度*/ while(isComplete){ run = PCBchange(isEmpty, run, PCB_num); //获取随机值 if(runningQueue->pnext==NULL){ /*首次运行*/ getP = findAndSwitch(run,readyQueue,runningQueue); //定位目标进程并完成切换 /*输出*/ printf("Sched:%s(Ready->Running)\n",runningQueue->pnext->pname); printf("Running:%s\n",runningQueue->pnext->pname); outputReady(readyQueue); } /*判断调度是否是自己*/// else if(run==runningQueue->pnext->pid){// printf("Sched:%s(Running->Runing)\n",runningQueue->pnext->pname);// printf("Running:%s\n",runningQueue->pnext->pname);// outputReady(readyQueue);// } /*后续运行*/ else{ getP = findAndSwitch(run, readyQueue, runningQueue); //定位目标进程并完成切换 temp = readyQueue; //连接到readyQueue链表尾部 while(temp->pnext!=NULL) temp = temp->pnext; temp->pnext = getP; //将进入就绪队列的进程放在队尾 /*输出*/ printf("Sche:%s(Running->Ready),%s(ready->Running)\n", getP->pname,runningQueue->pnext->pname); printf("Running:%s\n", runningQueue->pnext->pname); outputReady(readyQueue); } runningQueue->pnext->ptime -= 2; //进程时间-2 /*将就绪队列中运行完毕的进程转到空队列*/ for(i=0;i<PCB_num; i){ if(isEmpty[i] == -1) { isEmpty[i] = -2; temp = readyQueue; while(temp->pnext->pid != i) temp = temp->pnext; if(temp->pnext!=NULL){ getP = temp->pnext; temp->pnext = getP->pnext; }else{ getP = temp->pnext; temp->pnext = NULL; } getP->pnext = freeQueue->pnext; //free链表连接 freeQueue ->pnext = getP; printf("Sche:%s(Ready->free)\n",getP->pname); counter ; //已完成进程数量加一 } } if(runningQueue->pnext->ptime<=0){ //判断运行进程是否运行完毕 isEmpty[run] = -1; } if(counter == PCB_num-1){ //判断所有进程是否运行完毕 printf("Sche:%s(Ready->free)\n",runningQueue->pnext->pname); isComplete = 0; } } return 0;}
运行结果
小结
本次作业,发现了很多不足,比如在链表操作时经常遇到空指针问题,代表自己的指针操作还是不甚熟料,同时,犯了上手就写代码的错误,导致后期很多链表操作的代码重复,以至于后期不易调试导致我几乎重写把链表全都封到函数中,不过就算现在的代码逻辑也不是很清晰,下次一定要先构思再下手
- 操作系统作业02
- 操作系统作业
- 操作系统作业
- 操作系统作业
- 操作系统作业存储
- Linux操作系统作业
- 操作系统大作业笔记
- 操作系统第二章作业
- 操作系统--作业管理
- 操作系统 : 第一周作业
- 操作系统作业管理
- 操作系统第三次作业
- 操作系统第四次作业
- 【操作系统】作业管理
- 操作系统作业动态分区
- 操作系统五六章作业答案
- 操作系统作业03
- 操作系统作业04
- 17. Letter Combinations of a Phone Number
- Mybatis基本配置
- 14 Hive shell 命令 DML命令
- python学习笔记(六):字符串(三)
- socket.io各种API
- 操作系统作业02
- C++多态性总结
- Linux工作管理与系统资源查看详解
- 孙鑫MFC教程15课在VS2013
- http协议工作流程
- Hibernate-开发环境搭建(1)
- 百度的招聘广告为何比小米差 人工智能告诉你
- 15. 3Sum
- readlines and readline的区别