zoukankan      html  css  js  c++  java
  • 五种进程调度的算法实现(二)

    程序设计

    一、数据结构

    1.1 事件类型

    由于要求是基于事件的进程调度,所以必须创建一个存放事件的队列。

    enum EventType{ ARRIVALEVENT, FINISHEVENT, TIMEREVENT };    //事件类型

    1.2 任务结构(每一项数据都是输入):

    struct Job
    {
        char name[50];       //作业名
        int arriveTime;      //作业到达时间
        int needTime;        //作业所需运行时间
        int priority;        //作业优先级,数字越小,优先级越高
    };

    1.3 事件链表结点:

    struct Event
    {
        EventType type;            //事件类型
        int jobBeginTime;          //作业开始时间
        bool isFirstExe;           //判断是否第一次执行,用于记录作业开始时间
        int happenTime;            //发生时刻
        int remainTime;            //剩余运行时间
        double hrr;                //最高响应比
        Job job;                   //作业    
        Event *next;               //事件指针
    };

    因为事件为队列存储,因而需要动态增删,所以较佳的数据结构是链表。因为是链表,所以要定义一套操作链表的函数。

    二、程序流程图

    2.1 非抢占式调度

    clip_image002

    2.2 抢占式调度

    clip_image002[5]

    2.3 轮转调度

    clip_image002[7]

    三、过程定义

    3.1 事件队列相关函数

    /* 作业复制函数 */
    void CopyJob( Job *dest, const Job *sour );
    /* 事件队列创建函数
     * 包含头节点
     * 返回头指针 */
    Event *CreateEventQueue();
    /* 抓取头结点之外的第一个事件
     * 作为返回值返回 */
    Event *FetchFirstEvent( Event *head );
    /* 如果值相同,时间将插在前方 */
    void InsertFinishEvent( Event *head, Event *e );
    /* 插入到队尾 */
    void InsertTail( Event *head, Event *e );
    /* 按作业名称删除第一个匹配项,
     * 删除成功返回TRUE,不存在该节点返回FALSE
     */
    bool DeleteByJobName( Event *head, char *jobName );
    /* 删除事件队列 */
    void DestroyQueue( Event *head );

    3.2 进程调度相关函数

    /* 插入函数 */
    void InsertByHappenTime( Event *head, Event *e );
    void InsertByJobTime( Event *head, Event *e );
    void InsertByPriority( Event *head, Event *e );
    void InsertByRemainTime( Event *head, Event *e );
    void InsertByHRR( Event *head, Event *e );
    /* 排序函数 */
    void SortByHRR( Event *head, int currentTime );
    /* 调度函数 */
    void SJF ( Event *eventHead );
    void SRTF( Event *eventHead );
    void HRRF( Event *eventHead );
    void Priority(Event *eventHead);    //抢占式优先级调度
    void RR  ( Event *eventHead );      //时间片大小为1

    程序实现

     

    一、插入函数(用于插入排序)

    1.1 按开始时间插入

    void InsertByHappenTime( Event *head, Event *e )
    {
        if ( head == NULL || e == NULL )
        {
            cerr << "At: " << __FILE__ << "
    Line: " << __LINE__ << endl;
            throw "Head Point is NULL!
    ";
        }
        
        Event *p = head;
        while ( ( p->next != NULL ) && ( e->happenTime >= (p->next)->happenTime ) )
        {
            p = p->next;
        }
    
        e->next = p->next;
        p->next = e;
    }

    1.2 按结束时间插入

    void InsertFinishEvent( Event *head, Event *e )
    {
        if ( head == NULL || e == NULL )
        {
            cerr << "At: " << __FILE__ << "
    Line: " << __LINE__ << endl;
            throw "Head Point is NULL!
    ";
        }
        
        Event *p = head;
        while ( ( p->next != NULL ) && ( e->happenTime > (p->next)->happenTime ) )
        {
            p = p->next;
        }
        
        e->next = p->next;
        p->next = e;
    }

    1.3 按作业时间插入

    void InsertByJobTime( Event *head, Event *e )
    {
        if ( head == NULL || e == NULL )
        {
            cerr << "At: " << __FILE__ << "
    Line: " << __LINE__ << endl;
            throw "Head Point is NULL!
    ";
        }
        
        Event *p = head;
        while ( ( p->next != NULL ) && ( (e->job).needTime >= (p->next)->job.needTime ) )
        {
            p = p->next;
        }
    
        e->next = p->next;
        p->next = e;
    }

    1.4 按剩余时间插入

    void InsertByRemainTime( Event *head, Event *e )
    {
        if ( head == NULL || e == NULL )
        {
            cerr << "At: " << __FILE__ << "
    Line: " << __LINE__ << endl;
            throw "Head Point is NULL!
    ";
        }
        
        Event *p = head;
        while ( ( p->next != NULL ) && ( e->remainTime >= p->next->remainTime ) )
        {
            p = p->next;
        }
        e->next = p->next;
        p->next = e;
    }

    1.5 按优先级插入

    void InsertByPriority( Event *head, Event *e )
    {
        if ( head == NULL || e == NULL )
        {
            cerr << "At: " << __FILE__ << "
    Line: " << __LINE__ << endl;
            throw "Head Point is NULL!
    ";
        }
        
        Event *p = head;
        while ( ( p->next != NULL ) && ( e->job.priority >= p->next->job.priority ) )
        {
            p = p->next;
        }
        e->next = p->next;
        p->next = e;
    }

    1.6 按最高响应比插入

    void InsertByHRR( Event *head, Event *e )
    {
        if ( head == NULL || e == NULL )
        {
            cerr << "At: " << __FILE__ << "
    Line: " << __LINE__ << endl;
            throw "Head Point is NULL!
    ";
        }
        
        Event *p = head;
        while ( ( p->next != NULL ) && ( e->hrr <= p->next->hrr ) )
        {
            p = p->next;
        }
        e->next = p->next;
        p->next = e;
    }

    1.7 最高响应比插入排序

    void SortByHRR( Event *head, int currentTime )
    {
        Event *addrValue = new Event;
        addrValue->next = head->next;
        Event *p = addrValue->next;
        head->next = NULL; //将节点放置另一个链表中
        while ( p != NULL )
        {
            p->happenTime = currentTime;
            p->hrr = 1 + ( p->happenTime - p->job.arriveTime ) / p->job.needTime * 0.1;
            p = p->next;
        }
    
        while ( p = FetchFirstEvent( addrValue ) )
        {
            InsertByHRR( head, p );
            p = addrValue->next;
        }
    
        delete addrValue;
        addrValue = NULL;
    }

    二、调度算法

    2.1 最短工作时间优先

    void SJF( Event *eventHead )
    {
        if ( eventHead == NULL )
        {
            cerr << "At: " << __FILE__ << "
    Line: " << __LINE__ << endl;
            throw "Head Point is NULL!
    ";
        }
    
        int currentTime = 0;            //当前时间
        bool  isCpuBusy = false;        //CPU忙碌状态
        Event *readyQueue = new Event;  //包含头结点,就绪队列
        readyQueue->next = NULL;
    
        while ( eventHead->next != NULL )
        {
            Event *firstEvent = FetchFirstEvent( eventHead );
            currentTime = firstEvent->happenTime;
            
            if ( firstEvent->type == ARRIVALEVENT )
            {
                if ( isCpuBusy == true )
                {
                    InsertByJobTime( readyQueue, firstEvent );
                }
                else 
                {
                    isCpuBusy = true;
    
                    Event *finishEvent = new Event;
                    finishEvent->type = FINISHEVENT;
                    finishEvent->jobBeginTime = currentTime;
                    finishEvent->happenTime = currentTime + firstEvent->job.needTime;
                    finishEvent->remainTime = 0;
                    CopyJob( &(finishEvent->job),  &(firstEvent->job) );
    
                    if ( firstEvent != NULL )
                        delete firstEvent;//删除正在执行事件节点
                    firstEvent = NULL;
    
                    InsertByHappenTime( eventHead, finishEvent );
                }
                continue ;
            }
            
            if ( firstEvent->type ==  FINISHEVENT )
            {
                ShowEvent( firstEvent );
                if ( firstEvent != NULL )    
                    delete firstEvent;//删除已执行事件节点
                firstEvent = NULL;
    
                isCpuBusy = false;
                Event *shortestEvent = FetchFirstEvent( readyQueue );
    
                if ( shortestEvent != NULL )
                {
                    isCpuBusy = true;
    
                    Event *finishEvent = new Event();
                    finishEvent->type = FINISHEVENT;
                    finishEvent->jobBeginTime = currentTime;
                    finishEvent->happenTime = currentTime + shortestEvent->job.needTime;
                    finishEvent->remainTime = shortestEvent->job.needTime;
                    CopyJob( &(finishEvent->job),  &(shortestEvent->job) );
    
                    if ( shortestEvent != NULL )    
                        delete shortestEvent;//删除正在执行事件节点
                    shortestEvent = NULL;
    
                    InsertByHappenTime( eventHead, finishEvent );
                }
            }
        }
    }

    2.2 最短剩余时间优先

    void SRTF( Event *eventHead )
    {
        if ( eventHead == NULL )
        {
            cerr << "At: " << __FILE__ << "
    Line: " << __LINE__ << endl;
            throw "Head Point is NULL!
    ";
        }
        
        int currentTime = 0;            
        bool  isCpuBusy = false;        
        Event *readyQueue = new Event;  
        readyQueue->next = NULL;
        Event *runEvent = NULL;            //正在运行事件节点
        
        while ( eventHead->next != NULL )
        {
            Event *firstEvent = FetchFirstEvent( eventHead );
            int frontTime = currentTime;                      //上次事件发生时间
            currentTime = firstEvent->happenTime;
            
            if ( firstEvent->type == ARRIVALEVENT )
            {
                if ( isCpuBusy == true )
                {
                    runEvent->happenTime = currentTime;
                    runEvent->remainTime -= (currentTime - frontTime);//剩余时间 = 运行时间- 已运行时间(本次-上次时间)
                    if ( firstEvent->remainTime < runEvent->remainTime )
                    {                                                        //抢断
                        DeleteByJobName( eventHead, runEvent->job.name );    //删除上次事件的结束事件,PS.若上次事件先插入,将会被删除
                        InsertByRemainTime( readyQueue, runEvent );          //上次事件加入就绪队列
    
                        runEvent = firstEvent;                               //上次事件已插入继续队列,无须释放空间,更新本次事件
                        runEvent->isFirstExe = false;                        //
    
                        Event *finishEvent = new Event;                      
                        finishEvent->type = FINISHEVENT;
                        finishEvent->jobBeginTime = runEvent->jobBeginTime;//
                        finishEvent->happenTime = currentTime + runEvent->remainTime;
                        finishEvent->remainTime = 0;
                        CopyJob( &(finishEvent->job),  &(runEvent->job) );
                        InsertByHappenTime( eventHead, finishEvent );      //插入结束事件
                    }
                    else
                    {    
                        InsertByRemainTime( readyQueue, firstEvent );//等待,加入就绪事件队列
                    }
                }
    
                if ( isCpuBusy == false )
                {
                    isCpuBusy = true;
                    firstEvent->isFirstExe = false;
                
                    Event *finishEvent = new Event;
                    finishEvent->type = FINISHEVENT;
                    finishEvent->jobBeginTime = firstEvent->jobBeginTime;    //
                    finishEvent->isFirstExe = false;
                    finishEvent->happenTime = currentTime + firstEvent->remainTime;
                    finishEvent->remainTime = 0;
                    CopyJob( &(finishEvent->job),  &(firstEvent->job) );
                    
                    runEvent = firstEvent;
    
                    InsertByHappenTime( eventHead, finishEvent );
                }
    
                continue ;
            }
            
            if ( firstEvent->type ==  FINISHEVENT )
            {
                ShowEvent( firstEvent );
                if ( runEvent != NULL )        //删除已运行事件
                    delete runEvent;
                runEvent = NULL;
                
                isCpuBusy = false;
                Event *remainTimeEvent = FetchFirstEvent( readyQueue );
    
                if ( remainTimeEvent != NULL )
                {
                    isCpuBusy = true;
    
                    if ( remainTimeEvent->isFirstExe )    //在就绪队列中,若作业首次执行,必然是延迟发生的
                         remainTimeEvent->jobBeginTime = currentTime;
                    remainTimeEvent->isFirstExe = false;
    
                    Event *finishEvent = new Event();
                    finishEvent->type = FINISHEVENT;
                    finishEvent->jobBeginTime = remainTimeEvent->jobBeginTime;
                    finishEvent->happenTime = currentTime + remainTimeEvent->remainTime;
                    finishEvent->remainTime = 0;
                    CopyJob( &(finishEvent->job),  &(remainTimeEvent->job) );
    
                    runEvent = remainTimeEvent;       
                    InsertByHappenTime( eventHead, finishEvent );
                 }
            }
        }
    }

    2.3 时间片轮转(时间片大小为1)

    void RR( Event *eventHead )
    {
        if ( eventHead == NULL )
        {
            cerr << "At: " << __FILE__ << "
    Line: " << __LINE__ << endl;
            throw "Head Point is NULL!
    ";
        }
        
        int currentTime = 0;
        bool isCpuBusy = false;
        Event *readyQueue = new Event;
        readyQueue->next = NULL;
        
        while ( eventHead->next != NULL )
        {    
            Event *firstEvent = FetchFirstEvent( eventHead );
            if ( firstEvent->happenTime > currentTime )
                currentTime = firstEvent->happenTime;
            
            if ( firstEvent->type == ARRIVALEVENT )
            {
                if ( isCpuBusy )
                {
                    InsertTail( readyQueue, firstEvent );
                }
                else
                {    
                    isCpuBusy = true;
                    Event *nextEvent = new Event;
                    nextEvent->jobBeginTime = firstEvent->jobBeginTime;
                    CopyJob( &(nextEvent->job),  &(firstEvent->job) );
                    if ( firstEvent->remainTime <= TIMER )    //FinishEvent
                    {
                        nextEvent->type = FINISHEVENT;
                        nextEvent->happenTime = currentTime + firstEvent->remainTime;
                        nextEvent->remainTime = 0;    
                        InsertFinishEvent( eventHead, nextEvent );
                    }
                    else    //TimerEvent
                    {
                        nextEvent->type = TIMEREVENT;
                        nextEvent->happenTime = currentTime + TIMER;
                        nextEvent->remainTime = firstEvent->remainTime - TIMER;
                        InsertByHappenTime( eventHead, nextEvent );
                    }
                    
                    if ( firstEvent != NULL )
                        delete firstEvent;//删除正在执行事件节点
                    firstEvent = NULL;
                }
                continue ;
            }
            
            if ( firstEvent->type == TIMEREVENT )
            {
                InsertTail( readyQueue, firstEvent );
            }
            
            int isFinish = false;
            if ( firstEvent->type ==  FINISHEVENT )
            {
                ShowEvent( firstEvent );
                if ( firstEvent != NULL )    
                    delete firstEvent;//删除已执行事件节点
                firstEvent = NULL;
    
                isFinish = true;
            }
    
            while ( firstEvent = FetchFirstEvent( readyQueue ) )
            {
                if ( isFinish )
                    isCpuBusy = true, isFinish = false;
                Event *nextEvent = new Event;
                if ( firstEvent->type == ARRIVALEVENT )
                    nextEvent->jobBeginTime = currentTime;
                else if ( firstEvent->type == TIMEREVENT )
                    nextEvent->jobBeginTime = firstEvent->jobBeginTime;
                CopyJob( &(nextEvent->job),  &(firstEvent->job) );
                if ( firstEvent->remainTime <= TIMER )    //FinishEvent
                {
                    nextEvent->type = FINISHEVENT;
                    nextEvent->happenTime = currentTime + firstEvent->remainTime;
                    nextEvent->remainTime = 0;
                    InsertFinishEvent( eventHead, nextEvent );
                }
                else    //TimerEvent
                {    
                    nextEvent->type = TIMEREVENT;
                    nextEvent->happenTime = currentTime + TIMER;
                    nextEvent->remainTime = firstEvent->remainTime - TIMER;
                    InsertByHappenTime( eventHead, nextEvent );
                }
                
                currentTime = nextEvent->happenTime;
                
                if ( firstEvent != NULL )
                    delete firstEvent;//删除正在执行事件节点
                firstEvent = NULL;
            }
        }
    }

    2.4 抢占式优先级调度

    void Priority( Event *eventHead )
    {
        if ( eventHead == NULL )
        {
            cerr << "At: " << __FILE__ << "
    Line: " << __LINE__ << endl;
            throw "Head Point is NULL!
    ";
        }
        
        int currentTime = 0;            
        bool  isCpuBusy = false;        
        Event *readyQueue = new Event;  
        readyQueue->next = NULL;
        Event *runEvent = NULL;            //正在运行事件节点
        
        while ( eventHead->next != NULL )
        {
            Event *firstEvent = FetchFirstEvent( eventHead );
            int frontTime = currentTime;                      //上次事件发生时间
            currentTime = firstEvent->happenTime;
            
            if ( firstEvent->type == ARRIVALEVENT )
            {
                if ( isCpuBusy == true )
                {
                    runEvent->happenTime = currentTime;
                    runEvent->remainTime -= (currentTime - frontTime);//剩余时间 = 运行时间- 已运行时间(本次-上次时间)
                    if ( firstEvent->job.priority < runEvent->job.priority )
                    {                                                      //抢断
                        DeleteByJobName( eventHead, runEvent->job.name ); //删除上次事件的结束事件,PS.若上次事件先插入,将会被删除
                        InsertByPriority( readyQueue, runEvent );          //上次事件加入就绪队列
                        
                        runEvent = firstEvent;                              //上次事件已插入继续队列,无须释放空间,更新本次事件
                        runEvent->isFirstExe = false;                      //
                        
                        Event *finishEvent = new Event;                      
                        finishEvent->type = FINISHEVENT;
                        finishEvent->jobBeginTime = runEvent->jobBeginTime;//
                        finishEvent->happenTime = currentTime + runEvent->remainTime;
                        finishEvent->remainTime = 0;
                        CopyJob( &(finishEvent->job),  &(runEvent->job) );
                        InsertByHappenTime( eventHead, finishEvent );      //插入结束事件
                    }
                    else
                    {    
                        InsertByRemainTime( readyQueue, firstEvent );//等待,加入就绪事件队列
                    }
                }
                
                if ( isCpuBusy == false )
                {
                    isCpuBusy = true;
                    firstEvent->isFirstExe = false;
                    
                    Event *finishEvent = new Event;
                    finishEvent->type = FINISHEVENT;
                    finishEvent->jobBeginTime = firstEvent->jobBeginTime;    
                    finishEvent->happenTime = currentTime + firstEvent->remainTime;
                    finishEvent->remainTime = 0;
                    CopyJob( &(finishEvent->job),  &(firstEvent->job) );
                    
                    runEvent = firstEvent;
                    
                    InsertByHappenTime( eventHead, finishEvent );
                }
                
                continue ;
            }
            
            if ( firstEvent->type ==  FINISHEVENT )
            {
                ShowEvent( firstEvent );
                if ( runEvent != NULL )        //删除已运行事件
                    delete runEvent;
                runEvent = NULL;
                
                isCpuBusy = false;
                Event *priorityEvent = FetchFirstEvent( readyQueue );
                
                if ( priorityEvent != NULL )
                {
                    isCpuBusy = true;
                    
                    if ( priorityEvent->isFirstExe )    //在就绪队列中,若作业首次执行,必然是延迟发生的
                        priorityEvent->jobBeginTime = currentTime;
                    
                    Event *finishEvent = new Event();
                    finishEvent->type = FINISHEVENT;
                    finishEvent->jobBeginTime = priorityEvent->jobBeginTime;
                    finishEvent->happenTime = currentTime + priorityEvent->remainTime;
                    finishEvent->remainTime = 0;
                    CopyJob( &(finishEvent->job),  &(priorityEvent->job) );
                    
                    runEvent = priorityEvent;
                    InsertByHappenTime( eventHead, finishEvent );
                }
            }
        }
    }

    2.5 最高响应比优先

    void HRRF( Event *eventHead )
    {
        if ( eventHead == NULL )
        {
            cerr << "At: " << __FILE__ << "
    Line: " << __LINE__ << endl;
            throw "Head Point is NULL!
    ";
        }
        
        int currentTime = 0;            //当前时间
        bool  isCpuBusy = false;        //CPU忙碌状态
        Event *readyQueue = new Event;  //包含头结点,就绪队列
        readyQueue->next = NULL;
        
        while ( eventHead->next != NULL )
        {
            Event *firstEvent = FetchFirstEvent( eventHead );
            currentTime = firstEvent->happenTime;
            
            if ( firstEvent->type == ARRIVALEVENT )
            {
                if ( isCpuBusy == true )
                {
                    InsertTail( readyQueue, firstEvent ); 
                }
                else 
                {
                    isCpuBusy = true;
                    
                    Event *finishEvent = new Event;
                    finishEvent->type = FINISHEVENT;
                    finishEvent->jobBeginTime = currentTime;
                    finishEvent->happenTime = currentTime + firstEvent->job.needTime;
                    finishEvent->remainTime = 0;
                    CopyJob( &(finishEvent->job),  &(firstEvent->job) );
                    
                    if ( firstEvent != NULL )
                        delete firstEvent;//删除正在执行事件节点
                   firstEvent = NULL;
                    
                    InsertByHappenTime( eventHead, finishEvent );
                }
                continue ;
            }
            
            if ( firstEvent->type ==  FINISHEVENT )
            {
                ShowEvent( firstEvent );
                if ( firstEvent != NULL )    
                    delete firstEvent;//删除已执行事件节点
                firstEvent = NULL;
                
                isCpuBusy = false;
                SortByHRR( readyQueue, currentTime );
                Event *hrrEvent = FetchFirstEvent( readyQueue );
                
                if ( hrrEvent != NULL )
                {
                    isCpuBusy = true;
                    Event *finishEvent = new Event();
                    finishEvent->type = FINISHEVENT;
                    finishEvent->jobBeginTime = currentTime;
                    finishEvent->happenTime = currentTime + hrrEvent->job.needTime;
                    finishEvent->remainTime = hrrEvent->job.needTime;
                    CopyJob( &(finishEvent->job),  &(hrrEvent->job) );
                    
                    if ( hrrEvent != NULL )    
                        delete hrrEvent;//删除正在执行事件节点
                      hrrEvent = NULL;
                    
                    InsertByHappenTime( eventHead, finishEvent );
                }
            }
        }
    }

    测试数据

    进程

    到达时间

    服务时间

    优先级

    A

    0

    3

    5

    B

    2

    6

    2

    C

    4

    4

    3

    D

    6

    5

    4

    E

    8

    2

    1

     运行结果

    一、最短作业时间优先

    clip_image002[1]image

    二、最短剩余时间优先

    clip_image002[5]image

    三、最高响应比优先

    clip_image002[7]image

    四、优先级调度

    clip_image002[9]image

    五、时间片轮转

    时间片=1

    clip_image002[11]image

    时间片=4

    clip_image002[13]image 

    总结与体会

    根据流程图,一步一步实现功能,思路清晰,就不会出错。PS:C#程序的可视化及其调度算法采用LINQ实现,将在下章讲解。

  • 相关阅读:
    抱歉,我不接私单了
    MySQL大小写补坑记
    Go 系列教程 —— 第 15 部分:指针
    Go 系列教程 —— 14. 字符串
    Go 系列教程 —— 13. Maps
    Go 系列教程 —— 12. 可变参数函数
    Go 系列教程 —— 11. 数组和切片
    Go 系列教程 — 10. switch 语句
    Go 系列教程 — 9. 循环
    Go 系列教程 —— 8. if-else 语句
  • 原文地址:https://www.cnblogs.com/bajdcc/p/4707746.html
Copyright © 2011-2022 走看看