稍稍有点操作系统基础的朋友应该知道进程的调度算法,在这里Koala还是给大家略微介绍一下接下来将要用到的几种算法:
- 先来先服务(FCFS)
采用FCFS调度,先请求CPU的进程会先分配到CPU。
使用FCFS调度的等待时间通常较长,CPU利用率也会较低 - 最短作业优先调度(SJF)
采用SJF调度会选择具有最短CPU运行时间的进程分配CPU使用权。如果两个进程的CPU区间相同,则按照FCFS来进行选择。
SJF调度可以证明是最佳的,它降低了平均等待时间。 - 轮转法调度(RR)
RR调度将CPU时间分为较小的时间片,调度程序循环就绪队列。为每一个进程分配不超过一个时间片的CPU。
RR调度专门用于分时系统。 - 优先级调度
每一个进程都有一个优先级与其关联,具有最高优先级的进程会分配到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算法通常是最少平均等待时间的调度算法
最后希望大家能够积极提建议,指出纰漏!