Linux程式設計:模擬程式排程演算法

KoalaZB發表於2016-12-10

稍稍有點作業系統基礎的朋友應該知道程式的排程演算法,在這裡Koala還是給大家略微介紹一下接下來將要用到的幾種演算法:

  1. 先來先服務(FCFS)
    採用FCFS排程,先請求CPU的程式會先分配到CPU。
    使用FCFS排程的等待時間通常較長,CPU利用率也會較低
  2. 最短作業優先排程(SJF)
    採用SJF排程會選擇具有最短CPU執行時間的程式分配CPU使用權。如果兩個程式的CPU區間相同,則按照FCFS來進行選擇。
    SJF排程可以證明是最佳的,它降低了平均等待時間
  3. 輪轉法排程(RR)
    RR排程將CPU時間分為較小的時間片,排程程式迴圈就緒佇列。為每一個程式分配不超過一個時間片的CPU。
    RR排程專門用於分時系統
  4. 優先順序排程
    每一個程式都有一個優先順序與其關聯,具有最高優先順序的程式會分配到CPU。
    優先順序排程的一個主要問題是優先順序較低的程式會產生飢餓現象。

整個程式設計思路按照如下進行:

建立主執行緒,主執行緒建立子執行緒,子執行緒有一個虛擬PCB
主執行緒建立20個子執行緒,分別實現FCFS排程、SJF排程、RR排程、優先順序排程,並且計算每個排程的平均等待時間。
對於每個子執行緒,在其執行期間,輸出其佔用的時間標號(例如,第3個執行緒佔用了第10秒的CPU時間,輸出為:“Thread3:10”)。

下面是整個的程式碼(僅供參考):

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<unistd.h>
#include<pthread.h>
#include<time.h>
#include<iostream> 
#define Thread_Num 20
using namespace std;

pthread_mutex_t Device_mutex ;
//Virtual PCB of threads 
struct VirtualPCB
{
    int tid;
    int priority;
    int waittime;
    int runtime;
    int arrivetime;
    int visited;
    int tempruntime;
    public:
        int gettid()
        {
            return tid; 
        }
        int getwaittime()
        {
            return waittime;    
        }
        int getpriority()
        {
            return priority;
        }
        int getruntime()
        {
            return runtime;
        }
        int getarrivetime()
        {
            return arrivetime;
        }
        void setvisit(int a)
        {
            visited=a;
        }
        int getvisit()
        {
            return visited;
        }
        int gettempruntime()
        {
            return tempruntime;
        }
        void setwaittime(int n)
        {
            waittime = n;   
        }
        void settempruntime(int n)
        {
            tempruntime = tempruntime - n;
        }
}TCB[Thread_Num]; 

//Function to initial virtual PCB
void t_init()
{
    int n;
    srand(time(NULL));
    for(n =0;n<Thread_Num;n++)
    {
    TCB[n].tid = n + 1;//用執行緒建立序號作為虛擬程式id
    //用隨機數隨機產生虛擬PCB的值
    TCB[n].priority = 1 + rand()%19;
    TCB[n].runtime = 1 + rand()%19;
    TCB[n].arrivetime = 0;//模擬時,預設程式按建立順序依次在0時刻到達
    TCB[n].waittime = 0;
    TCB[n].visited =0;
    TCB[n].tempruntime = TCB[n].runtime;
    }
}

//Threads run function
void *t_print(void *arg)
{
    int n = *(int *)arg;//get argument
    while(1)
    {
            pthread_mutex_lock(&Device_mutex);
            printf("Thread_%-2d: ",n);
            printf("tid:%-2d priority:%-2d runtime:%-2d \n",TCB[n-1].gettid(),TCB[n-1].priority,TCB[n-1].runtime);
            pthread_mutex_unlock(&Device_mutex);
            sleep(1);
        break;
    }

    //printf("Error %d\n",n);

    pthread_exit(0);
}

//First come first service schedule function
void FCFS()
{
    cout<<"-----------FCFS:"<<endl;
    int i,j;
    int start = 0;
    float waittime = 0;
    float avwait = 0;
    for(i=0;i<Thread_Num/2;i++)
    {
        for(j=0;j<Thread_Num;j++){
            if(TCB[j].getarrivetime()==i && TCB[j].getvisit()==0){
                printf("Thread: %-2d  Start: %-3d   Runtime: %-2d\n",TCB[j].gettid(),start,TCB[j].getruntime());
                waittime = waittime + (float)start;
                start = start + TCB[j].getruntime();
                TCB[j].setvisit(1);
            }
        }
    }
    avwait = waittime / (float)Thread_Num;
    printf("Total waitting time : %f\n",waittime);
    printf("Average waitting time : %f\n",avwait);
}

//Shortest job first schedule function
void SJF()
{
    for(int k=0 ;k<Thread_Num;k++)
    {
        TCB[k].setvisit(0);
    }
    cout<<"-------------SJF:"<<endl;
    int i,j;
    int start = 0;
    float waittime = 0;
    float avwait = 0;
    for(i=1;i<Thread_Num;i++)
    {
        for(j=0;j<Thread_Num;j++){
            if(TCB[j].getruntime()==i && TCB[j].getvisit()==0){
                printf("Thread: %-2d  Start: %-3d   Runtime: %-2d\n",TCB[j].gettid(),start,TCB[j].getruntime());
                waittime = waittime + (float)start;
                start = start + TCB[j].getruntime();
                TCB[j].setvisit(1);
            }
        }
    }
    avwait = waittime / (float)Thread_Num;
    printf("Total waitting time : %f\n",waittime);
    printf("Average waitting time : %f\n",avwait);
}


//Round R schedule function
void RR(int r)
{
    cout<<"--------------RR:"<<endl;
    int start = 0;
    float waittime = 0;
    float avwait = 0;
    for(int i=0;i<Thread_Num;i++)
    {
        int totaltime = totaltime + TCB[i].getruntime();
        TCB[i].setvisit(0);
    }
    for(int j=0;j<20*Thread_Num;j=j+r)
    {
        int k = (j%(20*r))/r;
        if(TCB[k].gettempruntime() > 0){
            int tepruntime = r;
            if(TCB[k].gettempruntime()-r<=0){
                tepruntime = TCB[k].gettempruntime();
                TCB[k].setwaittime(start + tepruntime - TCB[k].getruntime());
                }
            printf("Thread: %-2d  Start:  %-3d  Runtime:%-2d \n",TCB[k].gettid(), start,tepruntime);
            start = start + tepruntime;
            TCB[k].settempruntime(r) ;
        }
    }
    for(int m=0;m<Thread_Num;m++)
    {
        waittime += TCB[m].getwaittime();
        //printf("TCB[%d].getwaittime():%d\n",m+1,TCB[m].getwaittime());
    }
    avwait = waittime / (float)Thread_Num;
    printf("Total waitting time : %f\n",waittime);
    printf("Average waitting time : %f\n",avwait);
}


//Priority schedule function
void Priority()
{
    for(int k=0 ;k<Thread_Num;k++)
    {
        TCB[k].setvisit(0);
    }
    cout<<"-----------Priority:"<<endl;
    int i,j;
    int start = 0;
    float waittime = 0;
    float avwait = 0;
    for(i=1;i<Thread_Num;i++)
    {
        for(j=0;j<Thread_Num;j++){
            if(TCB[j].getpriority()==i && TCB[j].getvisit()==0){
                printf("Thread: %-2d  Start: %-3d   Runtime: %-2d\n",TCB[j].gettid(),start,TCB[j].getruntime());
                waittime = waittime + (float)start;
                start = start + TCB[j].getruntime();
                TCB[j].setvisit(1);
            }
        }
    }
    avwait = waittime / (float)Thread_Num;
    printf("Total waitting time : %f\n",waittime);
    printf("Average waitting time : %f\n",avwait);
}

//Main thread execute function to create 20 children threads
void *Children(void*)
{
    int ret[Thread_Num];
    t_init();
        pthread_t tid[Thread_Num];
    pthread_mutex_init(&Device_mutex,NULL);
        int i,j;

        for(i=0;i<Thread_Num;i++)
        {
        int k =i+1;

            ret[i] = pthread_create(&tid[i],NULL,&t_print, &k);
        if(ret[i] == 0) {
            sleep(1);
        }
            else{ 
            printf("Thread_%-2d failed!\n",i+1);

        }   
        }
        for(j=0;j<Thread_Num;j++)
            pthread_join (tid[i], NULL);
    pthread_mutex_destroy(&Device_mutex);
    pthread_exit(0);
}

int main()
{
    int ret1;
    pthread_t tid1;//Declare main thread
    ret1 = pthread_create(&tid1,NULL,&Children,NULL);//Create main thread
    if(ret1 == 0) 
    {
        printf("Main Thread ok!\n");
        sleep(20);
    }
        else{ 
        printf("Thread failed!\n");

    }   

    FCFS();
    SJF();
    cout<<"Please enter RR time:\n";//Request RR time
    int rr;
    scanf("%d",&rr);
    RR(rr);
    Priority();
        return 0;
}

OK!此程式碼的執行結果如下(部分):

第一張圖列印了一下虛擬PCB的部分內容:

這裡寫圖片描述

第二張圖片列印了FCFS排程演算法執行結果:

這裡寫圖片描述

第三張圖片列印了SJF排程演算法執行結果:

這裡寫圖片描述

第四張圖片列印了RR排程演算法執行結果(部分):

這裡寫圖片描述

第五張圖片列印了Priority排程演算法執行結果:

這裡寫圖片描述

注意看每張圖下面的兩行資料,分別是不同演算法對應的總的程式的等待時間以及平均等待時間的大小,印證了SJF演算法通常是最少平均等待時間的排程演算法

最後希望大家能夠積極提建議,指出紕漏!

相關文章