吉林大学操作系统上机实验二(HRN算法和SRTF算法实现)

吉林大学操作系统上机(实验二:处理机调度——实时调度算法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;
            }

响应比定义:

 RR=\frac{(BT+WT)}{BT}=1+\frac{WT}{BT}

BT=burst time(要求服务时间)

WT=wait time(等待时间)

具体来看,要求服务时间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;
                }
            }

运行结果:

以作业题为例:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值