五種進程調度的算法實現(二)


程序設計

一、數據結構

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__ << "\nLine: " << __LINE__ << endl;
        throw "Head Point is NULL!\n";
    }
    
    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__ << "\nLine: " << __LINE__ << endl;
        throw "Head Point is NULL!\n";
    }
    
    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__ << "\nLine: " << __LINE__ << endl;
        throw "Head Point is NULL!\n";
    }
    
    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__ << "\nLine: " << __LINE__ << endl;
        throw "Head Point is NULL!\n";
    }
    
    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__ << "\nLine: " << __LINE__ << endl;
        throw "Head Point is NULL!\n";
    }
    
    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__ << "\nLine: " << __LINE__ << endl;
        throw "Head Point is NULL!\n";
    }
    
    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__ << "\nLine: " << __LINE__ << endl;
        throw "Head Point is NULL!\n";
    }

    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__ << "\nLine: " << __LINE__ << endl;
        throw "Head Point is NULL!\n";
    }
    
    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__ << "\nLine: " << __LINE__ << endl;
        throw "Head Point is NULL!\n";
    }
    
    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__ << "\nLine: " << __LINE__ << endl;
        throw "Head Point is NULL!\n";
    }
    
    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__ << "\nLine: " << __LINE__ << endl;
        throw "Head Point is NULL!\n";
    }
    
    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實現,將在下章講解。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM