【操作系统】简单调度算法的一种特殊实现

本文分享了一次操作系统作业中的非抢占式调度算法实现,包括先来先服务(FCFS)、短作业优先(SJF)和高响应比优先等策略。通过双指针和数组模拟队列的方法解决调度问题,详细阐述了每种算法的思路和代码实现,强调了在处理到达时间相同和响应比计算时的策略。
摘要由CSDN通过智能技术生成

这个是我一次的操作系统作业,在赶ddl的过程中临时产生的一种比较特别的实现思路,在此处分享。

这里的算法都是非抢占式,由于我本人比较懒,所以这里只有一些比较简单的算法。但是因为这个思路比较清奇,所以在此记录一下:

先来先服务算法

这个是实验中已经提供的算法,思路比较简单,就是直接比较几个进程的到达时间,谁最先到达就先服务,先到先得,而且是非抢占式,所以这里的实现非常的简单,代码如下:

void FCFS()
{
	int i, j, temp;
	double k;
	for(i = 0; i < num; i++)
	{
		order[i] = pcbdata[i].time_start;
		ready[i] = i;
	}
	for(i = 0; i < num;i++) // 简单冒泡排序
	{
		for(j = i + 1; j < num; j++)
		{
			if(order[i]  >  order[j])
			{
				temp = order[i];
				order[i] = order[j];
				order[j] = temp;
				temp = ready[i];
				ready[i] = ready[j];
				ready[j] = temp;
			}
		}
	}
	printf("FIFO running...\n");
    temp =pcbdata[ready[0]].time_start;
    for(i = 0;i < num;++i){
        printf("第%d个进程-- %s:",i+1,pcbdata[ready[i]].name);
        printf("到达时间: %d, 服务时间: %d\n",pcbdata[ready[i]].time_start,pcbdata[ready[i]].time_need);
        printf("本进程正在运行...\n");
        _sleep(1);
        printf("运行完毕\n");
        temp += pcbdata[ready[i]].time_need;
        j = temp - pcbdata[ready[i]].time_start;
        k = (double)j/pcbdata[ready[i]].time_need;
        printf("完成时间: %d, 周转时间: %d, 带权周转时间: %.2lf\n",temp,j,k);
    }
    printf("所有进程运行完毕.\n");
}

这里代码比较捞,没有用到比较方便的STL以及sort函数,后面的算法中需要用到队列,这里用数组来模拟这个队列。

短作业优先算法

短作业优先在上面先来先服务算法的基础上,加了一个对服务时间进行排序的过程,每一次找队列中服务时间最短的作业进行调度。这里就存在这么一个问题,我们不能像上面的实现直接对到达时间进行排序了那样对服务时间进行排序,因为这里也要遵循一个先来先到的原则。

这个就是本次激发我思路的地方,由于这里没有队列,所以想到用数组模拟队列,这里我将数组用两个指针分为三个部分,就像下面这个图一样。
在这里插入图片描述

而筛选最小运行时间的任务的工作,只需要在已入队列的部分中进行排序即可。所以这里整个算法的流程如下:

  1. 先对所有的任务的到达时间进行排序。
  2. 初始化三个部分的分割指针,初始化为0。初始化开始的时间
  3. 从未入队列部分中找出所有时间中等于当前任务的到达时间的任务(处理到达时间相同的情形),将其入队列。调整两个指针。
  4. 在两个指针中进行排序,得到以运行时间排序的队列
  5. 出队列头部处理任务,回到步骤3.

实现代码如下:

void SJF() // 短作业优先算法
{
	int ele_num_begin_pointer = 0;
	int ele_num_end_pointer = 0;
	int i, j, temp, t;
	double k;
	for(i = 0; i < num; i++)
	{
		order[i] = pcbdata[i].time_start;
		order2[i] = pcbdata[i].time_need;
		ready[i] = i;
	}
	for(i = 0; i < num;i++)
	{
		for(j = i + 1; j < num; j++)
		{
			if(order[i]  >  order[j])
			{
				temp = order[i];
				order[i] = order[j];
				order[j] = temp;
				temp = ready[i];
				ready[i] = ready[j];
				ready[j] = temp;
				temp = order2[i];
				order2[i] = order2[j];
				order2[j] = temp;
			}
		}
	}
	printf("SJF running...\n");
    temp =pcbdata[ready[0]].time_start;
	while(ele_num_begin_pointer < num)
	{
		int cnt = 0;
		for(i = ele_num_end_pointer; i < num; i++)
		{
			if(pcbdata[ready[i]].time_start <= temp)
			{
				cnt++;
			}
		}
		ele_num_end_pointer += cnt;
		// inner sort
		for(i = ele_num_begin_pointer; i < ele_num_end_pointer;i++)
		{
			for(j = ele_num_begin_pointer + 1; j < ele_num_end_pointer; j++)
			{
				if(order2[i]  >  order2[j])
				{
					t = order2[i];
					order2[i] = order2[j];
					order2[j] = t;
					t = ready[i];
					ready[i] = ready[j];
					ready[j] = t;
				}
			}
		}
		// running process
		printf("第%d个进程-- %s:",ele_num_begin_pointer+1,pcbdata[ready[ele_num_begin_pointer]].name);
        printf("到达时间: %d, 服务时间: %d\n",pcbdata[ready[ele_num_begin_pointer]].time_start,pcbdata[ready[ele_num_begin_pointer]].time_need);
        printf("本进程正在运行...\n");
        _sleep(1);
        printf("运行完毕\n");
        temp += pcbdata[ready[ele_num_begin_pointer]].time_need;
        j = temp - pcbdata[ready[ele_num_begin_pointer]].time_start;
        k = (double)j/pcbdata[ready[ele_num_begin_pointer]].time_need;
        printf("完成时间: %d, 周转时间: %d, 带权周转时间: %.2lf\n",temp,j,k);
		ele_num_begin_pointer += 1;
	}
    printf("所有进程运行完毕.\n");
}

你看,这样的思路是不是清晰了许多?

然后还有高响应比算法和时间片轮转算法,都是基于上面的这个模板思路,通过这个双指针滑动窗口的方法可以很好的将进程按照到达时间依次进入数组中。

高响应比优先算法

先来先服务可能会长阻塞,而短作业优先可能长作业一辈子也执行不了,为了解决这个问题,找到了一种折中的方法,那就是高响应比优先调度策略。响应比计算公式如下:

H R F = w a i t + n e e d n e e d = w a i t n e e d + 1 HRF = \frac{wait+need}{need}=\frac{wait}{need}+1 HRF=needwait+need=needwait+1

在上面短作业优先的基础之上,只需要将短作业的选择改为响应比的选择即可。由于这里我使用类似滑动窗口的方法用数组模拟队列,这里将会使得进入调度的任务都是严格按照时间前后进行处理的。这里只需要补充响应比的迭代即可。

时间片轮转算法

时间片轮转策略则是以时间片为一个调度切换周期。当时间片完了之后,进入先来先服务的调度中,当一个任务在时间片完了之后的剩余时间还不是0,则将该任务调度到队列的末尾中。与其他的进程继续在队列中等候处理。

这里同样需要考虑时间的前后问题,所以还是使用前面滑动窗口,数组模拟队列的思路。这里需要补充的就是更新进程pcb的剩余时间,判断时间片完时,是否运行完,如果没有则将其排到队列末尾中。这里的排到末尾步骤只需要在第二个部分中的已入队列部分中进行处理即可。

,则将该任务调度到队列的末尾中。与其他的进程继续在队列中等候处理。

这里同样需要考虑时间的前后问题,所以还是使用前面滑动窗口,数组模拟队列的思路。这里需要补充的就是更新进程pcb的剩余时间,判断时间片完时,是否运行完,如果没有则将其排到队列末尾中。这里的排到末尾步骤只需要在第二个部分中的已入队列部分中进行处理即可。

所有代码:https://download.csdn.net/download/Dong142857/19160293

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值