最早截止时间优先算法(EDF)-思考与编程

        最早截止时间优先(earliest deadline first,EDF)算法是根据任务的优先级,任务的截止时间越早,其优先级越高,具有最早截止时间的任务排在队列的前面。调度程序在选择任务时,总是选择就绪队列中的第一个任务,并为之分配处理机。EDF算法即可用于抢占式调度方式中,也可用于非抢占式调度方式中。

1.非抢占式调度方式用于非周期实时任务(参考《计算机操作系统慕课版》)

大家可通过以上图片了解非抢占式,本次主要以抢占式为主。

2.抢占式调度方式用于周期实时任务

我们先从《计算机操作系统慕课版》一个实例出发:现有两个周期实时任务A、B,其周期时间分别为20ms和50ms,每次周期的处理时间分别为10ms和25ms。

首先我们得先思考这个实例是否可行?

思考:任务A、B能否实现实时调度?为什么?

一个小知识点:假定系统中有m个周期性的HRT任务,它们一个周期内的处理时间为Ci,周期时间表示为Pi,则在单处理情况下,必须满足:C1/P1+C2/P2+……+Cm/Pm<=1 即每个任务的处理时间与周期时间比的和不超过1。我是这么理解:Ci/Pi是指i任务时间占用率,如果所有任务占用率小于等于100%,说明有机会按照一定的次序分配,如果超过100%肯定不会实现。

对本上面的实例 CA/PA+CB/PB=1 <=1,满足C1/P1+C2/P2+……+Cm/Pm<=1,所以可以实现。

思考:如果采用EDF算法实现?(参考《计算机操作系统慕课版》p88图3-8,即下图)

第一行是两个任务到达时间、执行时间和最晚截止时间图。

第二、三行是为了说明通常的优先级调度不能适用于实时系统,如果按照固定优先级调度下去(第二行A优先、第三行B优先),你会发现都会失败。

第四行则是采用EDF算法的时间图,根据截止时间决定优先级,截止时间越早,越优先。

那么你可能会问:如果截止时间相同怎么办?

如果截止时间相同先来的先执行,能不换就不换。

思考:EDF算法调度时机是什么?

在我看来:1.当前任务结束;2.新任务到达。(如果有错,欢迎大家批评指正)

思考:如何编写程序实现EDF算法?

代码思路:

首先确定好最后的截止时间我在代码中称之为大周期t,也就是所有任务的周期的最小公倍数;

其次就是利用公式判断可行性,前面已经提到过这个知识点;

最后就是利用结构体+sort+cmp确定调度顺序,然后不断地更新,使用结构体可以记录更多的信息。由于实例中任务数是n,我这里代码第6行n赋值为2,可根据实际需求更改。

欢迎各位大佬批评指正!

#include<cstdio>
#include<cstring>
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
const int n=2;//n表示任务数目,可以按照进程数目来更改n
int id;//该目的是为不重复输出某一个任务 
int ztime=0;//当前时间
int t=1;//t表示大周期
//EDF调度时机:1.当前任务结束(判断剩余的)2.新任务到达 /大周期得算出各个任务周期时间的最小公倍数
int gcd(int x,int y)
{   //最大公约数
    return y?gcd(y,x%y):x;
}
int lcm(int x, int y)
{   //最小公倍数
    return x*y/gcd(x,y);
}
struct Task
{
 int id;//序列号
 double ctime;//执行时间
 double ptime;//周期时间
 double atime;//到达时间
 double deadline;//截止时间
 double stime;//剩余时间
};
Task a[n];
bool cmp2(Task a,Task b)//排序规则
{
    if((a.atime<=ztime&&b.atime<=ztime)||(ztime>=a.atime&&ztime>=b.atime)) return a.deadline<b.deadline;//如果两个任务都到了或都没到,按截止时间排序
    else if (a.atime<=ztime&&b.atime>ztime)return true;//如果一个任务到了,另一个没到,任务先到的排在前面
    else return false;
}
void gx()
{//随着时间不断更新

    if(a[0].stime>0)
    {
        a[0].stime--;
    }
        if(a[0].stime<=0)
    {
        a[0].atime+=a[0].ptime;
        a[0].deadline+=a[0].ptime;
        a[0].stime+=a[0].ctime;
    }
   // cout<<"gx()第"<<a[0].id<<"的剩余时间"<<a[0].stime<<endl;当时debug使用的
    return;
}
int EDFdd()
{
 double m=0.0;//ci求和;
 cout<<"请分别输入这"<<n<<"个任务的序列号、第一个周期的执行时间id、ci、周期Pi"<<endl;
 for(int i=0;i<n;i++)
 {
  cin>>a[i].id>>a[i].ctime>>a[i].ptime;
  a[i].atime=0;//默认到达时间统一为0
  a[i].stime=a[i].ctime;//剩余时间参考执行时间
  a[i].deadline=a[i].atime+a[i].ptime;//截止时间
  m+=a[i].ctime/a[i].ptime;//需要根据公式判断可行吗
  t=lcm(t,a[i].ptime);//大周期=各个周期的最小公倍数
  }
  if(m>1)//利用公式判断是否可实现
  {
   cout<<"抱歉无法实现"<<endl;
   return 0;
  }
  sort(a,a+n,cmp2);id=a[0].id;//把第一个执行序的赋值给id
  for( ;ztime<=t;ztime++)
   {
       sort(a,a+n,cmp2);
       if(a[0].atime<=ztime)//如果有任务到达就可执行
       {
        if(ztime==0)//输出一个执行的
        cout<<"在"<<ztime<<"ms"<<a[0].id<<"开始执行"<<endl;
        else
        {
            if(id!=a[0].id)//为了不重复输出
            {
                cout<<"在"<<ztime<<"ms"<<a[0].id<<"开始执行"<<endl;
                id=a[0].id;
            }
        }
        gx();//更新
       }
   }
   cout<<"在"<<t<<"ms结束一个大周期"<<endl;
   return 0;
}
int main()
{
 EDFdd();
 return 0;
 }

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值