版权声明:醋姑娘 https://blog.csdn.net/weixin_37023469/article/details/84172885
一、说明
模拟了下面四种CPU调度算法
- FCFS,先到先服务
- SRTF,抢占式最短剩余时间优先
- RR,轮询
- 抢占式优先级
实验要求
- gantt图
- 计算每个进程的等待时间
- 计算平均等待时间
- 考虑CPU空闲的情况
其他
- 前端使用了Bootstrap框架,因为时间紧迫而且确实效果还行。
- github地址:https://github.com/cuguniang/CPU_Schedual
二、实现效果
-
进程信息
-
FCFS
-
SRTF
-
RR
-
优先级
-
CPU空闲的情况
三、实现时的一些思考
-
用户添加的顺序 != CPU调度的顺序,需要重新排序,而希望进程列表中显示的顺序仍是用户输入的顺序,所以在实现调度前,先深拷贝用户输入的数组。
-
gantt图使用彩色块看起来效果更好,本来想在一个大div里塞小div,但很丑。决定用bs的进度条组件,这是用bs框架的最重要的原因!但具体实现的时候,其实还是往大div里塞小div,只不过这里的div具有bs的class。
gantt图效果:
对应的html:
-
学会用array的sort和比较函数了,如下
scheual_process.sort(function (a, b) {
//到达时间一样,短作业优先
if(a.arrival_time == b.arrival_time){
return a.CPU_brust - b.CPU_brust;
}
//否则按到达时间排序
return a.arrival_time - b.arrival_time;
});
- 希望每段进程的CPU区间颜色不同,采用bs提供的progress-bar-xxx类,xxx=primary|warning|error|sucess|info,分别具有不同的颜色,一开始随机获取数组中一个值,作为每段的颜色。但是相邻的两段有时候就会颜色相同,于是就按顺序循环取:希望每段进程的CPU区间颜色不同,采用bs提供的progress-bar-xxx类,xxx=primary|warning|error|sucess|info,分别具有不同的颜色,一开始随机获取数组中一个值,作为每段的颜色。但是相邻的两段有时候就会颜色相同,于是就按顺序循环取:
var COLOR = {
color:["primary","warning","success","danger","default","info"],
index:0
};
function getColor(){
return COLOR.color[(COLOR.index++)%COLOR.color.length];
}
- 抢占实在是太难写了。当前进程结束时,如果没有别的进程,它就空闲,否则选择一个剩余时间最短的进程来执行;如果没执行完,一个新的进程就来到了,判断它的剩余时间和新进程的剩余时间,新进程更短的话,就抢占。最外层循环条件是:
while(scheual_process.length>0 || ready_queue.length>0){
...
//多种情况
1. CPU空闲
2. now_p结束时next_p还未到达 => ready_queue中还有没有进程?
3. 刚好在结束时到达 => 加入ready_queue一起排序
4. 未结束时到达,可能抢占 => 比较剩余时间
}
- 写了两个类,Process用来调度,Bar用来绘制gantt图
function Process(process_name,arrival_time,CPU_brust,priority) {
this.process_name = process_name;
this.arrival_time = arrival_time;
this.CPU_brust = CPU_brust;
this.priority = priority;
this.remaining_time = CPU_brust;
this.waiting_time = 0;
this.start_time = 0;
this.end_time = 0;
return this;
}
function Bar(name,start,end,color){//for gantt
this.name = name;
this.start = start;
this.end = end;
this.color = color;
return this;
}
附:利用Bar的对象数组bars来绘制gantt,包括下面的数字
function process_painter(bars,total_brust){
for(var i = 0;i < bars.length;i++){
var num = $("<span></span>");
var bar = $("<div></div>").addClass("progress-bar");
bar.addClass("progress-bar-"+bars[i].color);//进程颜色
bar.text(bars[i].name);//进程名字
bar.css('width',((bars[i].end-bars[i].start)/total_brust*100)+"%");//进程比例
$("#gantt").append(bar);
num.text(bars[i].end);
num.css('width',(bars[i].end-bars[i].start)/total_brust*100-0.5+"%");
$("#gantt_num").append(num);
}
}
在每个调度算法中往bars里添加元素,如
bars.push(new Bar(p.process_name,now_time,now_time+time_q,getColor()));
最后调用process_painter()方法即可
process_painter(bars,now_time);
- 如果一个进程分开执行了多次,每次等待时间就不能用now_time-减去arrival_time。要考虑是不是第一次执行到它,而且每次调度时,要更新它的start_time和end_time。(SRTF中代码如下)
if(now_p.CPU_brust == now_p.remaining_time){//第一次执行到它
now_p.start_time = now_time;
now_p.waiting_time += now_p.start_time - now_p.arrival_time;
}
else{
now_p.waiting_time = now_time - (now_p.end_time-now_p.start_time);
now_p.start_time = now_time;
}
- 被array的splice方法坑死(最开始还拼错了),第一个参数是index,最终改成这样才能把这个执行完的now_p给移除。
ready_queue.splice(ready_queue.indexOf(now_p),1);
- 优先级就是把SRTF的实现复制过来,改了抢占的条件和一点点细节(比如对remaining_time的处理)。实际上抢占式的优先级就是一般化的SRTF,SRTF的原则是剩余时间短 = 优先级高,而优先级是直接给了个数值代表优先级。注意small int ≡ high priority
四、反思
- Process类的定义应该从PCB的结构出发来考虑。
- 切换进程时,应该写一个类似切换上下文的函数。把对各种时间的设置写进函数里。