《操作系统》实验报告——进程调度的模拟
实验内容
熟悉进程调度的各种算法,并对模拟程序给出数据和流程的详细分析,之后画出流程图,最后参考模拟程序写出时间片轮转调度算法的程序。
实验目的
通过本实验,加深对进程调度算法原理和过程的理解。
实验要求
(1) 对调度算法进行详细分析,在仔细分析的基础上,完全理解主要数据结构和过程的作用,给出主要数据结构的说明及画出主要模块的流程图。
(2) 根据提示信息,把函数写完整,使成为一个可运行程序。
(3) 反复运行程序,观察程序执行的结果,验证分析的正确性,然后给出一次执行的最后运行结果,并由结果计算出周转时间和带权周转时间。
说明:进程生命周期数据。即CPU-I/O时间序列,它是进程运行过程中进行调度、进入不同队列的依据。
如序列:10秒(CPU),500秒(I/O),20秒(CPU),100秒(I/O),30秒(CPU),90秒(I/O),110秒(CPU),60秒(I/O)……,此序列在进程创建时要求自动生成。
源代码
#include <windows.h>
#include<iostream>
#include<fstream>
#include <conio.h>
#include <stdlib.h>
#include <io.h>
#include <string.h>
#include <stdio.h>
using namespace std;
struct ProcStruct
{int p_pid; // 进程的标识号char p_state; // 进程的状态,C--运行 R--就绪 W--组塞 B--后备 F--完成int p_rserial[10]; // 模拟的进程执行的CPU和I/O时间数据序列,间隔存储,第0项存储随后序列的长度(项数),以便知晓啥时该进程执行结束int p_pos; // 当前进程运行到的位置,用来记忆执行到序列中的哪项int p_starttime; // 进程建立时间int p_endtime; // 进程运行结束时间int p_cputime; // 当前运行时间段进程剩余的需要运行时间int p_iotime; // 当前I/O时间段进程剩余的I/O时间int p_next; // 进程控制块的链接指针
} proc[10];
int RunPoint; // 运行进程指针,-1时为没有运行进程
int WaitPoint; // 阻塞队列指针,-1时为没有阻塞进程
int ReadyPoint; // 就绪队列指针,-1时为没有就绪进程
long ClockNumber; // 系统时钟
int ProcNumber; // 系统中模拟产生的进程总数
int FinishedProc; // 系统中目前已执行完毕的进程总数// 显示进程数据序列void DisData()
{ofstream outFile; //同时将该信息写入磁盘的某txt文件中 ,该函数要#include <fstream.h>outFile.open("1_Process_Info.txt") ; //该txt 文件名可自己命名,第1次open时磁盘 中没有该文件,系统会创建一个空白的。for(int i=0; i<ProcNumber; i++) { //写到txt文件中outFile<< "ID=" << proc[i].p_pid <<"(len="<<proc[i].p_rserial[0]<<",start="<<proc[i].p_starttime<<"):";for(int j=1; j<=proc[i].p_rserial[0];j++)outFile<<" "<<proc[i].p_rserial[j];outFile<<"\n"; //打印到屏幕上 cout<< "ID=" << proc[i].p_pid <<"(len="<<proc[i].p_rserial[0]<<",start="<<proc[i].p_starttime<<"):";for(int j=1; j<=proc[i].p_rserial[0];j++)cout<<" "<<proc[i].p_rserial[j];cout<<"\n"; }outFile.close(); // 写入txt文件的流被冲刷,保存到磁盘上
}// //
// 随机生成进程数量和每个CPU--I/O时间数据序列,进程数量控制在5到10之间, //
// 数据序列控制在6到12之间,CPU和I/O的时间数据值在5到15的范围 //
// //void Create_ProcInfo(void ) {int s,i,j;srand(GetTickCount()); // 初始化随机数队列的"种子"ProcNumber=((float) rand() / 32767) * 5 + 5; // 随机产生进程数量5~10FinishedProc=0;for(i=0;i<ProcNumber;i++) // 生成进程的CPU--I/O时间数据序列{ proc[i].p_pid=((float) rand() / 32767) * 1000;proc[i].p_state='B'; // 初始都为后备状态s=((float) rand() / 32767) *6 + 6; // 产生的进程数据序列长度在6~12间proc[i].p_rserial[0]=s; // 第一项用于记录序列的长度for(j=1;j<=s;j++) // 生成时间数据序列,数值在10~30间proc[i].p_rserial[j]=((float) rand() / 32767) *10 + 5;// 赋其他字段的值proc[i].p_pos=1;proc[i].p_starttime=((float) rand() / 32767) *49+1;proc[i].p_endtime=0; proc[i].p_cputime=proc[i].p_rserial[1]; proc[i].p_iotime=proc[i].p_rserial[2]; proc[i].p_next=-1; }printf("\n---------------------------\n 建立了%d个进程数据序列\n\n", ProcNumber);DisData();printf("\nPress Any Key To Continue.......");_getch() ; return ;
}// 从磁盘读取最后一次生成的进程信息的文件,执行调度,以重现调度情况。void Read_Process_Info()
{ifstream inFile; // 定义打开文件的文件流char ch; int i,j,k,tmp; inFile.open("Process_Info.txt") ; // 打开上次写的txt进行信息文件流i=0;while(inFile){ inFile.get(ch);for(j=0;j<3;j++) inFile.get(ch);//扔掉3个字符, inFile>>proc[i].p_pid;for(j=0;j<5;j++) inFile.get(ch);//继续读,扔掉5个字符inFile>>proc[i].p_rserial[0];for(j=0;j<7;j++) inFile.get(ch);//继续读,扔掉7个字符inFile>>proc[i].p_starttime;for(j=0;j<2;j++) inFile.get(ch);//继续读,扔掉2个字符for(k=1;k<=proc[i].p_rserial[0];k++){inFile>>tmp; proc[i].p_rserial[k]=tmp;} proc[i].p_state='B';proc[i].p_pos=1;proc[i].p_endtime=0; proc[i].p_next=-1; proc[i].p_cputime=proc[i].p_rserial[1]; proc[i].p_iotime=proc[i].p_rserial[2]; i++; //本行结束,一个进程信息读完,序号+1, 准备 next process }ProcNumber=i-1; //给ProcNumber赋值,i最后有++,回位下inFile.close();//完工后,记得归位,关灯。
}// 检查是否有新进程到达,有则放入就绪队列void NewReadyProc(void)
{ int n;for(int i=0; i<ProcNumber; i++) { if (proc[i].p_starttime == ClockNumber) // 进程进入时间达到系统时间,ClockNumber是当前的系统时间{ proc[i].p_state='R'; // 进程状态修改为就绪 proc[i].p_next=-1; // 该进行即将要挂在队列末尾,它肯定是尾巴,后面没人的,所以先设置next=-1if (ReadyPoint==-1) // 如果当前就绪队列无进程ReadyPoint=i;else // 如果就绪队列有进程,放入队列尾{ n=ReadyPoint; while(proc[n].p_next!=-1) n=proc[n].p_next; //找到原来队伍中的尾巴proc[n].p_next=i; //挂在这个尾巴后面}}}
}// 选择下一个可以运行的进程void NextRunProcess(){if (ReadyPoint==-1) { RunPoint = -1; return;} // 就绪队列也没有等待的进程proc[ReadyPoint].p_state ='C'; RunPoint=ReadyPoint; proc[ReadyPoint].p_cputime =proc[ReadyPoint].p_rserial[proc[ReadyPoint].p_pos] ; ReadyPoint=proc[ReadyPoint].p_next;proc[RunPoint].p_next = -1;
}// CPU调度void Cpu_Sched(void)
{ int n;if (RunPoint == -1) // 没有进程在CPU上执行{ NextRunProcess(); return; }proc[RunPoint].p_cputime--; // 进程CPU执行时间减少1个时钟单位if (proc[RunPoint].p_cputime > 0) return; // 还需要CPU时间,下次继续,这次就返回了//如果不满足以上>0的条件,就意味着=0,就不会自动返回,接着做以下事情。
// 进程完成本次CPU后的处理if (proc[RunPoint].p_rserial[0]==proc[RunPoint].p_pos) //进程全部序列执行完成{ FinishedProc++;proc[RunPoint].p_state ='F';proc[RunPoint].p_endtime = ClockNumber; RunPoint=-1; //无进程执行 NextRunProcess(); //找分派程序去,接着做下一个} else //进行IO操作,进入阻塞队列{proc[RunPoint].p_pos++;proc[RunPoint].p_state ='W';proc[RunPoint].p_iotime =proc[RunPoint].p_rserial[proc[RunPoint].p_pos];proc[n].p_next == -1; //标记下,就自己一个进程,没带尾巴一起来;否则,当p_next不为-1时,后面的那一串都是被阻塞者n=WaitPoint;if(n == -1) //是阻塞队列第一个I/O进程WaitPoint=RunPoint; else{ do //放入阻塞队列第尾{if(proc[n].p_next == -1) { proc[n].p_next = RunPoint; break;}n=proc[n].p_next;} while(n!=-1) ;}RunPoint=-1; NextRunProcess(); }return;
}// 显示系统当前状态void Display_ProcInfo( )
{ int n;system("cls") ;printf("\n 当前系统模拟%2d个进程的运行时钟:%ld\n\n", ProcNumber,ClockNumber);printf(" 就绪指针=%d, 运行指针=%d, 阻塞指针=%d\n\n",ReadyPoint,RunPoint,WaitPoint);if(RunPoint!= -1){//Print 当前运行的进程的信息;printf(" .............Running Process .............\n ");printf("当前运行的进程 No.%d ID:%d(%2d,%2d)", RunPoint,proc[RunPoint].p_pid,proc[RunPoint].p_rserial[0],proc[RunPoint].p_starttime);printf(" 总CPU时间=%d, 剩余CPU时间=%d\n",proc[RunPoint].p_rserial[proc[RunPoint].p_pos],proc[RunPoint].p_cputime);}elseprintf("No Process Running !\n");n=ReadyPoint;printf("\n Ready Process ...... \n");while(n!=-1) // 显示就绪进程信息{printf(" [No.%2d ID:%4d],%d,%d,%d\n",n,proc[n].p_pid,proc[n].p_starttime,proc[n].p_rserial[proc[n].p_pos],proc[n].p_cputime );n=proc[n].p_next;}n=WaitPoint;printf("\n Waiting Process ...... \n");while(n!=-1) // 显示阻塞进程信息{ printf(" [No.%2d ID:%4d],%d,%d,%d\n",n,proc[n].p_pid,proc[n].p_starttime,proc[n].p_rserial[proc[n].p_pos],proc[n].p_iotime);n=proc[n].p_next; }printf("\n=================== 后备进程 ====================\n");for(int i=0; i<ProcNumber; i++) if (proc[i].p_state=='B')printf(" [No.%2d ID:%4d],%d\n",i,proc[i].p_pid,proc[i].p_starttime); printf("\n================ 已经完成的进程 =================\n");for(int i=0; i<ProcNumber; i++) if (proc[i].p_state=='F')printf(" [No.%2d ID:%4d],%d,%d\n",i,proc[i].p_pid,proc[i].p_starttime,proc[i].p_endtime);}// I/O调度void IO_Sched(){int n,bk;if (WaitPoint==-1) return; // 没有等待I/O的进程,直接返回proc[WaitPoint].p_iotime--; // 进行1个时钟的I/O时间 if (proc[WaitPoint].p_iotime > 0) return; // 还没有完成本次I/O// 进程的I/O完成处理if (proc[WaitPoint].p_rserial[0]==proc[WaitPoint].p_pos) //进程全部任务执行完成{ FinishedProc++;proc[WaitPoint].p_endtime = ClockNumber;proc[WaitPoint].p_state ='F';if(proc[WaitPoint].p_next==-1){ WaitPoint=-1;return ;}else //调度下一个进程进行I/O操作{n=proc[WaitPoint].p_next;proc[WaitPoint].p_next=-1;WaitPoint=n;proc[WaitPoint].p_iotime =proc[WaitPoint].p_rserial[proc[WaitPoint].p_pos] ;return ;}}else //进行下次CPU操作,进就绪队列{bk=WaitPoint;WaitPoint=proc[WaitPoint].p_next;proc[bk].p_pos++;proc[bk].p_state ='R'; //进程状态为就绪proc[bk].p_next =-1;n=ReadyPoint; if(n == -1) //是就绪队列的第一个进程{ ReadyPoint=bk; return; } else{ do {if(proc[n].p_next == -1) { proc[n].p_next = bk; break ; }n=proc[n].p_next;}while(n!=-1); }}return ;
}// 显示模拟执行的结果void DisResult(){int i; printf("\n---------------------------------\n");printf("标识号-时间序列-建立时间-结束时间-周转时间-带权周转时间\n");for(i=0; i<ProcNumber; i++) { printf("ID=%d -> %d\t",proc[i].p_pid ,proc[i].p_rserial[0] );printf("%d\t%d\t",proc[i].p_starttime,proc[i].p_endtime);printf("%d\t",proc[i].p_endtime-proc[i].p_starttime);int sumtime=0;for(int j=1; j<=proc[i].p_rserial[0];j++)sumtime+=proc[i].p_rserial[j];printf("%.2f",(proc[i].p_endtime-proc[i].p_starttime)*1.0/sumtime);printf("\n" );}
}// 调度模拟算法void Scheduler_FF(void) //调度模拟算法
{if(ProcNumber==0) //该值居然是0? 只能说用户没创建进程{ Read_Process_Info();//那么,从磁盘读取上次创建的进程信息,赋值给相应变量 }ClockNumber=0;// 时钟开始计时, 开始调度模拟while(FinishedProc < ProcNumber){ // 执行算法ClockNumber++; // 时钟前进1个单位NewReadyProc(); // 判别新进程是否到达Cpu_Sched(); // CPU调度IO_Sched(); // IO调度 Display_ProcInfo(); //显示当前状态Sleep(700); }DisResult(); _getch();
}
///// 主函数///
int main( )
{char ch; RunPoint=-1; // 运行进程指针,-1时为没有运行进程WaitPoint=-1; // 阻塞队列指针,-1时为没有阻塞进程ReadyPoint=-1; // 就绪队列指针,-1时为没有就绪进程ClockNumber=0; // 系统时钟ProcNumber=0; // 当前系统中的进程总数system("cls") ;while ( true ) {printf("***********************************\n");printf(" 1: 建立进程调度数据序列 \n") ;printf(" 2: 读进程信息,执行调度算法\n") ; printf(" 3: 显示调度结果 \n") ;printf(" 4: 退出\n") ;printf("***********************************\n");printf( "Enter your choice (1 ~ 4): "); do ch = (char)_getch() ; //如果输入信息不正确,继续输入while(ch != '1' && ch != '2' && ch != '3'&& ch != '4');if(ch == '4') { printf( "\n");return 0; } // 选择4,退出 else if(ch == '3') DisResult(); // 选择3 else if(ch == '2') Scheduler_FF(); // 选择2 else if(ch == '1') Create_ProcInfo(); // 选择1 _getch() ; system("cls") ;}//结束printf("\nPress Any Key To Continue:");_getch() ;return 0;
}
运行结果
参考文章
操作系统实验——进程调度的模拟
实验4 进程调度的模拟
2011 操作系统 实验4 进程调度的模拟(答案Part1)
2011 操作系统 实验4 进程调度的模拟(答案Part2)
2011 操作系统 实验4 进程调度的模拟(源程序)
《操作系统》实验报告——进程调度的模拟相关推荐
- 操作系统实验(进程调度)
操作系统实验(进程调度) 一.实验目的 二.实验内容 三.实验准备 3.1优先权算法 3.2时间片轮转调度算法 四.实验 一.实验目的 1.1理解有关进程控制块.进程队列的概念. 1.2掌握进 ...
- 操作系统实验报告18:硬盘柱面访问调度算法
操作系统实验报告18 实验内容 实验内容:硬盘调度. 编写 C 程序模拟实现课件 Lecture25 中的硬盘柱面访问调度算法 包括 FCFS.SSTF.SCAN.C-SCAN.LOOK.C-LOOK ...
- 操作系统实验报告17:请求页面置换算法
操作系统实验报告17 实验内容 实验内容:虚拟存储管理. 编写一个 C 程序模拟实现课件 Lecture24 中的请求页面置换算法 包括FIFO.LRU (stack and matrix imple ...
- 操作系统实验报告16:CPU 调度
操作系统实验报告16 实验内容 实验内容:CPU 调度. 讨论课件 Lecture19-20 中 CPU 调度算法的例子,尝试基于 POSIX API 设计一个简单调度器(不考虑资源竞争问题): 创建 ...
- 操作系统实验报告1:ucore Lab 1
操作系统实验报告1 实验内容 阅读 uCore 实验项目开始文档 (uCore Lab 0),准备实验平台,熟悉实验工具. uCore Lab 1:系统软件启动过程 (1) 编译运行 uCore La ...
- 计算机操作系统实验之进程调度(一)轮转调度法(C语言)
计算机操作系统实验之进程调度(一)轮转调度法(C语言) 实验目的 实验内容与基本要求 轮转调度法的基本原理 实现思路及功能分析 算法流程图 全部代码 工程图 ProcessScheduling.h P ...
- linux系统编程界面实验报告,操作系统实验报告-Linux操作使用编程.doc
操作系统实验报告-Linux操作使用编程 实 验 报 告( 2012/ 2013 学年 第二学期) 课程名称操 作 系 统A实验名称Linux操作.使用.编程实验时间2013年 5 月 6日指导单位计 ...
- 操作系统实验报告【太原理工大学】
操作系统实验报告 温馨提示:仅供参考! 目录 操作系统实验报告 一.进程调度程序设计 1.程序清单 2.运行结果 3.分析总结 二.页式虚拟存储管理程序设计 1.程序清单 2.运行结果 3.分析总结 ...
- 实验报告Linux操作系统基本命令,linux操作系统实验报告全部.doc
linux操作系统实验报告全部 计算机操作系统 实验报告 学 号:姓 名:提交日期:2014.12.15成 绩: 东北大学秦皇岛分校 [实验题目]熟悉Linux/UNIX操作系统[实验目的]1.熟悉L ...
最新文章
- 如果文件夹不存在,请创建它
- PCA目标函数的推导
- MacOS安装react。问题 -- npm全局包的权限问题
- 给网游写一个挂吧(四) – 调用游戏函数
- dateformat 返回类型_SpringBoot返回date日期格式化
- yy自动语音接待机器人_人脸签到、发言记录,会议机器人来啦
- android 跟随动画,Android实现View拖拽跟随手指移动效果
- linux mysql怎么建数据库用户,Linux MySQL新建用户
- Flink算子(Filter、KeyBy、Reduce和Aggregate)
- java判断浏览器类型_判断浏览器类型
- 智能优化算法(源码)-樽海鞘优化算法(Salp Swarm Algorithm,SSA)
- logitech鼠标接收器配对
- C rgb565转rgb888
- TCA9548A IIC多路扩展模块使用
- R语言实现非线性回归
- kent beck_肯特·沙基(Kent Sharkey)身着“ heezy fo'sheezy babay”!
- Soul向港交所递交上市申请,持续发力社交元宇宙赛道
- 07-HTML5举例:简单的视频播放器
- 如何快速把多个excel表合并成一个excel表(不熟悉vba及公式的人)
- IOS7越狱后无法开机,白苹果恢复固件
热门文章
- 北大poj1018题解题报告
- 让IE6支持图片半透明
- 在SQLSERVER EXPRESS 2005中安装northwind和pubs数据库。
- php 访问网页返回值,Ping网站并用PHP返回结果
- android7.1开机监听广播,Android7.1 Audio Debug相关方法
- mac怎么实现文件读写c语言,使用Sublime Text和Xcode在Mac上进行文件输入/输出。 C语言...
- [设计模式笔记]4.建造者模式
- 计算机网络电缆被拔出是怎么办,网络电缆被拔出是什么意思?网络电缆被拔出的修复办法...
- mysql 结构优化建议_MySQL优化之表结构优化的5大建议(数据类型选择讲的很好)...
- java模拟浏览器不关闭会话_JSP实现浏览器关闭cookies情况下的会话管理