操作系统 处理器调度——实时调度 算法EDF和RMS

(一)实验目的
深入理解处理机调度算法,了解硬实时概念,掌握周期性实时任务调度算法EDF(Earliest Deadline First)和RMS(Rate Monotonic Scheduling)的可调度条件,并能在可调度情况下给出具体调度结果。
(二)实验内容
在Linux环境中采用用户级线程模拟实现EDF和RMS两种实时调度算法。给定一组实时任务,按照EDF算法和RMS算法分别判断是否可调度,在可调度的情况下,创建一组用户级线程,分别代表各个实时任务,并按算法确定的调度次序安排各个线程运行,运行时在终端上画出其Gantt图。为避免图形绘制冲淡算法,Gantt图可用字符表示。 (三)实验准备
EDF算法和RMS算法的可调度条件及调度原则。。
在Linux环境中创建用户级线程的函数。
EDF为可抢先式调度算法,其调度条件为sum(Ci/Ti)£1;RMS算法为不可抢先调度算法,其调度条件为sum(Ci/Ti)£n(exp(ln(2)/n)-1)。
创建用户级线程的库函数为:
int pthread_create (pthread_t *THREAD,
pthread_attr_t * ATTR, void * (*START_ROUTINE)
(void ), void ARG
pthread_create(tid,NULL,func,arg);
其中第一个参数是pthread_t型的指针,用于保存线程id;第二个参数是pthread_attr_t的指针,用于说明要创建的线程的属性,NULL表示使用缺省属性;第三个参数指明了线程的入口,是一个只有一个(void *)参数的函数;第四个参数是传给线程入口函数的参数
(四)实验设计
实时任务用task数据结构描述,设计四个函数:select_proc()用于实现调度算法,被选中任务执行proc(),在没有可执行任务时执行idle(),主函数mian()初始化相关数据,创建实时任务并对任务进行调度。
为模拟调度算法,给每个线程设置一个等待锁,暂不运行的任务等待在相应的锁变量上。主线程按调度算法唤醒一个子线程,被选中线程执行一个时间单位,然后将控制权交给主线程判断是否需要重新调度。

实验代码:

#include "math.h"
#include "sched.h"
#include "pthread.h"
#include "stdlib.h"
#include "semaphore.h" 
#include "stdio.h"
typedef struct{  //实时任务描述
    char task_id;
    int call_num;  //任务发生次数
 int ci;  // Ci
    int ti;  //Ti 
    int ci_left;
    int ti_left; 
    int flag;  //任务是否活跃,0否,2是
    int arg;  //参数
    pthread_t th;  //任务对应线程
}task;
void proc(int* args);
void* idle();
int select_proc();
int task_num = 0;
int idle_num = 0;
int alg;  //所选算法,1 for EDF,2 for RMS
int curr_proc=-1;
int demo_time = 100;  //演示时间
task* tasks;
pthread_mutex_t proc_wait[100];
pthread_mutex_t main_wait, idle_wait;
float sum=0;
pthread_t idle_proc;
int main(int argc,char** argv)
{   
    pthread_mutex_init(&main_wait,NULL);
    pthread_mutex_lock(&main_wait);  //下次执行lock等待
    pthread_mutex_init(&idle_wait,NULL);
    pthread_mutex_lock(&idle_wait);  //下次执行lock等待
    printf("Please input number of real time tasks:\n");
    scanf("%d",&task_num);
    tasks = (task*)malloc(task_num*sizeof(task));
    int i;
for(i=0;i<task_num;i++)
{
        pthread_mutex_init(&proc_wait[i],NULL);
        pthread_mutex_lock(&proc_wait[i]);
    }
for(i=0;i<task_num;i++)
{
        printf("Please input task id, followed by Ci and Ti:\n");
    getchar();
        scanf("%c,%d,%d,",&tasks[i].task_id,&tasks[i].ci,&tasks[i].ti);
        tasks[i].ci_left=tasks[i].ci;
        tasks[i].ti_left=tasks[i].ti;
        tasks[i].flag=2;
        tasks[i].arg=i;
        tasks[i].call_num=1; 
        sum=sum+(float)tasks[i].ci/(float)tasks[i].ti; 
    }
    printf("Please input algorithm, 1 for EDF, 2 for RMS:");
    getchar();
    scanf("%d",&alg);
    printf("Please input demo time:");
    scanf("%d",&demo_time);
    double r=1;  //EDF算法
    if(alg==2)
    {  //RMS算法
        r=((double)task_num)*(exp(log(2)/(double)task_num)-1);
        printf("r is %lf\n",r);
    }
    if(sum>r)
    {  //不可调度
        printf("(sum=%lf > r=%lf) ,not schedulable!\n",sum,r);
        exit(2);
    }

    pthread_create(&idle_proc,NULL,(void*)idle,NULL); //创建闲逛线程
    for(i=0;i<task_num;i++)  //创建实时任务线程
        pthread_create(&tasks[i].th,NULL,(void*)proc,&tasks[i].arg);
    for(i=0;i<demo_time;i++)
    {
         int j; 
         if((curr_proc=select_proc(alg))!=-1)
         {  //按调度算法选线程
             pthread_mutex_unlock(&proc_wait[curr_proc]);  //唤醒
             pthread_mutex_lock(&main_wait);  //主线程等待
          }
          else
          {   //无可运行任务,选择闲逛线程
              pthread_mutex_unlock(&idle_wait);  
              pthread_mutex_lock(&main_wait);
          }
         for(j=0;j<task_num;j++)
          {  //Ti--,为0时开始下一周期
              if(--tasks[j].ti_left==0)
              {
                  tasks[j].ti_left=tasks[j].ti;
                  tasks[j].ci_left=tasks[j].ci;
                  pthread_create(&tasks[j].th,NULL,(void*)proc,&tasks[j].arg);
                  tasks[j].flag=2;
              }
         }
    }
    printf("\n");
    sleep(10); 
};

void proc(int* args)
{
    while(tasks[*args].ci_left>0)
    {
        pthread_mutex_lock(&proc_wait[*args]);  //等待被调度
        if(idle_num!=0)
{
            printf("idle(%d)",idle_num);
idle_num=0;
        }
        printf("%c%d",tasks[*args].task_id,tasks[*args].call_num);
        tasks[*args].ci_left--;  //执行一个时间单位
        if(tasks[*args].ci_left==0)
        {
            printf("(%d)",tasks[*args].ci);
            tasks[*args].flag=0;
            tasks[*args].call_num++;
        }
        pthread_mutex_unlock(&main_wait); //唤醒主线程
    }
};
void* idle()
{
     while(1)
      {
        pthread_mutex_lock(&idle_wait);  //等待被调度
        printf("->");  //空耗一个时间单位
        idle_num++;
        pthread_mutex_unlock(&main_wait);  //唤醒主控线程
    }
};
int select_proc(int alg)
{
    int j;
    int temp1,temp2;
    temp1=10000;
    temp2=-1;
    if((alg==2)&&(curr_proc!=-1)&&(tasks[curr_proc].flag!=0))
        return curr_proc; 

      for(j=0;j<task_num;j++)
      {
        if(tasks[j].flag==2)
          {
            switch(alg)
              {
                case 1:    //EDF算法
                     if(temp1>tasks[j].ci_left)
                        {
                           temp1=tasks[j].ci_left;
                            temp2=j;
                    }
                case 2:    //RMS算法
                   if(temp1>tasks[j].ti)
                          {
                        temp1=tasks[j].ti;
                        temp2=j;
                    }
               }
             }
         }
            return temp2;
}

编译:gcc -lpthread -lm test_scheduler.c -o scheduler.out
运行:./ scheduler.out
/算法EDF结果/
这里写图片描述
/算法RMS结果/
这里写图片描述

  • 14
    点赞
  • 99
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是一个简单的 C 语言周期性任务实时调度 EDFEarliest Deadline First)的伪代码: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <time.h> #define MAX_TASKS 10 typedef struct { int period; // 周期 int deadline; // 最后期限 int wcet; // 最坏情况执行时间 int remaining_time; // 剩余执行时间 } task_t; task_t tasks[MAX_TASKS]; int num_tasks = 0; int current_task = 0; void handler(int signum) { tasks[current_task].remaining_time--; if (tasks[current_task].remaining_time == 0) { printf("Task %d completed\n", current_task); tasks[current_task].remaining_time = tasks[current_task].wcet; tasks[current_task].deadline += tasks[current_task].period; } int min_deadline = INT_MAX; for (int i = 0; i < num_tasks; i++) { if (tasks[i].deadline < min_deadline) { min_deadline = tasks[i].deadline; current_task = i; } } } void add_task(int period, int wcet) { tasks[num_tasks].period = period; tasks[num_tasks].deadline = period; tasks[num_tasks].wcet = wcet; tasks[num_tasks].remaining_time = wcet; num_tasks++; } int main() { signal(SIGALRM, handler); struct itimerval timer; timer.it_interval.tv_sec = 0; timer.it_interval.tv_usec = 100000; // 100ms调度一次 timer.it_value = timer.it_interval; setitimer(ITIMER_REAL, &timer, NULL); add_task(3, 2); // 周期为3,最坏情况执行时间为2 add_task(4, 3); // 周期为4,最坏情况执行时间为3 while (1) { pause(); } return 0; } ``` 以上代码中,我们定义了一个 `task_t` 结构体表示每个任务的周期、最后期限、最坏情况执行时间和剩余执行时间。我们还定义了一个任务数组 `tasks` 和任务数量 `num_tasks`。在 `main` 函数中,我们使用 `setitimer` 设置一个周期为 100ms 的定时器,并为 `SIGALRM` 信号注册一个处理函数 `handler`。`handler` 函数会检查当前任务的剩余执行时间,如果为 0,说明任务已经完成,需要重置其剩余执行时间和最后期限;然后找到最早的最后期限的任务作为下一个要执行的任务。 在主函数中,我们通过 `add_task` 函数向 `tasks` 数组中添加任务,然后通过 `pause` 函数让程序等待信号的到来。注意,以上代码只是一个简单的示例,实际的周期性任务调度需要考虑更多的细节,比如任务的优先级、任务的实际执行时间与最坏情况执行时间的差异等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值