驱动调度.docx
《驱动调度.docx》由会员分享,可在线阅读,更多相关《驱动调度.docx(26页珍藏版)》请在冰豆网上搜索。
驱动调度
驱动调度
1实验目的
磁盘是一种高速、大容量、旋转型、可直接存取的存储设备。
它作为计算机系统的辅助存储器,担负着繁重的输入输出任务、在多道程序设计系统中,往往同时会有若干个要求访问磁盘的输入输出请求等待处理。
系统可采用一种策略,尽可能按最佳次序执行要求访问磁盘的诸输入输出请求。
这就叫驱动调度,使用的算法称为驱动调度算法。
驱动调度能降低为若干个输入输出请求服务所需的总时间,从而提高系统效率。
2设置初始条件
1、操作系统:
windows
2、程序设计语言:
C++
3功能描述
模拟电梯调度算法,实现对磁盘的驱动调度。
4方案论证
4.1数据结构设计
typedefstructProcess//描述进程信息
{
charname[N];//进程名
intcyl_num;//柱面号
inttra_num;//磁道号
intrec_num;//物理记录号
intsignal;//标记,用以判断结构体数组中该元素是否有效
}process;
4.2算法设计
函数模块
各函数调用关系如图1所示,箭头指向被调用的函数
各函数功能及流程图如下:
4.2.1主函数:
voidmain()
函数功能:
显示提示信息,初始化进程数组,根据随机数的值选择调用驱动调度和接收请求或者选择继续和退出程序
入口参数:
无
出口参数:
无
流程图:
如图2所示
4.2.2随机数函数:
floatRan_Num()
函数功能:
接收随机数
入口参数:
无
出口参数:
接收进来的随机数
流程图:
无
4.2.3接收请求函数:
voidlist(intpro_count,intpro_num,processpro[M])
函数功能:
存放输入的进程信息,创建等待进程列表
入口参数:
初始化后的进程数组
出口参数:
无
流程图:
如图3所示
4.2.4旋转调度函数:
voidcir_sec(processpro[M])
函数功能:
如果有请求与当前柱面号相同,进行旋转调度,选择旋转距离最小的进程
入口参数:
部分全局变量及进程数组
出口参数:
选择的数组元素编号
流程图:
如图4所示
4.2.5移臂调度函数:
voidmov_sec(processpro[M])
函数功能:
没有与当前柱面号相同的访问请求时,进行移臂调度
入口参数:
进程数组
出口参数:
选择的数组元素编号
流程图:
如图5所示
4.2.6驱动调度函数:
voiddri_sch(intpro_count,processpro[M])
函数功能:
进行进程调度,按照电梯调度算法选择进程
入口参数:
当前有效进程数、进程数组
出口参数:
无
流程图:
如图6所示
5设计结果与分析
5.1运行结果如下
图7初始状态
图8输入5个进程的相关信息
图9第一次选择后结果
图10第二次选择后结果
图11第三次选择后结果
图12第四次选择后结果
图13第五次选择后,进程等待表为空
图14再输入3个进程及相关信息
图15再次输入后第一次选择
图16再次输入后第二次选择
图17第三次选择后等待表为空,选择退出
5.2结果分析
5.2.1初始状态,结果如图7所示
5.2.2输入0.4,输入进程数据并选择继续,结果如图8所示
5.2.3重复选择继续,输入0.6进行驱动调度直到等待进程表为空,结果如图9~图13所示
第一次选择P5
第二次选择P3
第三次选择P1
第四次选择P4
第五次选择P2,当前等待表为空
5.2.4选择继续,输入0.4,再输入3个进程,结果如图14所示
5.2.5重复选择继续进行驱动调度至等待进程表为空,然后选择退出,结果如图15~图17所示
第一次选择P8
第二次选择P6
第三次选择P7,当前等待表为空,选择退出
6课设总结
1、通过设计数据结构进程访问磁盘,我进一步了解了磁盘存储器的物理结构,对电梯算法有深入的了解。
2、刚刚开始进行实习设计时,对题目没有进行正确的理解就忙于写代码,算法设计考虑的很不全面,从而导致后来实验数据出错,通过再次审查题目及资料,我了解了题目要求,对算法进行了重新设计,最终完成了试验,得出了正确的运行结果。
3、在调试的过程中出现了很多的问题,从语法到算法中的错误,通过向老师和同学请教以及查阅资料,解决了这些问题,使我对编程语句及算法设计有了更深的认识。
编程是很严谨的事情,不容半点马虎,即使是一个括号也可能导致程序的错误。
7参考文献
[1]谢宋和,甘勇.单片机模糊控制系统设计与应用实例[M].北京:
电子工业出版社,1999.5:
20-25
[2]潘新民,王燕芳.微型计算机控制技术[M],第2版.北京:
电子工业出版社,2003.4:
305-350
[3]范立南,谢子殿.单片机原理及应用教程[M].北京:
北京大学出版社,2006.1:
123-130
[4]NewmanWM,SbroullRF.PrinciplesofInteractiveComputerGraphics[M].NewYork:
McGrawHill,1979.10:
10-25
[5]卜小明,龙全求.一种薄板弯曲问题的四边形位移单元[J].力学学报,1991,23
(1):
53-60
[6]MastriAR.Neuropathyofdiabeticneurogenicbladder[J].AnnInternMed,1980,92
(2):
316-318
[7]范立南,韩晓微,王忠石等.基于多结构元的噪声污染灰度图像边缘检测研究[J].武汉大学学报(工学版),2003,49(3):
45-49
[8]index.asp
8源程序代码
pro_struct.h
#ifndefPRO_STRUCT_H
#definePRO_STRUCT_H
#defineN10
typedefstructProcess
{
charname[N];//进程名
intcyl_num;//请求的柱面号
inttra_num;//请求的磁道号
intrec_num;//请求的物理记录号
intsignal;//标记位
}process;
#endif
pro_list.h
#ifndefPRO_LIST_H
#definePRO_LIST_H
#include
#include
#include"pro_struct.h"
usingnamespacestd;
#defineM100
voidlist(intpro_count,intpro_num,processpro[M])//创建等待进程表
{
cout<<"等待的进程数:
";
cin>>pro_num;
if(pro_num>0&&(pro_num+pro_count)<=M)//判断要输入的进程数是否合法,输入后是否超出进程等待表所允许的最大值
{
cout<<"开始输入"<inti,j=0,h;
for(i=0;i{
for(;pro[i].signal==0&&j{
cin>>pro[i].name>>pro[i].cyl_num>>pro[i].tra_num>>pro[i].rec_num;
for(h=0;h{
if(pro[h].signal==1)
{
while(strcmp(pro[h].name,pro[i].name)==0||strlen(pro[i].name)>10)
{
cout<<"进程名不合规定,超出指定长度或已存在,请重新输入进程名:
"<cin>>pro[i].name;
}
}
}
while(pro[i].cyl_num<0||pro[i].cyl_num>199)//判断柱面号是否越界
{
cout<<"柱面号不合规定,请重新输入柱面号:
"<cin>>pro[i].cyl_num;
}
while(pro[i].tra_num<0||pro[i].tra_num>19)//判断磁道号是否越界
{
cout<<"磁道号不合规定,请重新输入磁道号:
"<cin>>pro[i].tra_num;
}
while(pro[i].rec_num<0||pro[i].rec_num>7)//判断物理记录号是否越界
{
cout<<"物理记录号不合规定,请重新输入物理记录号:
"<cin>>pro[i].rec_num;
}
pro[i].signal=1;
}
}
}
else
{
if(pro_num<=0)
{
cout<<"要输入的进程个数必须为正整数"<}
else
{
cout<<"进程数超出进程等待表所允许的最大量"<cout<<"当前最多允许输入"<<(M-pro_count)<<"个进程"<}
}
}
#endif
Driver_Scheduling.h
#include
#include
#include"pro_list.h"
#include"pro_struct.h"
intdir=0;//0,up向里;1,down向外
intcylinder=0;
intrecord=0;
intmin_rec=0;//移动到当前进程扇区所要移动的距离
intmin_r=8;//旋转调度中最小移动距离
intmax_min_cyl=200;//大于当前柱面号的访问请求中的最小者
intmin_min_cyl=200;//小于当前柱面号的访问请求中的最小者
intx;
intchoosen=0;//被选中的进程
voidcir_sec(processpro[M])//旋转调度
{
if(pro[x].rec_nummin_rec=8-(record-pro[x].rec_num);
else
min_rec=pro[x].rec_num-record;
if(min_rec<=min_r)//首选移动距离最小,再选磁盘号最小
{
min_r=min_rec;//选择移动距离最小的请求
choosen=x;
}
}
voidmov_sec(processpro[M])//移臂调度
{
intcount_abo=0;
intcount_low=0;
if(dir==0)//如果方向向里up
{
for(x=0;x{
if(pro[x].signal==1)
{
if(pro[x].cyl_num>cylinder)
count_abo++;
}
}
if(count_abo>0)//有进程柱面号大于当前柱面号
{
for(x=0;x{
if(pro[x].signal==1)
{
if(pro[x].cyl_num>cylinder&&pro[x].cyl_num{
max_min_cyl=pro[x].cyl_num;
choosen=x;
}
}
}
for(x=0;x{
if(pro[x].signal==1)
{
if(pro[x].cyl_num==max_min_cyl)//从大于当前柱面号的访问请求中选择一个最小者
{
cir_sec(pro);//旋转调度
}
}
}
}
else
{
dir=1;//改方向为向外,down
for(x=0;x{
if(pro[x].signal==1)
{
if(pro[x].cyl_num{
min_min_cyl=pro[x].cyl_num;
choosen=x;
}
}
}
for(x=0;x{
if(pro[x].signal==1)
{
if(pro[x].cyl_num==min_min_cyl)
{
cir_sec(pro);//旋转调度
}
}
}
}
}
else
{
for(x=0;x{
if(pro[x].signal==1)
{
if(pro[x].cyl_numcount_low++;
}
}
if(count_low>0)//有进程柱面号大于当前柱面号
{
for(x=0;x{
if(pro[x].signal==1)
{
if(pro[x].cyl_num{
min_min_cyl=pro[x].cyl_num;
choosen=x;
}
}
}
for(x=0;x{
if(pro[x].signal==1)
{
if(pro[x].cyl_num=min_min_cyl)
{
cir_sec(pro);//旋转调度
}
}
}
}
else
{
dir=0;//改方向为向里up
for(x=0;x{
if(pro[x].signal==1)
{
if(pro[x].cyl_num>cylinder&&pro[x].cyl_num{
max_min_cyl=pro[x].cyl_num;
choosen=x;
}
}
}
for(x=0;x{
if(pro[x].signal==1)
{
if(pro[x].cyl_num==max_min_cyl)//从大于当前柱面号的访问请求中选择一个最小者
{
cir_sec(pro);//旋转调度
}
}
}
}
}
}
voiddri_sch(intpro_count,processpro[M])//电梯调度
{
max_min_cyl=200;//大于当前柱面号的访问请求中的最小者
min_min_cyl=200;//小于当前柱面号的访问请求中的最小者
min_r=8;
choosen=0;
intcount_equ=0;
if(pro_count!
=0)//有等待访问的进程
{
cout<<"当前请求I/O表为:
"<cout<<"┌─────────────────┐"<cout<<"│进程名│柱面号│磁道号│物理记录号│"<cout<<"└─────────────────┙"<cout.setf(ios:
:
left);
for(x=0;x{
if(pro[x].signal==1)
{
cout<<""<}
}
cout.unsetf(ios:
:
left);
for(x=0;x{
if(pro[x].signal==1)
if(pro[x].cyl_num==cylinder)//有进程柱面号等于当前柱面号
count_equ++;
}
if(count_equ>0)
{
for(x=0;x{
if(pro[x].signal==1)
{
if(pro[x].cyl_num==cylinder)
{
cir_sec(pro);//旋转调度
}
}
}
}
else
{
mov_sec(pro);//移臂调度
}
cylinder=pro[choosen].cyl_num;
record=pro[choosen].rec_num;
pro[choosen].signal=0;
if(dir==0)
{
cout<<"选择的进程为:
"<cout<<"┌────────────────┐"<cout<<"│进程名│柱面号│物理记录号│方向│"<cout<<"└────────────────┙"<cout.setf(ios:
:
left);
cout<<""<cout.unsetf(ios:
:
left);
}
else
{
cout<<"选择的进程为:
"<cout<<"┌────────────────┐"<cout<<"│进程名│柱面号│物理记录号│方向│"<cout<<"└────────────────┙"<cout.setf(ios:
:
left);
cout<<""<cout.unsetf(ios:
:
left);
}
}
else
cout<<"请求I/O表为空"<}
ran_num.h
#include
floatRan_Num()
{
floatran_num;
/*floati;
i=float(rand());
if(i==0||1)
ran_num=i;
else
ran_num=1/i;*/
cout<<"输入随机数[0,1]:
"<cout<<"随机数>0.5时转入电梯调度"<cout<<"随机数<=0.5时转入接收请求"<cin>>ran_num;
return(ran_num);
}
qddd.cpp
#include
#include"Driver_Scheduling.h"
#include"pro_list.h"
#include"pro_struct.h"
#include"ran_num.h"
usingnamespacestd;
voidmain()
{
cout<<"***************************************************************************"<cout<<"请按照如下顺序输入各进程信息,以空格分开,每条进程信息输入完成后按回车键结束:
"<cout<<"进程名柱面号磁道号物理记录号"<cout<<"注:
进程名不超过10个字符,柱面号为0-199,磁道号为0-19,物理记录号为0-7"<cout<<"***************************************************************************"<inti;
processpro[M];//创建进程数组
for(i=0;i{
pro[i].signal=0;
}
intpro_num=0;
charsignal='Y';
intpro_count;//进程等待表中进程数
while(signal=='Y'||signal=='y')
{
if(Ran_Num()>0.5)//如果随即数大于0.5,转到调度模块
{
pro_count=0;
for(i=0;i{
if(pro[i].signal==1)
pro_count++;//统计进程等代表中有效进程数
}
dri_sch(pro_count,pro);
}
else//若随机数小于等于0.5,转到接受请求,即创建等待进程表
{
pro_count=0;
list(pro_count,pro_num,pro);
}
cout<";
cin>>signal;