操作系统-作业调度算法设计

2021/12/20 17:29:23

本文主要是介绍操作系统-作业调度算法设计,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

作业调度算法设计

1.先来先服务调度算法(实现)
2.短作业优先调度算法(实现,但可能有漏洞)
3.最高响应比调度算法(实现,但可能有漏洞)
4.最短剩余时间调度算法(抢占式,实现,但可能有漏洞)

输入
数据存放于 data.txt 文件中,每列分别对应进程名进程到达时间进程运行时间

J1 8:00 30.0
J2 8:20 5.0
J3 8:30 15.0

代码详情

#define _CRT_SECURE_NO_WARNINGS
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct
{
    char pname[10];         // 进程名 = input
    float pid;              // 进程id = input
    char arrival[10];       // 到达时刻 = input
    float time_arrival;     // 到达时间 = time2int(arrival)
    float time_run;         // 运行时间 = input 单位:分钟
    float time_start;       // 开始时间 According to the reslut of the algorithm
    float time_finish;      // 完成时间 According to the reslut of the algorithm
    float time_remaining;   // 剩余时间
    char begin[10];         // 开始时刻 = "str(time_start/60):str(time_start%60)" use ecvt() or gcvt().
    char finish[10];        // 完成时刻 = "str(time_finish/60):str(time_finish%60)"
    float tar;              // 周转时间 Turnaround time = time_finish - ta
    float tarw;             // 带权周转时间 Turnaround time with weight = tar / tr
    float rp;               // 响应比
} process;

typedef struct
{
    int len;
    float ava_tar, ava_tarw; // 平均周转时间、平均带权周转时间
    process *processes;
} process_array;

void print_process_array(process_array *pa)
{
    printf("====================================================\
==================================================================\n");
    printf("\t进程名\t到达时间\t运行时间\t开始时间\t完成时间\t周转时间\t带权周转时间\n");
    for (int i = 0; i < pa->len; i++)
    {
        printf("----------------------------------------------------\
------------------------------------------------------------------\n");
        printf("\t %s\t %s\t\t %-.2f\t\t %s\t\t %s\t\t %-.2f\t\t   %-.2f\n",
               pa->processes[i].pname,
               pa->processes[i].arrival,
               pa->processes[i].time_run,
               pa->processes[i].begin,
               pa->processes[i].finish,
               pa->processes[i].tar,
               pa->processes[i].tarw);
    }
    printf("----------------------------------------------------\
------------------------------------------------------------------\n");
    printf("\t平均周转时间:\t\t\t\t\t\t\t\t %.2f\n", pa->ava_tar);
    printf("----------------------------------------------------\
------------------------------------------------------------------\n");
    printf("\t平均带权周转时间:\t\t\t\t\t\t\t\t\t   %.2f\n", pa->ava_tarw);
    printf("====================================================\
==================================================================\n");
}

// 释放内存
void free_process_array(process_array **pa)
{
    free((*pa)->processes);
    free(*pa);
    *pa = NULL;
}

int time2int(char *time)
{
    // 输入形如:xx:xx 格式的时间,输出分钟型的时间
    int len_char = sizeof(time);
    char t[10];
    for (int i = 0; i < len_char; i++)
    {
        t[i] = time[i];
    }
    char min[4];
    for (int i = 0; i < len_char; i++)
    {
        if (time[i] == ':')
        {
            int k = 0;
            while (time[k + i + 1] != '\0')
            {
                min[k] = time[k + i + 1];
                k++;
            }
            min[k] = '\0';
            break;
        }
    }
    char *hour = strtok(t, ":");
    return atol(hour) * 60 + atol(min); // 字符型转整型
}

char *int2time(int time, char *buf)
{
    int hour = (time / 60) % 24;
    int minute = time % 60;
    if (sprintf(buf, "%02d:%02d", hour, minute) < 0)
        return NULL;
    return buf;
}

// 初始化参数
void process_init(process_array *pa)
{
    for (int i = 0; i < pa->len; i++)
    {
        pa->processes[i].time_arrival = time2int(pa->processes[i].arrival);
        pa->processes[i].time_remaining = pa->processes[i].time_run;
        pa->processes[i].time_start = -1; // 代表进程未开始运行
        pa->processes[i].tar = -1; // 代表周转时间未计算
        pa->processes[i].tarw = -1; // 代表带权周转时间未计算
        pa->processes[i].rp = -1; // 代表响应比未计算
    }
}

// 到达时间排序,先到先排
void sort_by_arrive_time(process_array *pa)
{
    for (int i = 0; i < pa->len; i++)
    {
        for (int j = i + 1; j < pa->len; j++)
        {
            if (pa->processes[j].time_arrival < pa->processes[i].time_arrival)
            {
                process tmp = pa->processes[i];
                pa->processes[i] = pa->processes[j];
                pa->processes[j] = tmp;
            }
        }
    }
}

// 短作业优先
void shortest_job_first(process_array *pa)
{
    float current_time = -1; // -1 表示未初始化
    for (int i = 0; i < pa->len; i++)
    {
        if (current_time == -1)
        {
            current_time = pa->processes[i].time_arrival;
        }

        // 选择当前时刻内最短的作业
        int select = 0;
        for (int j = 0; j < pa->len; j++)
        {
            if (pa->processes[j].time_finish != 0)
            {
                continue; // 作业已经完成
            }

            if (pa->processes[j].time_arrival > current_time)
            {
                break; // 时间没到
            }

            if (pa->processes[j].time_run < pa->processes[select].time_run)
            {
                select = j;
            }
        }

        // 执行选择的任务
        pa->processes[select].time_start = current_time;
        int2time(pa->processes[select].time_start, pa->processes[select].begin);
        pa->processes[select].time_finish = pa->processes[select].time_start + pa->processes[select].time_run;
        int2time(pa->processes[select].time_finish, pa->processes[select].finish);
        pa->processes[select].tar = pa->processes[select].time_finish - pa->processes[select].time_arrival;
        pa->processes[select].tarw = pa->processes[select].tar / pa->processes[select].time_run;
        current_time = pa->processes[select].time_finish;
    }
}

// 响应比计算
float response_ratio(process process, int start_time)
{
    /* 响应比 = ((开始运行时间 - 作业到达时间) + 运行时间) / 运行时间 */
    return ((start_time - process.time_arrival) + process.time_run) / process.time_run;
}

// 最高响应比优先
// 用于作业/进程调度
// 非抢占式的算法,因此只有当前运行的作业/进程主动放弃处理器时,才需要调度,才需要计算响应比
void highest_response_ratio_priority(process_array *pa, char* start)
{
    int work_time = time2int(start);
    float max_rp;
    for (int m = 0; m < pa->len; m++)
    {
        max_rp = 0;
        int i = 0;
        // 统计有多少个作业/进程在某次调度开始前到达
        for (int n = 0; n < pa->len; n++)
        {
            if (pa->processes[n].time_arrival <= work_time)
            {
                if (pa->processes[n].rp != 0)
                {
                    // 计算这些作业的响应比,找出最大的
                    pa->processes[n].rp = response_ratio(pa->processes[n], work_time);
                    if (pa->processes[n].rp > max_rp)
                    {
                        max_rp = pa->processes[n].rp;
                        i = n;
                    }
                    continue;
                }
            }
            else
                break;
        }
        // 响应比最大的开始运行
        pa->processes[i].time_start = work_time;
        int2time(pa->processes[i].time_start, pa->processes[i].begin);
        pa->processes[i].time_finish = pa->processes[i].time_start + pa->processes[i].time_run;
        int2time(pa->processes[i].time_finish, pa->processes[i].finish);
        pa->processes[i].tar = pa->processes[i].time_finish - pa->processes[i].time_arrival;
        pa->processes[i].tarw = pa->processes[i].tar / pa->processes[i].time_run;
        work_time = pa->processes[i].time_finish; // 下一次进行作业调度时间为当前作业运行完成时刻
        pa->processes[i].rp = 0; // 完成作业
    }
}

// 先来先服务
void first_come_first_service(process_array *pa)
{
    float current_time = -1; // -1 表示未初始化
    for (int i = 0; i < pa->len; i++)
    {
        if (current_time == -1)
        {
            current_time = pa->processes[i].time_arrival;
        }

        pa->processes[i].time_start = current_time;
        int2time(pa->processes[i].time_start, pa->processes[i].begin); // 转成字符串
        pa->processes[i].time_finish = pa->processes[i].time_start + pa->processes[i].time_run;
        int2time(pa->processes[i].time_finish, pa->processes[i].finish);
        pa->processes[i].tar = pa->processes[i].time_finish - pa->processes[i].time_arrival;
        pa->processes[i].tarw = pa->processes[i].tar / pa->processes[i].time_run;
        current_time = pa->processes[i].time_finish;
    }
}

// 最短剩余优先(抢占式)
void shortest_residue_time_fist(process_array *pa)
{
    int curren_time = 0;
    curren_time = pa->processes[0].time_arrival;

    while (1)
    {
        int break_flag = 1;
        for (int i = 0; i < pa->len; i++)
        {
            if (pa->processes[i].time_remaining != 0)
            {
                break_flag = 0;
            }
        }
        if (break_flag == 1)
        {
            break;
        }

        // 找出最短剩余时间的进程
        int select = 0;
        for (int i = 0; i < pa->len; i++)
        {
            if (curren_time < pa->processes[i].time_arrival)
            {
                break;
            }

            if (pa->processes[i].time_remaining == 0)
            {
                continue;
            }

            if (pa->processes[i].time_remaining < pa->processes[select].time_remaining || pa->processes[select].time_remaining == 0)
            {
                select = i;
                break;
            }
        }

        // 抢占运行
        if (pa->processes[select].time_start == -1)
        {
            pa->processes[select].time_start = curren_time;
            int2time(pa->processes[select].time_start, pa->processes[select].begin); // 转成字符串
        }
        pa->processes[select].time_remaining--;
        curren_time++;
        if (pa->processes[select].time_remaining == 0)
        {
            pa->processes[select].time_finish = curren_time;
            int2time(pa->processes[select].time_finish, pa->processes[select].finish); // 转成字符串
            pa->processes[select].tar = pa->processes[select].time_finish - pa->processes[select].time_arrival;
            pa->processes[select].tarw = (float)pa->processes[select].tar / pa->processes[select].time_run;
        }
    }
}

// 求平均周转时间、平均带权周转时间
void compute_average(process_array *pa)
{
    float sum_tar = 0, sum_tarw = 0;
    for (int i = 0; i < pa->len; i++)
    {
        sum_tar += pa->processes[i].tar;
        sum_tarw += pa->processes[i].tarw;
    }
    pa->ava_tar = sum_tar / pa->len;
    pa->ava_tarw = sum_tarw / pa->len;
}

// 从文件中读取初始数据
process_array *read_process_array_from_file(const char *path)
{
    FILE *fp = fopen(path, "r");
    if (fp == NULL)
    {
        return NULL;
    }

    // 申请一个进程队列空间
    process_array *pa = calloc(sizeof(process_array), 1);
    char line[256];
    while (fgets(line, sizeof(line), fp) != NULL)
    {
        pa->len += 1;
        process *tmp = calloc(sizeof(process), pa->len);
        memcpy(tmp, pa->processes, sizeof(*tmp) * (pa->len - 1));
        free(pa->processes);
        pa->processes = tmp;
        // 分别读入进程名、进程到达时间、进程运行时间
        if (sscanf(line, "%s %s %f", pa->processes[pa->len - 1].pname, pa->processes[pa->len - 1].arrival, &pa->processes[pa->len - 1].time_run) != 3)
        {
            free(tmp);
        }
    }

    fp = NULL;

    return pa;
}

int run()
{
    process_array *pa = read_process_array_from_file("data.txt");
    if (pa == NULL)
    {
        printf("%s\n", strerror(errno));
        return 1;
    }
    // 初始化各参数
    process_init(pa);
    // 根据到达时间排序
    sort_by_arrive_time(pa);
    int algorithm;
    printf("====================================================\
==================================================================\n\
==============================================数据已载入,请选择算法===\
===============================================\n\
\t1.先来先服务调度算法, 2.短作业优先调度算法, 3.最高响应比调度算法, 4.最短剩余时间调度算法, 5.退出程序\n");
    printf("====================================================\
==================================================================\n");
    scanf("%d", &algorithm);
    system("cls");

    printf("====================================================\
==================================================================\n");

    switch (algorithm)
    {
    case 1:
        printf("\t\t\t\t\t先来先服务调度算法\n");
        first_come_first_service(pa);
        break;
    case 2:
        printf("\t\t\t\t\t短作业优先调度算法\n");
        shortest_job_first(pa);
        break;
    case 3:
        printf("\t\t\t\t\t最高响应比调度算法\n");
        printf("\t请输入开始时间:");
        char* start[10];
        scanf("%s", &start);
        printf("\n");
        highest_response_ratio_priority(pa, start);
        break;
    case 4:
        printf("\t\t\t\t\t最短剩余时间调度算法\n");
        shortest_residue_time_fist(pa);
        break;
    case 5:
        return 1;
        break;
    default:
        printf("您的选择不在范围内,请从以下算法中选择:\n");
        // 释放内存
        free_process_array(&pa);
        return 0;
        break;
    }
    compute_average(pa);
    print_process_array(pa);
    // 释放内存
    free_process_array(&pa);
    return 0;
}

int main()
{
    while (1)
    {
        if(run() == 1)
            break;
    }
    return 0;
}

输出
选择算法界面

======================================================================================================================
==============================================数据已载入,请选择算法==================================================
        1.先来先服务调度算法, 2.短作业优先调度算法, 3.最高响应比调度算法, 4.最短剩余时间调度算法, 5.退出程序
======================================================================================================================

结果显示界面

======================================================================================================================
                                        最短剩余时间调度算法
======================================================================================================================
        进程名  到达时间        运行时间        开始时间        完成时间        周转时间        带权周转时间
----------------------------------------------------------------------------------------------------------------------
         J1      8:00            30.00           08:00           08:35           35.00             1.17
----------------------------------------------------------------------------------------------------------------------
         J2      8:20            5.00            08:20           08:25           5.00              1.00
----------------------------------------------------------------------------------------------------------------------
         J3      8:30            15.00           08:35           08:50           20.00             1.33
----------------------------------------------------------------------------------------------------------------------
        平均周转时间:                                                           20.00
----------------------------------------------------------------------------------------------------------------------
        平均带权周转时间:                                                                         1.17
======================================================================================================================
======================================================================================================================
==============================================数据已载入,请选择算法==================================================
        1.先来先服务调度算法, 2.短作业优先调度算法, 3.最高响应比调度算法, 4.最短剩余时间调度算法, 5.退出程序
======================================================================================================================

19 guan老师课程学生



这篇关于操作系统-作业调度算法设计的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程