第六次SPOOLING假脱机技术.docx
《第六次SPOOLING假脱机技术.docx》由会员分享,可在线阅读,更多相关《第六次SPOOLING假脱机技术.docx(10页珍藏版)》请在冰豆网上搜索。
![第六次SPOOLING假脱机技术.docx](https://file1.bdocx.com/fileroot1/2022-12/7/7c563d4e-266e-4fa5-86fa-c544abaf5029/7c563d4e-266e-4fa5-86fa-c544abaf50291.gif)
第六次SPOOLING假脱机技术
《操作系统》实验(六)
一、实验目的
理解和掌握SPOOLING假脱机技术。
二、实验内容
SPOOLING假脱机输入\输出技术广泛应用于各种计算机的I/O。
该技术通过采用预输入和缓输出的方法,使用共享设备的一部分空间来模拟独占设备,以提供独占设备的利用率。
为了理解该技术,设计一个SPOOLING假脱机的模拟程序。
三、实验准备
A.开发环境
操作系统WindowsXP,开发工具VC++6.0
B.分析设计
(一)实验原理
1.设计一个实现SPOOLING技术的进程
设计一个SPOOLING输出进程和两个请求输出的用户进程,以及一个SPOOLING输出服务程序。
SPOOLING输出进程工作时,根据请求块记录的各进程要输出的信息,将其实际输出到打印机或显示器。
这里,SPOOLING进程与请求输出的用户进程可并发运行。
2.设计进程调度算法
进程调度采用随机算法,这与进程输出信息的随机性相一致。
两个请求输出的用户进程的调度概率各为45%,SPOOLING输出进程为10%,这由随机数发生器产生的随机数模拟决定。
3.进程状态
进程基本状态有3种,分别为可执行,等待和结束。
可执行态就是进程正在运行或等待调度的状态;等待状态又分为等待状态1,等待状态2,等待状态3。
状态变化的条件为:
1>进程执行完成时,置为“结束”态。
2>服务程序在将输出信息送输出井时,如发现输出井已满,将调用进程置为“等待状态1”。
3>SPOOLING进程在进行输出时,若输出井空,则进入“等待状态2”。
4>SPOOLING进程输出一个信息块后,应立即释放该信息快所占的输出井空间,并将正在等待输出的进程置为“可执行状态”。
5>服务程序在输出信息到输出井并形成输出请求信息块后,若SPOOLING进程处于等待态则将其置为“可执行状态”。
6>当用户进程声请请求输出块时,若没有可用请求块时,调用进程进入“等待状态3”。
(二)程序体系
1.main()函数
1>初始化输入井buffer:
初始化为0
for(i=0;i<2;i++)
for(n=0;n<100;n++)
buffer[i][n]=0;
2>初始化进程控制块pcb:
初始化为以下状态
for(i=0;i<3;i++)
{
structpcb*tmPcb=(structpcb*)malloc(sizeof(structpcb));//开辟空间
tmPcb->id=i;
tmPcb->status=0;//状态
tmPcb->firstaddr=0;
tmPcb->length=0;//长度
tmPcb->outbufword=1;
PCB[i]=tmPcb;
}
3>调度算法:
随机调度:
用户1与用户2的调度概率各为45%,SPOOLING进程输出程序的调度概率为10%
srand((unsigned)time(NULL));//随机函数,利用系统时间做种子
while
(1)
{
i=rand()%100;//产生1到100的随机数
4>重要函数:
voidrequest(inti)和voidspooling()
◆voidrequest(inti):
输出用户请求数据
while
(1)
{
j=rand()%10;
if(j==0)
{
run->length=length;
break;
}
buffer[i-1][(run->addr+length)]=s;//输出请求数据
cout<
s++;
length++;
}
◆voidspooling():
SPOOLING输出程序
for(i=0;ilength;i++)
{
printf("%d",buffer[run->reqname-1][run->addr+i]);
fprintf(f,"%d",buffer[run->reqname-1][run->addr+i]);
}
(三)数据结构:
1>进程控制块PCB
structpcb
{
intstatus;/*进程状态*/
}PCB[3];
2>请求输出块reqblock
struct{
intreuname;
}reqblock[10];
3>输出井BUFFER
SPOOLING系统为每个请求输出的进程在输出井中分别开辟一个区。
本实验可设计一个二维数组(intbuffer[2][10])作为输出井。
每个进程在输出井最多可占用10个位置。
(四)详细分析
为两个请求输出的用户进程设计两个输出井。
每个可存放10个信息,即buffer[2][10]。
当用户进程将其所有文件输出完时,终止运行。
为简单起见,用户进程简单地设计成:
每运行一次,随机输出数字0~9之间的一个数,当输入10个数时形成一个请求信息块,填入请求输出信息块reqblock结构中。
#include
#include
#include
#include
structpcb
{
intid;/*进程标识数*/
intstatus;/*进程状态*/
intfirstaddr;/*信息块首地址*/
intlength;/*本次输出信息长度*/
intoutbufword;/*输出缓冲字*/
}*PCB[3];
FILE*f;
structreq/*请求输出块*/
{
intreqname;/*请求进程名*/
intlength;/*本次输出信息长度*/
intaddr;/*信息在输出井的首地址*/
}reqblock[10];
intbuffer[2][100];
intl1=1,l2=1;
inthead=0,tail=0;
intt1,t2;
voidrequest(inti)/*i为请求输出的进程标识1或2*/
{
intj,length=0,m;
structreq*run;
if(i==1)
{
t1--;
}
else
{
t2--;
}
cout<<"用户"<
\n";
run=&reqblock[tail%10];
run->reqname=i;
run->length=0;
if(tail==0)
{
run->addr=0;
}
else
{
intindex=(tail-1)%10;
run->addr=reqblock[index].addr+reqblock[index].length;
}
for(m=0;m<100;m++)
{
if(buffer[i-1][m]==0)
{
run->addr=m;
break;
}
}
ints=0;
while
(1)
{
j=rand()%10;
if(j==0)
{
run->length=length;
break;
}
buffer[i-1][(run->addr+length)]=s;//输出请求数据
cout<
s++;
length++;
}
cout<PCB[i-1]->length+=length;
length=0;
if(PCB[2]->status==2)
{
PCB[2]->status=0;
}
tail++;
}
voidspooling()
{
inti,j;
structreq*run;
printf("调用SPOOLING输出服务程序输出数据:
\n");
fprintf(f,"调用SPOOLING输出服务程序输出数据:
\n");
run=&reqblock[head%10];
printf("用户%d\n",run->reqname);
fprintf(f,"用户%d\n",run->reqname);
for(i=0;ilength;i++)
{
printf("%d",buffer[run->reqname-1][run->addr+i]);
fprintf(f,"%d",buffer[run->reqname-1][run->addr+i]);
}
printf("\n");
fprintf(f,"\n");
head++;
for(j=0;j<2;j++)
{
if(PCB[j]->status==1)
{
PCB[j]->status=0;
}
}
}
intmain()
{
inti,n;
f=fopen("result.txt","w");
for(i=0;i<2;i++)
for(n=0;n<100;n++)
buffer[i][n]=0;
for(i=0;i<3;i++)
{
structpcb*tmpPcb=(structpcb*)malloc(sizeof(structpcb));
tmpPcb->id=i;
tmpPcb->status=0;
tmpPcb->firstaddr=0;
tmpPcb->length=0;
tmpPcb->outbufword=1;
PCB[i]=tmpPcb;
}
printf("Howmanyworkdop1wanttodo?
");
fprintf(f,"Howmanyworkdop1wanttodo?
");
scanf("%d",&t1);
fprintf(f,"%d\n",t1);
printf("Howmanyworkdop2wanttodo?
");
fprintf(f,"Howmanyworkdop2wanttodo?
");
scanf("%d",&t2);
fprintf(f,"%d\n",t2);
srand((unsigned)time(NULL));
while
(1)
{
i=rand()%100;
if(i<=45)
{
if((PCB[0]->status==0)&&(t1>0))
{
request
(1);
}
}
elseif((i<=90)&&(t2>0))
{
if(PCB[1]->status==0)
{
request
(2);
}
}
else
{
spooling();
}
if((t1==0)&&(t2==0)&&(head==tail))
break;
}
for(i=0;i<3;i++)
{
free(PCB[i]);
PCB[i]=NULL;
}
fclose(f);
return0;
}