吉林大学操作系统上机(实验二:处理机调度——实时调度算法EDF和RMS)
上文已能解决本次实验基础部分,本文主要关注加分项,即完成其它任意调度算法。
1.在原实时调度框架下实现HRN(最高相应比)算法
在书上参考代码的select_pro部分加入RR(相应比)的计算和取最高,代码如下:
#include "math.h"
#include "sched.h"
#include "pthread.h"
#include "stdlib.h"
#include "semaphore.h"
#include "stdio.h"
#include <unistd.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,3 for HRN
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, 3 for HRN:");
getchar();
scanf("%d", &alg);
printf("Please input demo time:");
scanf("%d", &demo_time);
double r = 1; //EDF算法
if (alg != 1)
{ //RMS或HRN算法
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;
double temp3 = 0.0;
temp1 = 10000;
temp2 = -1;
if ((alg != 1) && (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].ti_left)
{
temp1 = tasks[j].ti_left;
temp2 = j;
}
break;
case 2: //RMS算法
if (temp1 > tasks[j].ti)
{
temp1 = tasks[j].ti;
temp2 = j;
}
break;
case 3:
double RR = 1 + ((double)tasks[j].ti-tasks[j].ti_left)/tasks[j].ci;
if(RR > temp3){ //HRN算法
temp3 = RR;
temp2 = j;
}
break;
}
}
}
return temp2;
}
具体实现:
case 3:
double RR = 1 + ((double)tasks[j].ti-tasks[j].ti_left)/tasks[j].ci;
if(RR > temp3){ //HRN算法
temp3 = RR;
temp2 = j;
}
break;
}
响应比定义:
(要求服务时间)
(等待时间)
具体来看,要求服务时间BT即为运行时间Ci,等待时间WT即为(周期时间Ti-周期剩余时间Ti_left);带入公式得到相应比RR。(注意:计算时,需将其中一项强制类型转换为double,否则计算出来为int,舍弃小数部分)
其他修改:
1.由于HRN算法也是非剥夺式算法,其调度可行性和RMS算法相同,也要根据n计算r;且类似RMS算法,可在select_pro中,判断已选择任务是否完成,是,继续选择;否,直接返回原任务。
2.算法选择提示加入3 for HRN;
问题:
测试发现,HRN和RMS调度策略相同。分析得出,对于实时调度系统,非剥夺式算法,RMS算法就是最优解;剥夺式算法,EDF就是最优解。实现其他算法意义不大。
2.修改原框架为到达时间不同的一次性任务序列
代码:
#include "math.h"
#include "sched.h"
#include "pthread.h"
#include "stdlib.h"
#include "semaphore.h"
#include "stdio.h"
#include <unistd.h>
typedef struct { //任务描述
char task_id;
int ci; // Ci 运行时间
int ti; //Ti 到达时间
int ci_left;
int ti_wait; //等待时间
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 HRN, 2 for SRTF
int curr_proc = -1;
int demo_time = 100; //演示时间
task* tasks;
pthread_mutex_t proc_wait[100];
pthread_mutex_t main_wait, idle_wait;
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 Ti and Ci:\n");
getchar();
scanf("%c,%d,%d,", &tasks[i].task_id, &tasks[i].ti, &tasks[i].ci);
tasks[i].ci_left = tasks[i].ci;
tasks[i].ti_wait = 0;
tasks[i].flag = 0;
tasks[i].arg = i;
}
printf("Please input algorithm, 1 for HRN, 2 for SRTF:");
getchar();
scanf("%d", &alg);
printf("Please input demo time:");
scanf("%d", &demo_time);
pthread_create(&idle_proc, NULL, (void*)idle, NULL); //创建闲逛线程
for (i = 0; i < demo_time; i++)
{
int j;
for (j = 0; j < task_num; j++) {//为到达任务创建任务线程
if (tasks[j].ti == i) {
pthread_create(&tasks[j].th, NULL, (void*)proc, &tasks[j].arg);
tasks[j].flag = 2;
}
}
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_wait++
if (tasks[j].flag == 2)
{
tasks[j].ti_wait++;
}
}
}
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", tasks[*args].task_id);
tasks[*args].ci_left--; //执行一个时间单位
if (tasks[*args].ci_left == 0)
{
printf("(%d)", tasks[*args].ci);
tasks[*args].flag = 0;
}
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;
double temp3 = 0.0;
temp2 = -1;
temp1 = 10000;
if ((alg == 1) && (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:
double RR = 1 + ((double)tasks[j].ti_wait) / tasks[j].ci;
if (RR > temp3) { //HRN算法
temp3 = RR;
temp2 = j;
}
break;
case 2:
if (tasks[j].ci_left < temp1) {//SRTF算法
temp1 = tasks[j].ci_left;
temp2 = j;
}
}
}
}
return temp2;
}
修改部分:
1. 任务描述:
typedef struct { //任务描述
char task_id;
int ci; // Ci 运行时间
int ti; //Ti 到达时间
int ci_left;
int ti_wait; //等待时间
int flag; //任务是否活跃,0否,2是
int arg; //参数
pthread_t th; //任务对应线程
}task;
到达时间不同的一次性任务没有没有周期和周期剩余时间,直接改为到达时间ti和等待时间ti_wait,删去不需要的call_num。
2.任务录入
for (i = 0; i < task_num; i++)
{
printf("Please input task id, followed by Ti and Ci:\n");
getchar();
scanf("%c,%d,%d,", &tasks[i].task_id, &tasks[i].ti, &tasks[i].ci);
tasks[i].ci_left = tasks[i].ci;
tasks[i].ti_wait = 0;
tasks[i].flag = 0;
tasks[i].arg = i;
}
先到达时间题,后运行时间ci。并将等待时间ti_wait和活跃标志flag都置为0(任务到达时,flag置为2,任务运行结束,flag置为0)
3.任务进程创建
for (j = 0; j < task_num; j++) {//为到达任务创建任务线程
if (tasks[j].ti == i) {
pthread_create(&tasks[j].th, NULL, (void*)proc, &tasks[j].arg);
tasks[j].flag = 2;
}
}
每个时间点,若为任务到达时间,创建任务进程,其flag置为2,表示活跃。
4.等待时间增加
for (j = 0; j < task_num; j++)
{ //ti_wait++
if (tasks[j].flag == 2)
{
tasks[j].ti_wait++;
}
}
每个时间点,对于活跃任务(已到达,未完成),其等待时间加一。
SRTF算法实现
SRTF(最短剩余时间)算法只需要比较剩余运行时间ci_left,且其为剥夺式算法,每次都比较。
case 2:
if (tasks[j].ci_left < temp1) {//SRTF算法
temp1 = tasks[j].ci_left;
temp2 = j;
}
}
运行结果:
以作业题为例:

2万+

被折叠的 条评论
为什么被折叠?



