资源下载地址:https://download.csdn.net/download/sheziqiong/85932347
资源下载地址:https://download.csdn.net/download/sheziqiong/85932347
一、课程设计目的
操作系统是计算机系统配置的基本软件之一。它在整个计算机系统软件中占有中心地位。其作用是对计算机系统进行统一的调度和管理,提供各种强有力的系统服务,为用户创造既灵活又方便的使用环境。本课程是计算机及应用专业的一门专业主干课和必修课。
通过课程设计,使学生掌握操作系统的基本概念、设计原理及实施技术,具有分析操作系统和设计、实现、开发实际操作系统的能力。
二、课程设计内容和要求
提交一批作业(>=10),按先来先服选择一部分作业(最多 5 个)进入内存
为每个作业创建一个进程,并分配内存(用户内存:0—1024K,采用可变连续分配方式)
进程调度功能(时间片轮转)
随机阻塞进程,并在一段时间后唤醒进程(选做)
显示相关信息:后备作业队列、内存分配情况、进程信息、完成作业情况
这些功能要有机地连接起来
三、软、硬件环境
软件:Windows 10, JDK1.8,IntelliJ IDEA
硬件:Intel® Core™ i5-8300H , 2.30GHz, RAM: 8.00GB
四、设计步骤
- 题目分析
本次课程设计是将作业调度,内存管理、进程调度、进程阻塞等功能有机结合起来的一道题目。首先,需要使用随机数初始化 10 个作业,放入后备队列中,然后使用先来先服务(FCFS)进行作业调度,使用时间片轮转算法进行进程调度。其中,最多只能有五个作业能同时进入内存,本实验假设阻塞状态的进程依然在内存中。也就是说,处于就绪、运行、阻塞三种状态的进程数目之和最多为 5 个,即并发进程数最多为 5 个,在进程结束后,就会被调出内存,使用 FCFS 算法从后备队列中调入新的作业。在内存中的几个非阻塞状态的进程使用时间片轮转(RR)算法进行调度。而作业在进入内存之前,是要申请内存的,这时使用首次适应(FF)算法申请内存,从空闲分区链中找到合适的空闲分区并分配给该进程。在进程结束时,要回收其占用的内存,并进行相应的空闲分区合并。如此,便可以将作业调度、内存管理、进程调度和进程阻塞与唤醒这几个功能有机地连接起来了。
2.算法流程图:
3.项目工程截图:
/
* 调度方法
* @throws InterruptedException
*/
public void dispatch() throws InterruptedException {
if (isFinishALLProcess()) {
return;
}
long now = System.currentTimeMillis();
double passedTime = (now - lastTime) / 1000.0; //距离上次调度经过的时间
double allTime = (now - beginTime) / 1000.0;
// 从后备队列调入进程
getNextOnDisk(allTime);
if (runningIndex != -1) {
double oldhasUsedTime = pcb[runningIndex].hasUsedTime;
if (passedTime >= timeSlice) {
if (oldhasUsedTime + passedTime >= pcb[runningIndex].needTime) {
pcb[runningIndex].hasUsedTime = pcb[runningIndex].needTime;
pcb[runningIndex].status = "Finish";
releaseMemory(pcb[runningIndex].address);
} else {
pcb[runningIndex].hasUsedTime = oldhasUsedTime + timeSlice;
pcb[runningIndex].status = "Waiting";
}
// 从就绪队列中选择下一个进程
int next = getNextWaiting(runningIndex);
if (next != -1) {
pcb[next].status = "Running";
runningIndex = next;
print();
}
}
} else {
pcb[0].status = "Running";
runningIndex = 0;
print();
}
// 随机阻塞进程
Random random = new Random();
int randomNum = random.nextInt(3);
// 符合此条件的进程将被阻塞
if (randomNum == 2 && (blocked == 0 ) ) {
blockIndex = runningIndex;
pcb[runningIndex].status = "Blocking";
blocked = 1;
runningIndex = getNextWaiting(runningIndex);
}
// 唤醒进程
if (blocked == 1) {
long time = System.currentTimeMillis();
double intervalTime = (time - lastTime) / 1000.0;
if (runningIndex == -1) {
// 只剩下最后一个阻塞进程未执行完,则该进程休眠1秒后唤醒
Thread.sleep(1000);
runningIndex = blockIndex;
pcb[runningIndex].status = "Waiting";
blocked = 0;
} else if (intervalTime > 2.0) {
// 有进程属于阻塞状态时,满足阻塞时间大于2s则唤醒进程
if (blockIndex != -1) {
pcb[blockIndex].status = "Waiting";
blocked = 0;
}
}
}
}
// 界面输出函数
6.运行结果截图(内容太多,仅展示关键部分):
初始的分区说明表(1024KB 的内存):
开始时,后备队列中的十个作业:
按照要求开始进程调度,按照时间片轮转算法:
此时,已经运行完一些进程了:
直至所有进程运行完成:
7.运行结果的分析:
第一张图是初始时候的内存分区说明表,共1024KB,都是空闲状态。
第二张图是随机生成的十个作业。第三张图开始是进程调度,此时只有 P1 到达,因此先调入内存。运行到第四张图时,P1、P2、P10、P9、P7 已经被进入内存,剩下 P3、P4、P5、P6、P8 在后备队列中。结合第四第五张图看,可以看出,进程调度算法是时间片轮转算法,每个时间片为 2。
在同一张图片中,结合内存分区表来看,可以看到,内存分区表中状态为 Busy 的块和 PCB 信息相符合。PCB 表中的 运行中(Running)、就绪(Waiting)、阻塞(Blocking)状态的进程刚好和内存分区表中的 Busy 状态内存块一一对应。因为最多同时调入五个作业进内存,因此,内存分区表中也最多只有五个处于 Busy 状态的内存块。
当某一个进程执行完成,就会释放内存,如果释放的内存块的前后内存块也是空闲的,则进行合并,从最后一张图可以看到,最终虽有进程都执行完毕后,内存分区表最终也回到了最初的时候,只有一个 1024KB 的空闲块。
随机阻塞进程,从第四张图片开始看,会看到有进程属于阻塞状态,当阻塞到达一定的时间后会被唤醒,最终全部执行完成。
资源下载地址:https://download.csdn.net/download/sheziqiong/85932347
资源下载地址:https://download.csdn.net/download/sheziqiong/85932347