【操作系统实验6】CPU调度程序模拟实现

这篇具有很好参考价值的文章主要介绍了【操作系统实验6】CPU调度程序模拟实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、实验目标

加深对操作系统CPU调度以及调度算法的理解

二、实验内容

1.思路

1)

  • 单处理器环境下,针对最短作业优先算法(SJF)和优先级调度算法(Priority),分别模拟实现抢占调度和非抢占调度的调度程序
  • 设计使用三个队列,分别为就绪队列(readyQueue)、运行队列(runningQueue)、等待队列(waitingQueue)
  • 进程状态三种,分别为就绪状态:0、运行状态:1、等待状态:2
  • 输入:task.txt 文件和指定调度算法
    • task.txt 文件为需要调度的进程集
    • 非抢占 SJF: sjf
    • 抢占 SJF: psjf
    • 非抢占 Priority: pprio
    • 抢占 Priority: prio
  • 输出:按照所指定的调度算法,显示调度结果
    • 比如:P2:2、P1:2、P3:1、P4:5

2)1数据结构
本次实验的数据结构参考了 pintos 中的线程调度:使⽤ PCB 结构体表示进程、使⽤双向链表管理进程。
PCB 结构体定义如下:

 typedef struct PCB {
 int pid; // pid
 int time_release; // release time
 int time_cpu; // total CPU execution time
 int time_remaining; // remaining CPU execution tine
 int priority; // priority
 enum ProcessState state; // process state

 struct PCB* prev; // previous process pointer
 struct PCB* next; // next process pointer
 } PCB;

为何适配该实验,双向链表上实现了⼀些常⽤的操作函数。由于本实验中需要通过进程的优先级和剩余 CPU 时间进⾏排序,所以还参考 pintos 实现了有序插⼊的操作。

1 /* Operations on list. */
2 List* list_create();
3 void list_delete(List* list);
4
5 /* Iteration operations */
6 ListElem* list_begin(List* list);
7 ListElem* list_next(ListElem* elem);
8 ListElem* list_end(List* list);
9
10 /* Removal operations. */
11 ListElem* list_remove(ListElem* elem);
12 ListElem* list_pop_front(List* list);
13
14 /* Insertion operations. */
15 void list_insert(ListElem* before, ListElem* elem);
16 void list_insert_ordered(List* list, ListElem* elem,
17 list_less_func* less_func);
18 void list_push_back(List* list, ListElem* elem);
19
20 /* Get list properties. */
21 size_t list_size(List* list);
22 int list_empty(List* list);

3)算法
本实验中⾸先计算出运⾏完所有进程所需要的 CPU 区间⻓度 T,然后使⽤ for 循环,令 i 从0 遍历到 T-1 来模拟实际 CPU 调度中定时器产⽣的时间⽚到时中断:i 每增加 1,代表 CPU执⾏了⼀个时间⽚,此时应该重新进⾏调度。
下⾯以最短作业优先调度为例概述调度算法,优先级调度算法与此类似,代码也极其相似。
在⼀个新的时间⽚到来时,将 CPU 分配给哪⼀个进程有两个需要考虑的因素 — 进程的到达时间与进程的剩余 CPU 区间。假如当前到来的是第 i 个时间⽚,只有到达时间(release time)⼩于等于 i 的进程才有机会被分配 CPU;随后我们需要在些进程中选择剩余 CPU 区间最短的作为执⾏进程。
由此得到的结论就是,我们需要先对进程的到达时间作为第⼀优先级、剩余 CPU 区间作为第⼆优先级进⾏排序。本实验采⽤的⽅法是在进程创建的时候就将其按照上述两个优先级插⼊到ready queue 中,使 ready queue 成为⼀个优先级队列。在⾮抢占式调度中,⼀个进程执⾏完⽆需执⾏其他操作;⽽在抢占式调度中,⼀个进程在该时间⽚内执⾏完后,需要判断其剩余 CPU 区间是否为 0,如果为 0,则需要将其重新按照上述两个优先级插⼊到队列中。
同理,如果采⽤优先级调度,上述的排列规则变为到达时间使第⼀优先级,⽽进程优先级是第⼆优先级。

2.代码

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

enum ProcessState {
    PROCESS_READY,
    PROCESS_RUNNING
};

typedef struct PCB {
    int pid;                  
    int time_release;         
    int time_cpu;             
    int time_remaining;       
    int priority;             
    enum ProcessState state;  

    struct PCB* prev;
    struct PCB* next;
} PCB;

typedef PCB ListElem;

typedef struct List {
    ListElem head;
    ListElem tail;
} List;

/* Compares the value of two list elements A and B, given
   auxiliary data AUX.  Returns true if A is less than B, or
   false if A is greater than or equal to B. */
typedef int list_less_func(const ListElem* a,
                           const ListElem* b);

PCB* process_running;
List* ready_queue;
List* terminated_list;

char file_name[] = "sched.txt";
FILE* file;

/* Operations on list. */
List* list_create();
void list_delete(List* list);

ListElem* list_begin(List* list);
ListElem* list_next(ListElem* elem);
ListElem* list_end(List* list);

ListElem* list_remove(ListElem* elem);
ListElem* list_pop_front(List* list);

void list_insert(ListElem* before, ListElem* elem);
void list_insert_ordered(List* list, ListElem* elem,
                         list_less_func* less_func);
void list_push_back(List* list, ListElem* elem);

size_t list_size(List* list);
int list_empty(List* list);

/* Operations on process. */
PCB* process_create(int pid, int time_release, int priority, int time_exec);

void process_sched_sjf(int cpu_time);
void process_sched_psjf(int cpu_time);
int process_cmp_sjf(const ListElem* a, const ListElem* b);

void process_sched_prio(int cpu_time);
void process_sched_pprio(int cpu_time);
int process_cmp_prio(const ListElem* a, const ListElem* b);

void process_print(int cnt);

void print_header(int cpu_time);

int get_total_cpu_time();

PCB* load_process_from_file();

int main() {
    int cpu_time, mode;
    PCB* process;
    file = fopen(file_name, "r");

    ready_queue = list_create();
    terminated_list = list_create();

    printf("Input schedule mode.\n1: sjf, 2: psjf, 3: prio, 4:pprio.\n");
    scanf("%d", &mode);

    switch (mode) {
    case 1: {
        while ((process = load_process_from_file()) != NULL) {
            list_insert_ordered(ready_queue, process, process_cmp_sjf);
        }
        cpu_time = get_total_cpu_time();
        printf("\n\n");
        print_header(cpu_time);
        process_sched_sjf(cpu_time);
        printf("\n\n");
    } break;
    case 2: {
        while ((process = load_process_from_file()) != NULL) {
            list_insert_ordered(ready_queue, process, process_cmp_sjf);
        }
        cpu_time = get_total_cpu_time();
        printf("\n\n");
        print_header(cpu_time);
        process_sched_psjf(cpu_time);
        printf("\n\n");
    } break;
    case 3: {
        while ((process = load_process_from_file()) != NULL) {
            list_insert_ordered(ready_queue, process, process_cmp_prio);
        }
        cpu_time = get_total_cpu_time();
        printf("\n\n");
        print_header(cpu_time);
        process_sched_prio(cpu_time);
        printf("\n\n");
    } break;
    case 4: {
        while ((process = load_process_from_file()) != NULL) {
            list_insert_ordered(ready_queue, process, process_cmp_prio);
        }
        cpu_time = get_total_cpu_time();
        printf("\n\n");
        print_header(cpu_time);
        process_sched_pprio(cpu_time);
        printf("\n\n");
    } break;

    default:
        break;
    }

    list_delete(ready_queue);
    list_delete(terminated_list);

    return 0;
}

List* list_create() {
    List* list = (List*)malloc(sizeof(List));
    if (!list) {
        printf("list_create(): malloc failed.\n");
        exit(1);
    }

    list->head.prev = NULL;
    list->head.next = &list->tail;
    list->tail.prev = &list->head;
    list->tail.next = NULL;

    return list;
}

void list_delete(List* list) {
    ListElem* elem;
    while (!list_empty(list)) {
        elem = list_pop_front(list);
        free(elem);
    }
    free(list);
}

ListElem* list_begin(List* list) {
    return list->head.next;
}

ListElem* list_next(ListElem* elem) {
    return elem->next;
}

ListElem* list_end(List* list) {
    return &list->tail;
}

ListElem* list_remove(ListElem* elem) {
    elem->prev->next = elem->next;
    elem->next->prev = elem->prev;

    return elem->next;
}

ListElem* list_pop_front(List* list) {
    ListElem* front = list_begin(list);
    list_remove(front);

    return front;
}

void list_insert(ListElem* before, ListElem* elem) {
    elem->prev = before->prev;
    elem->next = before;
    before->prev->next = elem;
    before->prev = elem;
}

void list_push_back(List* list, ListElem* elem) {
    list_insert(list_end(list), elem);
}

void list_insert_ordered(List* list, ListElem* elem,
                         list_less_func* less_func) {
    ListElem* e;
    for (e = list_begin(list); e != list_end(list); e = list_next(e))
        if (less_func(elem, e))
            break;
    list_insert(e, elem);
}

size_t list_size(List* list) {
    ListElem* elem;
    size_t cnt = 0;
    for (elem = list_begin(list); elem != list_end(list); elem = list_next(elem))
        cnt++;

    return cnt;
}

int list_empty(List* list) {
    return (list_begin(list) == list_end(list));
}

PCB* process_create(int pid, int time_release, int priority, int time_exec) {
    PCB* process = (PCB*)malloc(sizeof(PCB));
    if (!process) {
        printf("process_create(): malloc failed.\n");
        exit(1);
    }

    process->pid = pid;
    process->time_release = time_release;
    process->time_cpu = time_exec;
    process->time_remaining = time_exec;
    process->priority = priority;
    process->state = PROCESS_READY;

    return process;
}

void process_sched_sjf(int cpu_time) {
    int i = 0;
    PCB* next;

    for (; i < cpu_time; i++) {
        process_running = list_begin(ready_queue);
        for (next = list_next(process_running); next != list_end(ready_queue); next = list_next(next)) {
            if (next->time_release > i)
                break;
            if (next->time_remaining < process_running->time_remaining)
                process_running = next;
        }
        i += process_running->time_remaining - 1;
        list_remove(process_running);
        list_push_back(terminated_list, process_running);
        process_print(process_running->time_remaining);
    }
}

void process_sched_psjf(int cpu_time) {
    int i = 0;
    PCB* next;

    for (; i < cpu_time; ++i) {
        process_running = list_begin(ready_queue);
        for (next = list_next(process_running); next != list_end(ready_queue); next = list_next(next)) {
            if (next->time_release > i)
                break;
            if (next->time_remaining < process_running->time_remaining)
                process_running = next;
        }
        process_running->time_remaining--;
        process_print(1);
        if (process_running->time_remaining > 0) {
            list_remove(process_running);
            list_insert_ordered(ready_queue, process_running, process_cmp_sjf);
        } else {
            list_remove(process_running);
            list_push_back(terminated_list, process_running);
        }
    }
}

int process_cmp_sjf(const ListElem* a, const ListElem* b) {
    if (a->time_release != b->time_release)
        return (a->time_release < b->time_release);
    else
        return (a->time_remaining < b->time_remaining);
}

void process_sched_prio(int cpu_time) {
    int i = 0;
    PCB* next;

    for (; i < cpu_time; i++) {
        process_running = list_begin(ready_queue);
        for (next = list_next(process_running); next != list_end(ready_queue); next = list_next(next)) {
            if (next->time_release > i)
                break;
            if (next->priority < process_running->priority)
                process_running = next;
        }
        i += process_running->time_remaining - 1;
        list_remove(process_running);
        list_push_back(terminated_list, process_running);
        process_print(process_running->time_remaining);
    }
}

void process_sched_pprio(int cpu_time) {
    int i = 0;
    PCB* next;

    for (; i < cpu_time; ++i) {
        process_running = list_begin(ready_queue);
        for (next = list_next(process_running); next != list_end(ready_queue); next = list_next(next)) {
            if (next->time_release > i)
                break;
            if (next->priority < process_running->priority)
                process_running = next;
        }
        process_running->time_remaining--;
        process_print(1);
        if (process_running->time_remaining > 0) {
            list_remove(process_running);
            list_insert_ordered(ready_queue, process_running, process_cmp_prio);
        } else {
            list_remove(process_running);
            list_push_back(terminated_list, process_running);
        }
    }
}

int process_cmp_prio(const ListElem* a, const ListElem* b) {
    if (a->time_release != b->time_release)
        return (a->time_release < b->time_release);
    else
        return (a->priority < b->priority);
}

void process_print(int cnt) {
    int i = 0;
    for (; i < cnt; ++i)
        printf("  P%d  ", process_running->pid);
}

void print_header(int cpu_time) {
    int i = 0;
    for (; i < cpu_time; ++i)
        printf("|_____");
    printf("|\n");

    for (i = 0; i <= cpu_time; ++i)
        printf("%-6d", i);
    printf("\n");
}

int get_total_cpu_time() {
    int total_cpu_time = 0;
    ListElem* elem = list_begin(ready_queue);
    for (; elem != list_end(ready_queue); elem = list_next(elem))
        total_cpu_time += elem->time_remaining;

    return total_cpu_time;
}

PCB* load_process_from_file() {
    int pid, time_release, time_cpu, priority;
    PCB* process = NULL;

    if (fscanf(file, "%d%d%d%d", &pid, &time_release, &priority, &time_cpu) != EOF) {
        process = process_create(pid, time_release, priority, time_cpu);
    }

    return process;
}

3.过程及运行结果展示

从文本文件中输入信息(格式:进程ID, 到达时间, 优先级, 运行时间)
【操作系统实验6】CPU调度程序模拟实现

非抢占式最短作业优先调度
【操作系统实验6】CPU调度程序模拟实现

抢占式最短作业优先调度
【操作系统实验6】CPU调度程序模拟实现

非抢占式优先级调度
【操作系统实验6】CPU调度程序模拟实现

抢占式优先级调度
【操作系统实验6】CPU调度程序模拟实现

三、实验结论

通过本实验对于调度算法有了更加深刻的理解。
-最短作业优先调度:
抢占式:当新进来的进程的CPU区间比当前执行的进程所剩的CPU区间短,则抢占。
非抢占:为下一个最短优先,因为在就绪队列中选择最短CPU区间的进程放在队头。
-优先级调度算法:SJF是特殊的优先级调度算法,以CPU区间长度的倒数为优先级。
抢占式为如果进来的进程优先级高于运行的进程,则替换。
非抢占式只是在就绪队列中按优先级排队。
缺点:无线阻塞或饥饿。前者为一个优先级高且运行时间长的进程一直阻塞,后者为优先级低的进程永远都得不到执行。文章来源地址https://www.toymoban.com/news/detail-456530.html

到了这里,关于【操作系统实验6】CPU调度程序模拟实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 操作系统进程调度算法(c语言模拟实现)

            前言: 本文旨在分享如何使用c语言对操作系统中的部分进程调度算法进行模拟实现,以及算法描述的讲解, 完整代码放在文章末尾,欢迎大家自行拷贝调用 目录 常见的调度算法 数据结构 先来先服务调度算法 算法模拟思路: 算法模拟:  最短作业优先调度算法

    2024年02月06日
    浏览(54)
  • 操作系统进程调度算法的模拟实现(c语言版本)

            前言: 本文旨在分享如何使用c语言对操作系统中的部分进程调度算法进行模拟实现,以及算法描述的讲解, 完整代码放在文章末尾,欢迎大家自行拷贝调用 目录 常见的调度算法 数据结构 先来先服务调度算法 算法模拟思路: 算法模拟:  最短作业优先调度算法

    2024年02月06日
    浏览(55)
  • 先来先服务调度算法(C语言代码实现) 大三操作系统实验

    实验原理: 先来先服务(First Come First Served,FCFS),是一种简单的调度算法,它既适用于作业调度,也适用于进程调度。先来先服务算法是按照作业或进程的到达先后次序来进行调度。当作业调度中采用该算法时,每次调度都是从后备队列中选择一个最先进入该队列中作业,将

    2024年04月16日
    浏览(33)
  • 【操作系统原理实验】银行家算法模拟实现

    选择一种高级语言如C/C++等,编写一个银行家算法的模拟实现程序。1) 设计相关数据结构;2) 实现系统资源状态查看、资源请求的输入等模块;3) 实现资源的预分配及确认或回滚程序;4) 实现系统状态安全检查程序;5) 组装各模块成一个完整的模拟系统。 (1)设计思想: 1、

    2024年02月01日
    浏览(44)
  • 操作系统课程设计进程调度模拟

    程序下载链接:https://download.csdn.net/download/m0_56241309/86945709 进程调度模拟 摘要 :进程调度是操作系统中必不可少的一种调度,在3中OS中都无一例外地配置了进程调度。此外,它也是对系统性能影响最大的一种处理机调度,在操作系统中具有十分重要的地位。本次模拟,旨在全

    2024年02月08日
    浏览(41)
  • 操作系统实验(进程调度)

      1.1理解有关进程控制块、进程队列的概念。   1.2掌握进程优先权调度算法和时间片轮转调度算法的处理逻辑。   2.1设计进程控制块PCB的结构,分别适用于优先权调度算法和时间片轮转调度算法。   2.2建立进程就绪队列。   2.3编制两种进程调度算法:优先权调度

    2024年02月06日
    浏览(46)
  • 操作系统-进程调度实验报告

    1.实现四种不同及进程调度算法: 先来先服务、时间片轮转调、优先级调度以及短作业优先调度算法。 2.通过实验理解有关进程控制块,进程队列等的概念。 1.运行素材中的代码,观察其执行结果是否正确?各个调度算法的功能是否完善?如果没有,则完善。 2. 按照下表

    2024年02月06日
    浏览(43)
  • 计算机操作系统实验:进程调度实验

    前言 二、实验目的 三、实验要求 四、实验原理 五、实验过程 六、代码详解 总结 计算机操作系统是管理计算机硬件和软件资源的核心软件,它负责为用户提供一个友好、高效、安全的使用环境。进程调度是操作系统的一个重要功能,它决定了进程在处理器上的执行顺序和时

    2024年02月07日
    浏览(57)
  • 磁盘调度算法(操作系统实验 C++)

    通过这次实验,加深对磁盘调度算法的理解,进一步掌握先来先服务FCFS、最短寻道时间优先SSTF、SCAN和循环SCAN算法的实现方法。 问题描述: 设计程序模拟先来先服务FCFS、最短寻道时间优先SSTF、SCAN和循环SCAN算法的工作过程。假设有n个磁道号所组成的磁道访问序列,给定开

    2024年02月07日
    浏览(55)
  • 操作系统实验—进程调度算法(java)

    目录 文章目录 前言 一、实验原理 二、实验步骤 1.创建PCB类 2.创建创建类 3.设计主窗口类 4.调度界面函数 5.算法类及其调度算法通用函数 6.进程调度算法函数 总结 操作系统实验1:进程调度算法,步骤3、4在一个类中,步骤5、6在一个类中。 (1)先到先服务调度算法:按照进程提

    2024年02月04日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包