C++ 抢占时优先级进程调度

OCaml智者
• 阅读 2226
  • 先来先服务
  • 短进程优先算法
  • 优先级调度(抢占)
  • 优先级调度
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;

struct PCB
{
    int id;                          // 进程id
    double turnaround_time;          // 周转时间
    double weighted_turnaround_time; // 带权周转时间
    double wait_time;                // 等待时间
    double start_time;               // 开始时间
    double coming_time;              // 到达时间
    double service_time;             // 运行时间
    double finish_time;              // 完成时间
    int youxianji;                   // 优先级
    double run_time;                 // 已运行时间
};

int n;                    // 进程个数
vector<PCB> process_list; // 输入的进程序列
vector<PCB> res;          // 待输出的结果队列

void input_process_count()
{
    printf("请输入进程数量:");
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
    {
        PCB pcb; // pcb初始化
        pcb.id = i + 1;
        pcb.run_time = 0;            // 初始时已运行时间为零
        pcb.start_time = -1;         // 为判断是否第一次到达
        process_list.push_back(pcb); // 加入已初始化好的pcb
    }
}

void input_youxianshu() // 输入优先级
{
    for (int i = 0; i < n; i++)
    {
        printf("请输入进程%d的优先级:", process_list[i].id);
        scanf("%d", &process_list[i].youxianji);
    }
}

void input_coming_time() // 输入到达时间
{
    for (int i = 0; i < n; i++)
    {
        printf("请输入进程%d的到达时间:", process_list[i].id);
        scanf("%lf", &process_list[i].coming_time);
    }
}

void input_serve_time() // 输入需要服务时间
{
    for (int i = 0; i < n; i++)
    {
        printf("请输入进程%d所需时间", process_list[i].id);
        scanf("%lf", &process_list[i].service_time);
    }
}

int choose_method() // 输入选择的算法
{
    int select = 0;
    cout << "*****************************************\n";
    cout << "1 \t    先来先服务算法            *******\n";
    cout << "2 \t    短进程优先算法            *******\n";
    cout << "3 \t    优先级调度(抢占)          *******\n";
    cout << "4 \t    优先级调度(非抢占)        *******\n";

    cout << "请选择: ";
    cin >> select;
    return select;
}

int cmpByComingTime(PCB a, PCB b) // 按照到达时间从小到大排序
{
    return a.coming_time < b.coming_time;
}

int cmpByServiceTime(PCB a, PCB b) // 按照需要服务时间从大到小排序
{
    return a.service_time > b.service_time;
}

void FCFS()
{
    sort(process_list.begin(), process_list.end(), cmpByComingTime); // 先按照到达时间排序
    double time = process_list[0].coming_time;                       // 初始化时间
    for (int i = 0; i < n; i++)
    {
        PCB pcb = process_list[i]; // 因为已经按照时间排序,所以当前为待运行的进程
        // 更新当前进程的信息
        pcb.start_time = time;
        pcb.wait_time = time - pcb.coming_time;
        pcb.finish_time = time + pcb.service_time;
        pcb.turnaround_time = pcb.finish_time - pcb.coming_time;
        pcb.weighted_turnaround_time = (pcb.turnaround_time) / pcb.service_time;
        time = pcb.finish_time; // 以当前进程的时间更新time
        process_list[i] = pcb;
        res.push_back(pcb); // 加入结果队列
    }
}

void SJF()
{
    int top = 0;
    vector<PCB> short_jobs;                                          // 定义短进程队列 其中数据由大到小
    sort(process_list.begin(), process_list.end(), cmpByComingTime); // 按照到达时间初始化
    double time = process_list[0].coming_time;                       // 初始化时间
    while (top < n || !short_jobs.empty())                           // 如果两个对列里仍然存在元素
    {
        if (short_jobs.empty()) // 如果队列未空,则加入当前已经到达的进程
            short_jobs.push_back(process_list[top++]);

        PCB pcb = short_jobs[int(short_jobs.size() - 1)]; // 取出时间最短的
        if (pcb.start_time == -1)
            pcb.start_time = time;
        // 更新pcb的时间
        pcb.wait_time = time - pcb.coming_time;
        pcb.finish_time = time + pcb.service_time;
        pcb.turnaround_time = pcb.finish_time - pcb.coming_time;
        pcb.weighted_turnaround_time = (pcb.turnaround_time) / pcb.service_time;
        time = pcb.finish_time;

        // 加入到运行结束队列
        res.push_back(pcb);
        short_jobs.pop_back();
        // 如果在上个进程运行期间有进程到达则加入short_jobs队列
        for (; top < n && process_list[top].coming_time < time; top++)
        {
            short_jobs.push_back(process_list[top]);
        }
        // 因为有新的进程加入,所以对short_jobs进行排序
        sort(short_jobs.begin(), short_jobs.end(), cmpByComingTime);
    }
}

bool cmpByPriority(PCB a, PCB b) // 按照优先级排序
{
    if (a.youxianji == b.youxianji)
        return a.coming_time > b.coming_time;
    return a.youxianji < b.youxianji;
}

void PriorityNo() // 非抢占优先级调度
{
    int top = 0; // 定义头指针
    vector<PCB> priority_higher;
    sort(process_list.begin(), process_list.end(), cmpByComingTime);
    double time = process_list[0].coming_time;
    while (top < n || !priority_higher.empty()) // 如果仍有进程未运行结束
    {
        if (priority_higher.empty()) // 为空则加入新的进程
            priority_higher.push_back(process_list[top++]);

        PCB pcb = priority_higher[int(priority_higher.size() - 1)]; // 取出要运行的进程
        if (pcb.start_time == -1)                                   //如果是第一次抵达则更新时间
            pcb.start_time = time;

        // 更新pcb
        pcb.wait_time = time - pcb.coming_time;
        pcb.finish_time = time + pcb.service_time;
        pcb.turnaround_time = pcb.finish_time - pcb.coming_time;
        pcb.weighted_turnaround_time = (pcb.turnaround_time) / pcb.service_time;
        time = pcb.finish_time;

        res.push_back(pcb);         // 运行结束则加入res
        priority_higher.pop_back(); // 并删除已运行结束的进程

        for (; top < n && process_list[top].coming_time < time; top++)
        { // 加入在此期间到达的进程
            priority_higher.push_back(process_list[top]);
        }
        // 因为有新进程加入,进行排序
        sort(priority_higher.begin(), priority_higher.end(), cmpByPriority);
    }
}

void PriorityYes()
{
    int top = 0;
    vector<PCB> priority_higher;
    sort(process_list.begin(), process_list.end(), cmpByComingTime);
    double time = process_list[0].coming_time;  // 初始化时间
    while (top < n || !priority_higher.empty()) // 如果仍有进程未结束
    {
        if (priority_higher.empty()) // 如果为空,则加入新的进程
            priority_higher.push_back(process_list[top++]);

        PCB pcb = priority_higher[int(priority_higher.size() - 1)]; // 取出优先级最高的进程运行
        if (pcb.start_time == -1)                                   // 如果是第一次到达,则记录开始时间
        {
            pcb.start_time = time;
            pcb.wait_time = pcb.start_time - pcb.coming_time;
        }
        if (top < n && process_list[top].coming_time <= time + pcb.service_time - pcb.run_time) // 如果仍有未加入的进程, 并且在运行期间有新的进程到达
        {
            pcb.run_time += process_list[top].coming_time - time;                // 则先运行距离下个进程到达的时间
            time += process_list[top].coming_time - time;                        // 并更新时间
            priority_higher[priority_higher.size() - 1] = pcb;                   // 更新队列
            priority_higher.push_back(process_list[top++]);                      // 把下一个进程加入
            sort(priority_higher.begin(), priority_higher.end(), cmpByPriority); // 并进行排序
            if (pcb.run_time == pcb.service_time)                                // 如果当前进程的运行时间已经够了,则更新pcb信息,并删除进程
            {
                pcb.finish_time = time;
                pcb.turnaround_time = pcb.finish_time - pcb.coming_time;
                pcb.weighted_turnaround_time = (pcb.turnaround_time) / pcb.service_time;
                res.push_back(pcb);
                priority_higher.pop_back();
            }
        }
        else // 如果没有新的进程到达, 则将当前进程运行完毕
        {
            pcb.finish_time = time + pcb.service_time - pcb.run_time;
            pcb.turnaround_time = pcb.finish_time - pcb.coming_time;
            pcb.weighted_turnaround_time = (pcb.turnaround_time) / pcb.service_time;
            time = time + pcb.service_time - pcb.run_time;
            res.push_back(pcb); // 运行完毕则加入res
            priority_higher.pop_back();
        }
    }
}

bool cmpById(PCB a, PCB b)
{
    return a.id < b.id;
}

void print_schedulInfo()
{
    printf("进程编号\t提交时间\t运行时间\t开始时间\t等待时间\t完成时间\t周转时间\t带权周转时间\n");
    // cout << res.size() << endl;
    sort(res.begin(), res.end(), cmpById); // 按照ID排序
    double start = 0x3f3f3f3f3f, end = 0;
    double allTT = 0, allWTT = 0, runTime = 0;
    for (int i = 0; i < n; i++)
    {
        PCB pcb = res[i];
        start = min(start, pcb.start_time);     // 得到开始时间
        end = max(end, pcb.finish_time);        // 所有进程结束时间
        allTT += pcb.turnaround_time;           // 总的周转时间
        allWTT += pcb.weighted_turnaround_time; // 总的带权周转时间
        runTime += pcb.service_time;            // 总的服务时间
        printf("%8d\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\n", pcb.id, pcb.coming_time, pcb.service_time, pcb.start_time, pcb.wait_time, pcb.finish_time, pcb.turnaround_time, pcb.weighted_turnaround_time);
    }

    printf("平均周转时间%.2f\t平均带权周转时间%.2f\tCPU利用率%.2f\t系统吞吐量%.2f\n", allTT / n, allWTT / n, (runTime) / (end - start), (n) / (end - start));
}

int main()
{
    // 4 1 1 1 1 9 8 8.4 8.8 0.2 2 1 0.5
    // 4 2 4 3 1 10 20 30 50 20 30 25 20
    // 4 1 2 3 2 0 2 4 5 7 4 1 4
    input_process_count();        // 输出进程数量
    input_youxianshu();           // 输入优先级数
    input_coming_time();          // 输入到达时间
    input_serve_time();           // 输入需要服务时间
    int choose = choose_method(); // 得到用户选择的数
    // printf("%d\n", choose);
    switch (choose)
    {
    case 1:
        FCFS(); // 先来先服务
        break;
    case 2:
        SJF(); // 短作业优先
        break;
    case 3:
        PriorityYes(); // 优先级抢占式
        break;
    default:
        PriorityNo(); // 优先级非抢占式
        break;
    }
    print_schedulInfo(); // 打印结果
    return 0;
}
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
6个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
3年前
java多线程小结,及解决应用挂死的问题
这两天为了定位JBOSS老是挂死的问题,学习了一下JAVA多线程方面的知识,在此总结一下1、在Java程序中,JVM负责线程的调度。线程调度是指按照特定的机制为多个线程分配CPU的使用权。调度的模式有两种:分时调度和抢占式调度。分时调度是所有线程轮流获得CPU使用权,并平均分配每个线程占用CPU的时间;抢占式调度是根据线程的优先级别来获
Wesley13 Wesley13
3年前
java线程优先级
java中的线程优先级的范围是1~10,默认的优先级是5。10最高。MIN\_PRIORITY 1MAX\_PRIORITY10NORM\_PRIORITY5优先级高的获得cpu的几率更大些,不是优先级高的就先执行完,线程优先级随机特性在java中,线程的优先级具有继承性,例如A线程启动B线程,则A和B的优先级是一样的线程创建
Wesley13 Wesley13
3年前
SCHED_FIFO与SCHED_OTHER调度机制
疑问两个线程分别有不同的调度策略,一个SCHED\_FIFO,一个SCHED\_OTHER,按照之前的理解,SCHED\_FIFO实时线程一定会占用CPU一直运行,导致SCHED\_OTHER的普通线程得不到CPU,事实是这样么?验证写了一小段代码,一个是验证SCHED\_FIFO的高优先级线程会不会抢占低优先级的线程,在不主动放弃的
Wesley13 Wesley13
3年前
java实现任务调度
最近的一个小项目是做一个简单的数据仓库,需要将其他数据库的数据抽取出来,并通过而出抽取成页面需要的数据,以空间换时间的方式,让后端报表查询更快。因为在抽取的过程中,有一定的先后顺序,需要做一个任务调度器,某一优先级的会先执行,然后会进入下一个优先级的队列任务中。先定义了一个Map的集合,key是优先级,value是任务的集合,某一个优先级内的任务是并发执
Wesley13 Wesley13
3年前
Java的编程逻辑
1、run()和start()的区别2、线程的基本属性和方法1.id:一个递增的整数,每创建一个线程就加一2.name3.优先级:从1到10,默认为5,会映射到系统中的优先级。数字越大,要优先级越高4.状态: NEW:还没调用start RUNABLE:正在执行run或者正在等待cup分配
Stella981 Stella981
3年前
Nginx 常见问题整理
Nginx常见问题整理1、Nginx常见问题1、相同server\_name多个虚拟主机优先级访问根据文件名顺序优先读取。使用ip访问的时候,也是根据文件名顺序优先读取。2、location匹配优先级进行普通字符精
Wesley13 Wesley13
3年前
CPU调度
1.CPU调度程序  每当CPU空闲时,OS必须从就绪队列选择一个进程来执行。进程选择由短期调度程序或CPU调度程序执行。调度程序从内存中选择一个能执行的进程,并为之分配CPU。2.抢占:可以选择       (1)当一个进程从运行状态切换到就绪状态;(eg:当出现中断时)       (2)当一个进
Stella981 Stella981
3年前
CSS前端经典面试题及解析——小白入门必备
1.CSS选择器的优先级是如何计算的?浏览器通过优先级规则,判断元素展示哪些样式。优先级通过4个维度指标确定,我们假定以a、b、c、d命名,分别代表以下含义:1.a表示是否使用内联样式(inlinestyle)。如果使用,a为1,否则为0。2.b表示ID选择器的数量。3.c表示类选择器、属性