操作系统(SPOOLING技术)

一、实验目的

理解和掌握SPOOLING假脱机技术


二、实验内容

  通过SPOOLING技术可将一台物理I/O设备虚拟为多台逻辑I/O设备,同样允许多个用户共享一台物理I/O设备,从而使其成为虚拟设备。该技术广泛应用与各种计算机的I/O,通过采用预输入和缓输出的方法,使用共享设备的一部分空间来模拟独占设备,以提高独占设备的利用率。


三、实验准备

1、设计一个实现SPOOLING技术的进程

  设计一个SPOOLING输出进程和两个请求输出的用户进程及一个SPOOLING输出服务程序。

  SPOOLING输出进程工作时,根据请求块记录的各进程要输出的信息,将其实际输出到打印机或显示器。这里,SPOOLING进程与请求输出的用户进程可并发运行。


2、设计进程调度算法

  进程调度采用随机算法,这与进程输出信息的随机性相一致。两个请求输出的用户进程的调度概率各为45%,SPOOLING输出进程为10%,这由随机数发生器产生的随机数模拟决定。


3、进程状态

  进程基本状态有3种,分别为可执行、等待和结束。可执行状态就是进程正在运行或等待调度的状态;

  等待状态又分为等待状态1、等待状态2、等待状态3。

  状态变化的条件为:

  ①进程执行完成时,置为“结東”状态。

  ②服务程序在将输出信息送至输出井时,如发现输出井已满,将调用进程置为“等待状态1”。

  ③SPOOLING进程在进行输出时,若输出井空,则进入“等待状态2”。

  ④当用户进程申请请求输出块时,若没有可用请求块时,调用进程进入“等待状态3”。

  ⑤SPOOLING进程输出一个信息块后,应立即释放该信息块所占的输出井空间,并将正在等待输出的进程置为“可执行状态”。

  ⑥服务程序在输出信息到输出井并形成输出请求信息块后,若SPOOLING进程处于等待状态则将其置为“可执行状态”


4、数据结构

1)进程控制块PCB

structpcb{

    intstatus:

    intlength

}PCBL3];

其中status表示进程状态,其取值:

0表示可执行状态

1表示等待状态1;

2表示等待状态2;

3表示等待状态3。


2)请求输出块reqblock

struct{

intreqname;//请求进程名

intlength;//本次输出信息长度

intaddr;//信息在输出井的首地址

}reblock[10];


3)输出井BUFFER

  SPOOLING系统为每个请求输出的进程在输出井中分别开辟一个区。本实验可设计一个二维数组(intbuffer[2][10])作为输出井。每个进程在输出井最多可占用10个位置。


5、编程说明

  为两个请求输出的用户进程设计两个输出井。每个可存放10个信息,即buffer[2][10]。当用户进程将其所有文件输出完时,终止运行。

  为简单起见,用户进程简单地设计成:每运行一次,随机输出数字0~9之间的一个数,当输入10个数时形成一个请求信息块,填入请求输出信息块reqlock结构中。


6、程序框图

SPOOLING输出模拟系统主控流程图如图所示。
在这里插入图片描述

四、实验要求

1、分析程序所定义使用的数据结构;
2、分析程序的结构,并画出程序流程图;
3、撰写实验报告;

1、数据结构

struct process 
{
	int status;//进程状态 
	int length;//数据长度 
}*PCB[3]; 

struct requset
{
	int reqName;//用户名字 
	int length;//输出数据长度 
	int addr;//地址寄存器 
}reqBlock[10];

int Buffer[2][100];//定义# 
int Head = 0;//打印用户请求的的数据<10的随机数 
int Tail = 0;//请求用户数据<10的随机数 
int T1 = 0;//用户1请求次数定义 
int T2 = 0;//用户2请求次数定义
void Request(int i);//i=1表示用户进程1;i=2表示用户进程2
void Spooling();

2、程序流程图

在这里插入图片描述
获取本地时间代码

void Time()
{
	time_t t;//将t声明为时间变量
    struct tm *p;//struct tm是一个结构体,声明一个结构体指针
    time(&t);
    p=localtime(&t);//获得当地的时间
    int s = 7;//定义一个值
    int k = 7;
    int sum;//计算出k和s,自己的学号是sum
    sum = s * k;
    printf("\n");
    printf("          学号展示\n",sum);
    printf("          自己的姓名\n");
    printf("\n");
    printf("操作系统实验展示于%d年%d月%d日 %d时%d分%d秒\n",1900 + p -> tm_year, 1 + p -> tm_mon, p -> tm_mday, p -> tm_hour, p -> tm_min, p -> tm_sec);
    //输出当前本地的时间 
}

请求函数代码

void Request(int i)
{
	int j = 0;
	int m = 0;
	int length = 0;
	struct requset *run;
	if(1 == i)
	T1--;
	else
	T2--;
	printf("用户%d请求数据:\n",i);
	run =& reqBlock[Tail%10];
	run->reqName = i;
	run->length = 0;
	if(0 == Tail)
	run->addr = 0;
	else
	{
		int index = (Tail-1) % 10;
		run->addr = reqBlock[index].addr + reqBlock[index].length;
	}
	for(m = 0; m < 100; m++)
	{
		if(0 == Buffer[i-1][m])
		{
			run->addr = m;
			break;
		}
	}
	while(1)
	{
		j = rand()%10;
		if(0 == j)
		{
			run -> length = length;
			break;
		}
		Buffer[i-1][(run->addr+length)] = j;
		printf("%3d",j);
		length++;
	}
	printf("\n");
	PCB[i-1]->length += length;
	printf("此时process[%d]中length的值为%d\n",i,length); 
	printf("*******************************\n");
	length = 0;
	if(2 == PCB[j]->status)
	PCB[j]->status = 0;
	Tail++;
}

SPOOLING代码

void Spooling()
{
	int i = 0;
	int j = 0;
	struct requset *run;
	printf("调用SPOOLING输出服务程序输出数据:\n");
	run =& reqBlock[Head%10];
	printf("用户%d请求的数据:\n",run->reqName);
	
	for(i = 0; i < run->length; i++)
	{
		printf("%3d",Buffer[run->reqName-1][run->addr+i]);
	}
	printf("\n");
	printf("\n***********************************\n");
	Head++;
	for(j = 0; j < 2; j++)
	{
		if(1 == PCB[j]->status)//若没有可用请求块时,调用进程进入"等待状态3
		PCB[j]->status = 0;
	}
}

主函数代码

int main()
{
	int l = 0;
	int j = 0;
	int n = 0;
	int m = 0;
	int k = 0;
	for(l = 0; l < 2; l++)
	for(j = 0; j < 100; j++)
	Buffer[l][j] = 0;
	
	for(n = 0; n < 3; n++)
	{
		struct process *tmpprocess = (struct process*)malloc(sizeof(struct process));
		tmpprocess->status = 0;
		tmpprocess->length = 0;
		PCB[n] = tmpprocess;
	}
	Time();
	printf("用户1请求次数为:\n");
	scanf("%d",&T1);
	printf("用户2请求次数为:\n");
	scanf("%d",&T2);
	srand((unsigned)time(NULL));
	while(1)
	{
		k = rand()%100;
		printf("\n");
		printf("当前K值为%d\n",k);
		if((k <= 45) && (T1 > 0))
		{
			if((0 == PCB[0]->status) && (T1 > 0))
			Request(1);		
		}
		else 
		if((k <= 90) && (T2 > 0))
		{
			if(0 == PCB[1]->status)
			Request(2);
		}
		else
		Spooling();
		if((0 == T1) && (0 == T2) && (Head == Tail))
		break;
	}
		for(m = 0; m < 3; m++)
		{
			free(PCB[m]);
			PCB[m] = NULL;
		}
	getchar();
}

全部代码展示

#include<stdio.h>
#include<iostream>
#include<time.h>
#include<stdlib.h>

struct process 
{
	int status;//进程状态 
	int length;//数据长度 
}*PCB[3]; 

struct requset
{
	int reqName;//用户名字 
	int length;//输出数据长度 
	int addr;//地址寄存器 
}reqBlock[10];

int Buffer[2][100];//定义# 
int Head = 0;//打印用户请求的的数据<10的随机数 
int Tail = 0;//请求用户数据<10的随机数 
int T1 = 0;//用户1请求次数定义 
int T2 = 0;//用户2请求次数定义
void Request(int i);//i=1表示用户进程1;i=2表示用户进程2
void Spooling();

void Time()
{
	time_t ti;//将t声明为时间变量
    struct tm *p;//struct tm是一个结构体,声明一个结构体指针
    time(&ti);
    p = localtime(&ti);//获得当地的时间
    int s = 7;
    int k = 7;
    int sum;
    sum = s * k;
    printf("***********************************\n");
    printf("******   SPOOLING技术模拟系统  ****\n"); 
    printf("******      学号   *********\n",sum);
    printf("******       姓名       *********\n");
    printf("***********************************\n");
    printf("操作系统实验展示于%d年%d月%d日 %d时%d分%d秒\n",1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday, p->tm_hour, p->tm_min, p ->tm_sec);
    printf("---------------------------------------------\n");
}

int main()
{
	int l = 0;
	int j = 0;
	int n = 0;
	int m = 0;
	int k = 0;
	for(l = 0; l < 2; l++)
	for(j = 0; j < 100; j++)
	Buffer[l][j] = 0;
	
	for(n = 0; n < 3; n++)
	{
		struct process *tmpprocess = (struct process*)malloc(sizeof(struct process));
		tmpprocess->status = 0;
		tmpprocess->length = 0;
		PCB[n] = tmpprocess;
	}
	Time();
	printf("用户1请求次数为:\n");
	scanf("%d",&T1);
	printf("用户2请求次数为:\n");
	scanf("%d",&T2);
	srand((unsigned)time(NULL));
	while(1)
	{
		k = rand()%100;
		printf("\n");
		printf("当前K值为%d\n",k);
		if((k <= 45) && (T1 > 0))
		{
			if((0 == PCB[0]->status) && (T1 > 0))
			Request(1);		
		}
		else 
		if((k <= 90) && (T2 > 0))
		{
			if(0 == PCB[1]->status)
			Request(2);
		}
		else
		Spooling();
		if((0 == T1) && (0 == T2) && (Head == Tail))
		break;
	}
		for(m = 0; m < 3; m++)
		{
			free(PCB[m]);
			PCB[m] = NULL;
		}
	getchar();
}

void Request(int i)
{
	int j = 0;
	int m = 0;
	int length = 0;
	struct requset *run;
	if(1 == i)
	T1--;
	else
	T2--;
	printf("用户%d请求数据:\n",i);
	run =& reqBlock[Tail%10];
	run->reqName = i;
	run->length = 0;
	if(0 == Tail)
	run->addr = 0;
	else
	{
		int index = (Tail-1) % 10;
		run->addr = reqBlock[index].addr + reqBlock[index].length;
	}
	for(m = 0; m < 100; m++)
	{
		if(0 == Buffer[i-1][m])
		{
			run->addr = m;
			break;
		}
	}
	while(1)
	{
		j = rand()%10;
		if(0 == j)
		{
			run -> length = length;
			break;
		}
		Buffer[i-1][(run->addr+length)] = j;
		printf("%3d",j);
		length++;
	}
	printf("\n");
	PCB[i-1]->length += length;
	printf("此时process[%d]中length的值为%d\n",i,length); 
	printf("*******************************\n");
	length = 0;
	if(2 == PCB[j]->status)
	PCB[j]->status = 0;
	Tail++;
}

void Spooling()
{
	int i = 0;
	int j = 0;
	struct requset *run;
	printf("调用SPOOLING输出服务程序输出数据:\n");
	run =& reqBlock[Head%10];
	printf("用户%d请求的数据:\n",run->reqName);
	
	for(i = 0; i < run->length; i++)
	{
		printf("%3d",Buffer[run->reqName-1][run->addr+i]);
	}
	printf("\n");
	printf("\n***********************************\n");
	Head++;
	for(j = 0; j < 2; j++)
	{
		if(1 == PCB[j]->status)//若没有可用请求块时,调用进程进入"等待状态3
		PCB[j]->status = 0;
	}
}

代码运行结果

在这里插入图片描述

SPOOLING技术 一、实验目的 理解和掌握SPOOLING技术。 二、实验内容 编写程序实现SPOOLING技术的模拟。 三、实验要求 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”。 4、数据结构 1)进程控制块PCB struct pcb { int status; int length; }pcb[3]; 其中status表示进程状态,其取值: 0 表示可执行状态; 1 表示等待状态1; 2 表示等待状态2; 3 表示等待状态3 2)请求输出块reqblock struct{ int reqname;//请求进程名 int length;// 本次输出信息长度 int addr;// 信息输出的首地址 }reqblock[10]; 3)输出BUFFER SPOOLING系统为每个请求输出进程输出中分别开辟一个区。本实验可设计一个二维数组(int buffer[2][10])作为输出每个进程输出最多可占用10个位置。 5、编程说明 为两个请求输出用户进程设计两个输出每个存放10个信息,即buffer[2][10]。当用户进程将其所有文件输出完时,终止运行。 为简单起见,用户进程简单的设计成:每运行一次,随机输出数字0~9之间的一个数,当输入10个数时形成一个请求信息块,填入请求输出信息块reqblock结构中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

又菜又爱巻

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值