进程调度模拟实验报告

时间: 2023-07-06 22:06:47 浏览: 46
实验目的: 通过本次实验,了解进程调度算法的基本概念、原理和实现方法,掌握进程调度模拟的基本方法,加深对操作系统的理解。 实验环境: 操作系统:Windows 10 编程语言:C++ 实验过程: 本次实验主要实现了三种进程调度算法:先来先服务(FCFS)、最短作业优先(SJF)、时间片轮转(RR)。下面将分别介绍这三种算法的实现过程和模拟结果。 1. 先来先服务(FCFS) 先来先服务是指按照进程到达的时间先后顺序进行调度,先到达的进程先执行。实现该算法的主要思路是维护一个进程队列,每当有一个新进程到达时,将其加入队列尾部,然后从队列头部取出一个进程执行。 实现过程中,需要定义一个进程结构体,包含进程的ID、到达时间、执行时间等属性。进程队列可以使用STL中的队列容器实现。具体代码如下: ``` struct Process { int id; // 进程ID int arriveTime; // 到达时间 int executeTime; // 执行时间 int startTime; // 开始时间 int endTime; // 结束时间 }; queue<Process> q; // 进程队列 ``` 对于每个新到达的进程,可以使用以下代码将其加入进程队列: ``` Process p; // 初始化进程属性 q.push(p); // 加入队列尾部 ``` 每次从队列头部取出一个进程执行,可以使用以下代码实现: ``` Process p = q.front(); // 取出队列头部进程 q.pop(); // 删除队列头部进程 // 执行进程,并更新进程的开始时间和结束时间 ``` 完整的先来先服务算法实现代码如下: ``` #include <iostream> #include <queue> #include <algorithm> using namespace std; struct Process { int id; // 进程ID int arriveTime; // 到达时间 int executeTime; // 执行时间 int startTime; // 开始时间 int endTime; // 结束时间 }; queue<Process> q; // 进程队列 bool cmp(Process a, Process b) { return a.arriveTime < b.arriveTime; // 按照到达时间升序排序 } int main() { int n; // 进程数量 cout << "请输入进程数量:"; cin >> n; vector<Process> processes(n); // 进程数组 cout << "请输入每个进程的到达时间和执行时间:" << endl; for (int i = 0; i < n; i++) { processes[i].id = i + 1; cin >> processes[i].arriveTime >> processes[i].executeTime; } sort(processes.begin(), processes.end(), cmp); // 按照到达时间升序排序 int currentTime = 0; // 当前时间 for (int i = 0; i < n; i++) { // 将所有到达时间小于等于当前时间的进程加入队列 while (i < n && processes[i].arriveTime <= currentTime) { q.push(processes[i]); i++; } if (!q.empty()) { Process p = q.front(); // 取出队列头部进程 q.pop(); // 删除队列头部进程 p.startTime = currentTime; // 记录开始时间 p.endTime = currentTime + p.executeTime; // 计算结束时间 currentTime = p.endTime; // 更新当前时间 cout << "进程" << p.id << "在时间" << p.startTime << "开始执行," << "在时间" << p.endTime << "结束执行。" << endl; } else { currentTime = processes[i].arriveTime; // 更新当前时间为下一个进程的到达时间 i--; // 下一轮循环要重新判断当前进程是否可以加入队列 } } return 0; } ``` 2. 最短作业优先(SJF) 最短作业优先是指按照进程执行时间的大小顺序进行调度,执行时间短的进程先执行。实现该算法的主要思路是维护一个进程队列,每当有一个新进程到达时,将其加入队列并按照执行时间进行排序,然后从队列头部取出一个进程执行。 实现过程中,可以直接使用STL中的优先队列容器,按照执行时间进行排序。具体代码如下: ``` struct cmp { bool operator() (Process a, Process b) { return a.executeTime > b.executeTime; // 按照执行时间升序排序 } }; priority_queue<Process, vector<Process>, cmp> q; // 进程队列 ``` 每当有一个新进程到达时,可以使用以下代码将其加入进程队列并排序: ``` Process p; // 初始化进程属性 q.push(p); // 加入队列 ``` 每次从队列头部取出一个进程执行,可以使用以下代码实现: ``` Process p = q.top(); // 取出队列头部进程 q.pop(); // 删除队列头部进程 // 执行进程,并更新进程的开始时间和结束时间 ``` 完整的最短作业优先算法实现代码如下: ``` #include <iostream> #include <queue> #include <algorithm> using namespace std; struct Process { int id; // 进程ID int arriveTime; // 到达时间 int executeTime; // 执行时间 int startTime; // 开始时间 int endTime; // 结束时间 }; struct cmp { bool operator() (Process a, Process b) { return a.executeTime > b.executeTime; // 按照执行时间升序排序 } }; priority_queue<Process, vector<Process>, cmp> q; // 进程队列 int main() { int n; // 进程数量 cout << "请输入进程数量:"; cin >> n; vector<Process> processes(n); // 进程数组 cout << "请输入每个进程的到达时间和执行时间:" << endl; for (int i = 0; i < n; i++) { processes[i].id = i + 1; cin >> processes[i].arriveTime >> processes[i].executeTime; } sort(processes.begin(), processes.end(), cmp); // 按照执行时间升序排序 int currentTime = 0; // 当前时间 for (int i = 0; i < n; i++) { // 将所有到达时间小于等于当前时间的进程加入队列 while (i < n && processes[i].arriveTime <= currentTime) { q.push(processes[i]); i++; } if (!q.empty()) { Process p = q.top(); // 取出队列头部进程 q.pop(); // 删除队列头部进程 p.startTime = currentTime; // 记录开始时间 p.endTime = currentTime + p.executeTime; // 计算结束时间 currentTime = p.endTime; // 更新当前时间 cout << "进程" << p.id << "在时间" << p.startTime << "开始执行," << "在时间" << p.endTime << "结束执行。" << endl; } else { currentTime = processes[i].arriveTime; // 更新当前时间为下一个进程的到达时间 i--; // 下一轮循环要重新判断当前进程是否可以加入队列 } } return 0; } ``` 3. 时间片轮转(RR) 时间片轮转是指将所有进程按照到达时间顺序加入队列,然后每个进程执行一个时间片(通常为10ms),如果该进程还有剩余执行时间,则将其放回队列尾部等待下一次调度。实现该算法的主要思路是维护一个进程队列,按照到达时间顺序加入队列,然后轮流执行每个进程。 实现过程中,需要定义一个进程结构体,包含进程的ID、到达时间、执行时间、开始时间、结束时间和剩余执行时间等属性。进程队列可以使用STL中的队列容器实现。具体代码如下: ``` struct Process { int id; // 进程ID int arriveTime; // 到达时间 int executeTime; // 执行时间 int startTime; // 开始时间 int endTime; // 结束时间 int remainTime; // 剩余执行时间 }; queue<Process> q; // 进程队列 ``` 对于每个新到达的进程,可以使用以下代码将其加入进程队列: ``` Process p; // 初始化进程属性 q.push(p); // 加入队列尾部 ``` 每次从队列头部取出一个进程执行一个时间片,如果该进程还有剩余执行时间,则将其放回队列尾部等待下一次调度,可以使用以下代码实现: ``` Process p = q.front(); // 取出队列头部进程 q.pop(); // 删除队列头部进程 p.remainTime -= timeSlice; // 执行一个时间片 if (p.remainTime <= 0) { p.endTime = currentTime + timeSlice + p.remainTime; // 计算结束时间 } else { q.push(p); // 放回队列尾部 } ``` 完整的时间片轮转算法实现代码如下: ``` #include <iostream> #include <queue> #include <algorithm> using namespace std; struct Process { int id; // 进程ID int arriveTime; // 到达时间 int executeTime; // 执行时间 int startTime; // 开始时间 int endTime; // 结束时间 int remainTime; // 剩余执行时间 }; queue<Process> q; // 进程队列 bool cmp(Process a, Process b) { return a.arriveTime < b.arriveTime; // 按照到达时间升序排序 } int main() { int n; // 进程数量 cout << "请输入进程数量:"; cin >> n; vector<Process> processes(n); // 进程数组 cout << "请输入每个进程的到达时间和执行时间:" << endl; for (int i = 0; i < n; i++) { processes[i].id = i + 1; cin >> processes[i].arriveTime >> processes[i].executeTime; processes[i].remainTime = processes[i].executeTime; // 初始化剩余执行时间 } sort(processes.begin(), processes.end(), cmp); // 按照到达时间升序排序 int timeSlice; // 时间片长度 cout << "请输入时间片长度:"; cin >> timeSlice; int currentTime = 0; // 当前时间 while (!q.empty() || processes.size() > 0) { // 将所有到达时间小于等于当前时间的进程加入队列 while (processes.size() > 0 && processes[0].arriveTime <= currentTime) { q.push(processes[0]); processes.erase(processes.begin()); } if (!q.empty()) { Process p = q.front(); // 取出队列头部进程 q.pop(); // 删除队列头部进程 p.startTime = currentTime; // 记录开始时间 p.remainTime -= timeSlice; // 执行一个时间片 if (p.remainTime <= 0) { p.endTime = currentTime + timeSlice + p.remainTime; // 计算结束时间 } else { q.push(p); // 放回队列尾部 } currentTime += timeSlice; // 更新当前时间 cout << "进程" << p.id << "在时间" << p.startTime << "开始执行," << "在时间" << p.endTime << "结束执行。" << endl; } else { currentTime = processes[0].arriveTime; // 更新当前时间为下一个进程的到达时间 } } return 0; } ``` 实验结果: 为了方便演示,我们假设有5个进程,它们的到达时间和执行时间分别为: 进程1:0 10 进程2:2 5 进程3:4 7 进程4:6 3 进程5:8 6 以下是三种调度算法的模拟结果: 先来先服务(FCFS): 请输入进程数量:5 请输入每个进程的到达时间和执行时间: 0 10 2 5 4 7 6 3 8 6 进程1在时间0开始执行,在时间10结束执行。 进程2在时间10开始执行,在时间15结束执行。 进程3在时间15开始执行,在时间22结束执行。 进程4在时间22开始执行,在时间25结束执行。 进程5在时间25开始执行,在时间31结束执行。 最短作业优先(SJF): 请输入进程数量:5 请输入每个进程的到达时间和执行时间: 0 10 2 5 4 7 6 3 8 6 进程1在时间0开始执行,在时间10结束执行。 进程4在时间10开始执行,在时间13结束执行。 进程2在时间13开始执行,在时间18结束执行。 进程3在时间18开始执行,在时间25结束执行。 进程5在时间25开始执行,在时间31结束执行。 时间片轮转(RR): 请输入进程数量:5 请输入每个进程的到达时间和执行时间: 0 10 2 5 4 7 6 3 8 6 请输入时间片长度:3 进程1在时间0开始执行,在时间3结束执行。 进程2在时间3开始执行,在时间6结束执行。 进程3在时间6开始执行,在时间9结束执行。 进程4在时间9开始执行,在时间12结束执行。 进程5在时间12开始执行,在时间16结束执行。 进程1在时间16开始执行,在时间19结束执行。 进程3在时间19开始执行,在时间22结束执行。 进程5在时间22开始执行,在时间25结束执行。 进程1在时间25开始执行,在时间28结束执行。 进程5在时间28开始执行,在时间31结束执行。 可以看到,三种调度算法产生的结果不同,但都能正确地完成进程调度。其中,最短作业优先算法在本例中获得了最短的平均等待时间和平均周转时间,同时也是最优的算法。

相关推荐

最新推荐

recommend-type

计算机操作系统 进程调度 实验报告

1)本实验目的是通过对进程调度算法的实现和实验模拟,加深对操作系统进程调度操作功能和进程调度算法的完整理解,培养和提高学生对操作系统开发的兴趣,以及进程调度程序的开发与应用能力; 2)理论上必须深刻理解...
recommend-type

《操作系统》进程调度实验报告

编写并调试一个模拟的进程调度程序。采用“轮转法”调度算法对五个进程进行调度。 轮转法可以是简单轮转法,可变时间片轮转法,或多队列轮转法。 简单轮转法的基本思想是:所有就绪进程按FCFS排成一个队列,总是把...
recommend-type

操作系统实验报告 进程调度 作业调度等

操作系统实验报告 1、进程调度 2、作业调度 3、作业调度4、文件系统 一、 实验目的 用高级语言编写和调试一个进程调度程序,以加深对进程的概念及进程调度算法的理解。 二、实验内容和要求 编写并调试一个模拟的...
recommend-type

OS实验报告.docx

本实验模拟实现处理机调度及内存分配及回收机制,以对处理机调度的工作原理以及内存管理的工作过程进行更深入的了解。 二、实验内容及要求 1.实验内容 (1)选择一个调度算法,实现处理机调度; (2)结合(1)...
recommend-type

按优先级调度发进行CPU调度实验报告

多道系统中,当就绪进程数大于处理机数时,须按照某种策略决定哪些进程优先占用处理机,以使系统中的歌就绪进程有条不紊的运行。本实验模拟实现处理机调度,以加深对处理机调度的理解
recommend-type

RTL8188FU-Linux-v5.7.4.2-36687.20200602.tar(20765).gz

REALTEK 8188FTV 8188eus 8188etv linux驱动程序稳定版本, 支持AP,STA 以及AP+STA 共存模式。 稳定支持linux4.0以上内核。
recommend-type

管理建模和仿真的文件

管理Boualem Benatallah引用此版本:布阿利姆·贝纳塔拉。管理建模和仿真。约瑟夫-傅立叶大学-格勒诺布尔第一大学,1996年。法语。NNT:电话:00345357HAL ID:电话:00345357https://theses.hal.science/tel-003453572008年12月9日提交HAL是一个多学科的开放存取档案馆,用于存放和传播科学研究论文,无论它们是否被公开。论文可以来自法国或国外的教学和研究机构,也可以来自公共或私人研究中心。L’archive ouverte pluridisciplinaire
recommend-type

Redis验证与连接:快速连接Redis服务器指南

![Redis验证与连接:快速连接Redis服务器指南](https://img-blog.csdnimg.cn/20200905155530592.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMzNTg5NTEw,size_16,color_FFFFFF,t_70) # 1. Redis验证与连接概述 Redis是一个开源的、内存中的数据结构存储系统,它使用键值对来存储数据。为了确保数据的安全和完整性,Redis提供了多
recommend-type

gunicorn -k geventwebsocket.gunicorn.workers.GeventWebSocketWorker app:app 报错 ModuleNotFoundError: No module named 'geventwebsocket' ]

这个报错是因为在你的环境中没有安装 `geventwebsocket` 模块,可以使用下面的命令来安装: ``` pip install gevent-websocket ``` 安装完成后再次运行 `gunicorn -k geventwebsocket.gunicorn.workers.GeventWebSocketWorker app:app` 就不会出现这个报错了。
recommend-type

c++校园超市商品信息管理系统课程设计说明书(含源代码) (2).pdf

校园超市商品信息管理系统课程设计旨在帮助学生深入理解程序设计的基础知识,同时锻炼他们的实际操作能力。通过设计和实现一个校园超市商品信息管理系统,学生掌握了如何利用计算机科学与技术知识解决实际问题的能力。在课程设计过程中,学生需要对超市商品和销售员的关系进行有效管理,使系统功能更全面、实用,从而提高用户体验和便利性。 学生在课程设计过程中展现了积极的学习态度和纪律,没有缺勤情况,演示过程流畅且作品具有很强的使用价值。设计报告完整详细,展现了对问题的深入思考和解决能力。在答辩环节中,学生能够自信地回答问题,展示出扎实的专业知识和逻辑思维能力。教师对学生的表现予以肯定,认为学生在课程设计中表现出色,值得称赞。 整个课程设计过程包括平时成绩、报告成绩和演示与答辩成绩三个部分,其中平时表现占比20%,报告成绩占比40%,演示与答辩成绩占比40%。通过这三个部分的综合评定,最终为学生总成绩提供参考。总评分以百分制计算,全面评估学生在课程设计中的各项表现,最终为学生提供综合评价和反馈意见。 通过校园超市商品信息管理系统课程设计,学生不仅提升了对程序设计基础知识的理解与应用能力,同时也增强了团队协作和沟通能力。这一过程旨在培养学生综合运用技术解决问题的能力,为其未来的专业发展打下坚实基础。学生在进行校园超市商品信息管理系统课程设计过程中,不仅获得了理论知识的提升,同时也锻炼了实践能力和创新思维,为其未来的职业发展奠定了坚实基础。 校园超市商品信息管理系统课程设计的目的在于促进学生对程序设计基础知识的深入理解与掌握,同时培养学生解决实际问题的能力。通过对系统功能和用户需求的全面考量,学生设计了一个实用、高效的校园超市商品信息管理系统,为用户提供了更便捷、更高效的管理和使用体验。 综上所述,校园超市商品信息管理系统课程设计是一项旨在提升学生综合能力和实践技能的重要教学活动。通过此次设计,学生不仅深化了对程序设计基础知识的理解,还培养了解决实际问题的能力和团队合作精神。这一过程将为学生未来的专业发展提供坚实基础,使其在实际工作中能够胜任更多挑战。