关于网站开发的步骤,江苏省宿迁市建设局网站,做网站买服务器,企业网站认证广州大学操作系统课程设计报告
要求#xff1a;书写课程设计报告#xff0c;报告中应该包含如下内容#xff1a; 一#xff0e;课程设计题目及内容 课程设计题目#xff1a;题目三#xff1a; 设计模拟一个SPOOLING假脱机输出程序 #xff08;1#xff09; 系统设计要…广州大学操作系统课程设计报告
要求书写课程设计报告报告中应该包含如下内容 一课程设计题目及内容 课程设计题目题目三 设计模拟一个SPOOLING假脱机输出程序 1 系统设计要求设计一个SPOOLING输出进程和两个请求输出的用户进程以及一个SPOOLING输出服务程序request。当用户进程希望输出一系列信息时调用SPOOLING输出服务程序request由输出服务程序将该信息送入输出井。待给出一个结束标志时表示进程该次的文件输出结束。之后申请一个输出请求块用来记录请求输出的用户进程的名字、要输出的文件名以及要输出信息的长度等。等待SPOOLING输出进程进行输出。这里SPOOLING输出进程与请求输出的用户进程可并发运行。SPOOLING输出进程工作时根据请求块记录的各进程要输出的信息将其实际输出到打印机或显示器这里记录到一个文件中。 2 进程调度采用随机调度算法这与进程要求输出信息的随机性相一致。两个请求输出的用户进程的调度概率各为40%SPOOLING输出进程被调度的概率为20%这由随机数发生器产生的随机数来模拟决定。 3 进程状态进程有三个基本状态分别为可执行、等待和结束。状态变化的条件为 1 当进程正在运行或等待调度时的状态为可执行态。 2 服务程序在将用户输出信息送输出井时如发生输出请求块已用完将调用它的用户进程置为“等待状态1”。 3 SPOOLING输出进程在进行输出时若发现输出请求块为空则进入“等待状态2”。 4 SPOOLING输出进程输出一个信息块后应将正在等待输出的进程置为“可执行状态”。 5 服务程序在输出信息到输出井并形成输出请求信息块后若SPOOLING进程处于等待态则将其置为“可执行状态”。 6 进程执行完成时置为“结束态”。
二程序中使用的数据结构及主要符号说明 4 数据结构 1 进程控制块PCB如下
struct pcb //进程控制块PCB
{int id; //进程标识 int status; //状态0为可执行态等待状态1表示请求输出块用完请求输出的用户进程等待等待状态2表示输出井空SPOOLING输出进程等待3为结束态int length;//输出长度
}PCB[PROCESSNUM 1];
其中status0 为可执行态status1 为等待状态1表示请求输出块用完请求输出的用户进程等待status2 为等待状态2 表示输出井空SPOOLING输出进程等待status3 为结束态进程执行完成。
2 请求输出块reqblock 如下
struct reqblock //请求输出块
{int reqid;//要求输出的进程 int tname;int length;//输出长度 int addr;//输出首地址
}ReqBlock[REQBLOCKNUM];3 输出井BUFFER。SPOOLING系统为每个请求输出的进程在输出井中分别开辟一个区。本题目可设计一个二维数组int buffer[T1][30] 和 buffer[T2][30]作为输出井。每个进程一个文件最多可占用输出井20个位置。
struct BUFFER //输出井结构
{int buf[OUTBUFFERNUM]; //输出井缓冲区int usedNum; //输出井缓冲区已使用的数目int head; //指示输出井空闲块首地址//int tail; //指示输出井信息块有信息的部分尾地址
}OutBuffer[PROCESSNUM];三程序流程图和带有注释的源程序
SPOOLING系统输出模拟的主控流程图如图3-1所示 SPOOLING输出服务程序request由请求输出的两个用户进程调用流程图如图3-2所示 SPOOLING输出进程流程图如图3-3所示 图3-1 SPOOLING系统输出模拟的主控流程图 图3-2 SPOOLING输出服务程序request流程图 图3-3 SPOOLING输出进程流程图
源程序
#include stdio.h
#include stdlib.h
#include time.h
#include iostream
using namespace std;#define PROCESSNUM 2 //输出进程个数
#define OUTBUFFERNUM 30 //输出井存储字节个数
#define REQBLOCKNUM 10
#define T1 3 //定义用户进程0要输出的文件数T1
#define T2 3 //定义用户进程1要输出的文件数T2struct pcb //进程控制块PCB
{int id; //进程标识 int status; //状态0为可执行态等待状态1表示请求输出块用完请求输出的用户进程等待等待状态2表示输出井空SPOOLING输出进程等待3为结束态int length;//输出长度
}PCB[PROCESSNUM 1];struct reqblock //请求输出块
{int reqid;//要求输出的进程 int tname;int length;//输出长度 int addr;//输出首地址
}ReqBlock[REQBLOCKNUM];struct BUFFER //输出井结构
{int buf[OUTBUFFERNUM]; //输出井缓冲区int usedNum; //输出井缓冲区已使用的数目int head; //指示输出井空闲块首地址//int tail; //指示输出井信息块有信息的部分尾地址
}OutBuffer[PROCESSNUM];int C3 10; //C3表示当前系统剩余的请求输出信息块个数初值为10
int n_out 0, n_in 0; //指示当前使用的输出请求块request从n_in开始取spooling从n_out开始取int t1 0; //设两个计时器分别记录两个用户进程已经输出的文件个数都初始化为0
int t2 0;
int t_num[2][10];void init()//初始化函数
{int i, j;for (i 0; i PROCESSNUM; i){OutBuffer[i].head 0;OutBuffer[i].usedNum 0;for (j 0; j OUTBUFFERNUM; j)OutBuffer[i].buf[j] 0;}for (i 0; i REQBLOCKNUM; i){ReqBlock[i].reqid -1;ReqBlock[i].length 0;ReqBlock[i].addr 0;}for (i 0; i PROCESSNUM 1; i){PCB[i].id i;PCB[i].status 0;PCB[i].length 0;}//自动生成用户进程0和用户进程1的文件长度/*for (i 0; i T1; i){t_num[0][i] (rand() % 30) 1;}*//*for (i 0; i T2; i){t_num[1][i] (rand() % 30) 1;}*///手动生成用户进程0和用户进程1的文件长度t_num[0][0] 15;t_num[0][1] 18;t_num[0][2] 8;t_num[1][0] 25;t_num[1][1] 18;t_num[1][2] 6;
}void request(int i)
{cout endl;cout 进程: i 调用request进程写入的进程块序号为ReqBlock[ n_in ] endl;int j, length 0;if (C3 0) //判断是否有空闲的请求块{PCB[i].status 1; //没有空闲的请求块进程状态置3cout 没有空闲的请求块进程状态置1 endl;return;}C3--;//申请一个空闲的请求输出块//判断输出文件的字符数是否大于20如果大于20标志aa和bb会置为falsebool aa true;bool bb true;if (i 0) //如果是用户进程0for (int k 0; k t_num[0][t1]; k) {j (rand() % 10) 1;//随机数if (k 20) {aa false;cout endl该文件个数大于20将被挂起 endl;t_num[0][t1] t_num[0][t1] - 20;PCB[0].status 1;break;}OutBuffer[0].buf[(OutBuffer[i].head k) % OUTBUFFERNUM] j; //J送buffer[0][length]cout j ;OutBuffer[0].usedNum;//判断输出井是否满if (OutBuffer[0].usedNum OUTBUFFERNUM) {cout endl输出井满 endl;ReqBlock[n_in].length k1;t_num[0][t1] t_num[0][t1] - ReqBlock[n_in].length;ReqBlock[n_in].reqid i;ReqBlock[n_in].addr OutBuffer[i].head;n_in (n_in 1) % REQBLOCKNUM; //修改的输出请求块的个数加1PCB[0].status 1; //挂起进程return;}}else { //如果是用户进程1for (int k 0; k t_num[1][t2]; k) {j (rand() % 10) 1;//随机数if (k 20) {bb false;cout endl该文件个数大于20将被挂起 endl;t_num[1][t2] t_num[1][t2] - 20;PCB[1].status 1;break;}OutBuffer[1].buf[(OutBuffer[i].head k) % OUTBUFFERNUM] j; //J送buffer[0][length]cout j ;OutBuffer[1].usedNum;//判断输出井是否满if (OutBuffer[1].usedNum OUTBUFFERNUM) {cout 输出井满 endl;PCB[1].status 1; //挂起进程ReqBlock[n_in].length k1;t_num[1][t2] t_num[1][t2] - ReqBlock[n_in].length;ReqBlock[n_in].reqid i;ReqBlock[n_in].addr OutBuffer[i].head;n_in (n_in 1) % REQBLOCKNUM; //修改的输出请求块的个数加1return;}}}cout endl;if (i 0) {cout 进程 i 文件的 t1 的字符个数: t_num[0][t1] endl endl;if (aa) {ReqBlock[n_in].length t_num[0][t1];cout 进程结束 endl endl;t1; //t1记录用户进程1已经输出的文件个数}elseReqBlock[n_in].length 20;}else {cout 进程 i 文件 t2 的字符个数: t_num[1][t2] endl endl;if (bb) {ReqBlock[n_in].length t_num[1][t2];cout 进程结束 endl endl;t2; //t2记录用户进程1已经输出的文件个数}elseReqBlock[n_in].length 20;}//填写请求块ReqBlock[n_in].reqid i; //置该输出请求块的进程名字为iReqBlock[n_in].addr OutBuffer[i].head; //修改输出首地址OutBuffer[i].head (OutBuffer[i].head ReqBlock[n_in].length) % OUTBUFFERNUM;if (PCB[PROCESSNUM].status 2) //若spooling进程阻塞则修改其状态为可执行0PCB[PROCESSNUM].status 0;n_in (n_in 1) % REQBLOCKNUM; //修改的输出请求块的个数加1}void spooling()
{//请完成spooling函数的设计if (C3 10) {//如果没有请求块if (PCB[0].status 3 PCB[1].status 3) {//是否所有输出进程结束PCB[2].status 3;return;}else {PCB[2].status 2;return;}}cout ******************************************************************************* endl;//按照请求块从输出井中取数据输出打印到屏幕//遍历请求块while (C3 10) {int requid ReqBlock[n_out].reqid;int addr ReqBlock[n_out].addr;int length ReqBlock[n_out].length;cout addr addr endl;cout SPOOLING输出进程为 requid endl;cout 调用SPOOLING进程释放的进程块序号为ReqBlock[ n_out ] endl;cout 以下为输出结果 endl;int k;if (requid 0) {for (k 0; k length; k)cout OutBuffer[0].buf[(addr k) % OUTBUFFERNUM] ;OutBuffer[0].usedNum OutBuffer[0].usedNum - length;}else {for (k 0; k length; k)cout OutBuffer[1].buf[(addr k) % OUTBUFFERNUM] ;OutBuffer[1].usedNum OutBuffer[1].usedNum - length;}cout endl;C3;//将数据从输出井输出n_out (n_out 1) % REQBLOCKNUM;}if (PCB[0].status 1) //修改阻塞进程状态为就绪PCB[0].status 0;if (PCB[1].status 1)PCB[1].status 0;cout endlendl;return;}void work()//模拟进程调度
{int i;bool isFinish;srand((unsigned)time(NULL));while (1){i rand() % 100;if (i 40 PCB[0].status 0){if (t1 3) {request(0);}}else if (i 80 PCB[1].status 0){if (t2 3) {request(1);}}else if (i 80 PCB[2].status 0){spooling();}//所有进程都结束了吗isFinish true;if (t1 T1) {PCB[0].status 3;}if (t2 T2) {PCB[1].status 3;}for (i 0; i PROCESSNUM 1; i) {if (PCB[i].status ! 3)isFinish false;}if (isFinish) //若所有进程都结束则退出return;}}
int main() //主程序
{srand((unsigned)time(NULL));init();cout \n SPOOLing系统模拟程序 \n;cout 进程0创建 T1 个文件 endl;for (int i 0; i T1; i) {cout 进程0文件 i 的文件个数是 t_num[0][i] endl;}cout endl;cout 进程1创建 T2 个文件 endl;for (int i 0; i T2; i) {cout 进程1文件 i 的文件个数是 t_num[1][i] endl;}cout endl;work();return 0;}
四执行程序名并打印程序运行时的初值和运算结果 五实验结果分析实验收获和体会 操作系统是比较复杂抽象的课程。单单看书很难领会操作系统的知识。只有多动手多做实验才会对操作系统的知识有更深刻的体会比如文件管理SPOOLING技术等。纸上得来终觉浅绝知此事要躬行。 六实验的改进意见和建议。 1.我觉得操作系统课程设计放在期末考试前是一种不妥的行为一方面学生要忙于复习另一方面又要忙于课程设计。既影响复习也影响课设完成的质量。