(1) 课程设计题目及内容
设计模拟一个SPOOLING假脱机输出程序 设计一个SPOOLING输出进程和两个请求输出的用户进程,以及一个SPOOLING输出服务程序request。当用户进程希望输出一系列信息时,调用SPOOLING输出服务程序request,由输出服务程序将该信息送入输出井。待给出一个结束标志时,表示进程该次的文件输出结束。之后,申请一个输出请求块,用来记录请求输出的用户进程的名字、要输出的文件名以及要输出信息的长度等。等待SPOOLING输出进程进行输出。这里,SPOOLING输出进程与请求输出的用户进程可并发运行。SPOOLING输出进程工作时,根据请求块记录的各进程要输出的信息,将其实际输出到打印机或显示器,这里记录到一个文件中。
(2) 程序中使用的数据结构及主要符号说明
进程标识用结构体pcb表示,整型id表示进程标识数,status表示进程状态。 struct pcb { int id; // 进程标识数 int status; // 进程状态 }; 文件标识用结构体filehandle表示,整型file_length表文件长度,在开始进程前随机写入,file_already表已写入输出井中的长度。 struct filehandle //文件标识 { int file_length;//文件长度 int file_already;//文件已写入缓冲的长度 };
申明一个全局二维指针,用于申请动态二维数组时表示两个进程的文件 extern filehandle FH;
status = 0 为可执行态; status = 1 为等待状态1,表示请求输出块用完,请求输出的用户进程等待; status = 2 为等待状态2, 表示输出井空,SPOOLING输出进程等待; status = 3 为结束态,进程执行完成。
请求块用结构体block表示,整型reqname记录请求块对应的进程名,sta对应该请求块在输出井中开始输出的起点,length表示该请求块对应的写入数据总长度。
struct block { int reqname; // 请求进程名 int sta; //请求块对应输出井中起点 int length; // 本次输出信息长度 }; extern pcb PCB[3]; extern block reqblock[block_num]; extern int T[2];//进程1、2需要完成输出的文件数目 extern int t[2];//进程1、2已经完成输出的文件数目
extern int n_in, n_out;//送取数据时的块数标记,取值为0~9(超过9时模10),因为有C3作标记,无需考虑循环队列的判空判满,只要考虑各自位置即可 整型C3标记请求块剩余数目,同时循环队列判空判满 extern int C3;//请求块剩余块数
为每个进程开辟一个文件共享区 extern int buffer[2][buffer_size];//输出井 extern int bufferleft[2];//输出井剩余空间
(3) 程序流程图和带有注释的源程序
程序流程图
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200116152417728.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDM1Mzk3MA==,size_16,color_FFFFFF,t_70)
Spooling.h
#include
#include
#define p1_fnum 5 //进程一需要输出的文件数目
#define p2_fnum 2 //进程二需要输出的文件数目
#define f_maxsize 10 //一个文件所占输出井最大空间
#define buffer_size 30 //一块输出井大小
#define block_num 10 //请求块数目
struct pcb
{
int id; // 进程标识数
int status; // 进程状态
};
struct filehandle //文件标识
{
int file_length;//文件长度
int file_already;//文件已写入缓冲的长度
};
extern filehandle** FH;
/*
status = 0 为可执行态;
status = 1 为等待状态1,表示请求输出块用完,请求输出的用户进程等待;
status = 2 为等待状态2, 表示输出井空,SPOOLING输出进程等待;
status = 3 为结束态,进程执行完成。
*/
struct block
{
int reqname; // 请求进程名
int sta; //请求块对应输出井中起点
int length; // 本次输出信息长度
};
extern pcb PCB[3];
extern block reqblock[block_num];
extern int T[2];//进程1、2需要完成输出的文件数目
extern int t[2];//进程1、2已经完成输出的文件数目
extern int n_in, n_out;//送取数据时的块数标记,取值为0~9(超过9时模10),因为有C3作标记,无需考虑循环队列判空判满,只要考虑各自位置即可
extern int C3;//请求块剩余块数
extern int buffer[2][buffer_size];//输出井
extern int bufferleft[2];//输出井剩余空间
void systemInitialize();//进程、输出井初始化
int getpid(); //获取随机调度的进程
void printblock(int num);//在spooling中打印对应块的内容
int getfinish();//查询完成资源数
void renewprocess();//更新子进程状态
void spooling();//spooling调度算法
void request(int pid);//输出进程请求
Spooling.cpp
#include"SPOOLING.h"
pcb PCB[3];
block reqblock[10];
filehandle** FH = (filehandle**)(malloc(sizeof(filehandle*) * 2));
int T[2] = { p1_fnum, p2_fnum };//进程1、2需要完成输出的文件数目
int t[2] = { 0,0 };//进程1、2已经完成输出的文件数目
int n_in = 0, n_out = 0;//送取数据时的块数标记,取值为0~9(超过9时模10),因为有C3作标记,无需考虑循环队列判空判满,只要考虑各自位置即可
int C3 = block_num;//请求块剩余块数
int buffer[2][buffer_size];//输出井
int bufferleft[2] = { buffer_size,buffer_size };//输出井剩余空间
void systemInitialize()
{
FH[0] = (filehandle*)malloc(sizeof(filehandle) * p1_fnum);
FH[1] = (filehandle*)malloc(sizeof(filehandle) * p2_fnum);
std::cout
FH[1][i].file_already = 0;
FH[1][i].file_length = rand() % 20 + 1;
std::cout
int p = rand() % 100 + 1;
if (p
return 1;
}
else
{
return 2;
}
}
int getfinish()
{
int finish = 0;
for (int i = 0; i
finish++;
}
}
return finish;
}
void printblock(int num)
{
std::cout
if (C3 == block_num)
{
if (getfinish() == 2)//其它进程已结束,SPOOLING进程结束
{
std::cout
PCB[0].status = 0;
for (; n_out != n_in; n_out = (n_out + 1) % 10)
{
printblock(n_out);
C3++;//所剩块加一
}
bufferleft[0] = buffer_size;
bufferleft[1] = buffer_size;
if (PCB[1].status == 1)
{
std::cout
if (C3 == 0)//请求块剩余数为0或对应的输出井区域所剩空间不足
{
std::cout
//写文件,如果已经是最后一个字符了,写完break,表明文件写完
if (FH[pid - 1][t[pid - 1]].file_already == FH[pid - 1][t[pid - 1]].file_length - 1)
{
pen = 0;
}
else
{
pen = rand() % 9 + 1;
}
buffer[pid - 1][buffer_size - bufferleft[pid - 1] + l] = pen;//写入输出井
FH[pid - 1][t[pid - 1]].file_already++;
//每次写字符,该文件已写字符数往后走一步
l++;
std::cout
PCB[pid].status = 1;
}
bufferleft[pid-1] -= l;
reqblock[n_in].length = l;//文件输出流长度写入该块
C3--;//所剩请求块减一
n_in = (n_in + 1) % block_num; //写入块往下走
if (PCB[0].status == 2)
{
std::cout
PCB[1].status = 3;
}
if (T[1] == t[1])
{
PCB[2].status = 3;
}
}
(4) 执行程序名,并打印程序运行时的初值和运算结果
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200116152600819.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDM1Mzk3MA==,size_16,color_FFFFFF,t_70)
|