操作系统---“进程调度模拟程序” , “生产者―消费者问题算法的实现” , “银行家算法的实现”

       如果有正在学习计算机操作系统的小伙伴,可以通过此文章对 进程调度模拟程序,生产者――消费者问题算法的实现,银行家算法的实现更加清楚。

      本人也只是一个学生,下面内容我主要整合了一些学习心得和成果,还有能够帮助自己快速掌握知识的视频,网站,链接。希望对你们有用。

1. 进程调度模拟程序

#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;


struct PCB//类定义PCB表
{
    string ID;        //进程的名字
    int arrive_time; //进入进程队列的时间
    int CPUtime;     //进程运行完需要的时间
    int priority;  //优先级
    char status;//进程状态,"R"-运行态,"W"表示就绪态
};


vector<PCB> EnterReadyQueue;


//排序方式 按进入进程队列的时间先后排 时间相同则把运行时间长的放前面
bool cmp0(PCB a, PCB b) {
    if (a.arrive_time == b.arrive_time) {
        return a.CPUtime < b.CPUtime;
    }
    return a.arrive_time < b.arrive_time; //对时间进行排序。
}
//排序方式 按进入进程队列的优先级排 优先级相同则把进队时间先的放前面
bool cmp1(PCB a, PCB b) {
    if (a.priority == b.priority) {
        return a.arrive_time < b.arrive_time;
    }
    return a.priority > b.priority; //对时间进行排序。
}

void print_queue() { //打印当前就绪队列的情况。
    cout << "<-------------------------------->" << endl;
    cout << "进程名字     到达时间    需要运行的时间     优先数     进程状态" << endl;
    for (int i = 0; i < EnterReadyQueue.size(); i++) {
        cout << EnterReadyQueue[i].ID << "             "
            << EnterReadyQueue[i].arrive_time << "             "
            << EnterReadyQueue[i].CPUtime << "             "
            << EnterReadyQueue[i].priority << "             "
            << EnterReadyQueue[i].status << endl;
    }
    cout << "<-------------------------------->" << endl << endl;
}

void Rprint_queue() { //打印当前就绪队列的情况。
    cout << "<-------------------------------->" << endl;
    cout << "进程名字     到达时间    需要运行的时间     进程状态" << endl;
    for (int i = 0; i < EnterReadyQueue.size(); i++) {
        cout << EnterReadyQueue[i].ID << "             "
            << EnterReadyQueue[i].arrive_time << "             "
            << EnterReadyQueue[i].CPUtime << "             "
            << EnterReadyQueue[i].status << endl;
    }
    cout << "<-------------------------------->" << endl << endl;
}

void priority_way()//优先数算法的调用
{
    int w_time = 0;
    w_time = EnterReadyQueue[0].arrive_time + EnterReadyQueue[0].CPUtime;
    cout << "当前进程名字     进程到达时间    需要运行的时间     优先数" << endl;
    cout << EnterReadyQueue[0].ID << "               "
            << EnterReadyQueue[0].arrive_time << "               "
            << EnterReadyQueue[0].CPUtime << "               "
            << EnterReadyQueue[0].priority << endl;
            cout << EnterReadyQueue[0].ID << "在第" << w_time << "秒运行结束"<< endl<< endl;
            EnterReadyQueue.erase(EnterReadyQueue.begin());

    sort(EnterReadyQueue.begin(), EnterReadyQueue.end(), cmp1);   //重新排序
    print_queue();
    while(EnterReadyQueue.size() > 0)
    {

        PCB now = EnterReadyQueue.front();
       w_time  = w_time + now.CPUtime;
    cout << "当前进程名字     进程到达时间    需要运行的时间     优先数" << endl;
    cout << now.ID << "               "
            << now.arrive_time << "               "
            << now.CPUtime << "               "
            << now.priority << endl;
            cout << now.ID << "在第" << w_time << "秒运行结束"<< endl<< endl;
            EnterReadyQueue.erase(EnterReadyQueue.begin());
            if(EnterReadyQueue.size() != 0)
            print_queue();

    }
   cout << "<-------- 就绪队列为空,调度进程结束 ---------->" << endl << endl;
  cout << "进程总花费时间为 " << w_time << " 秒" << endl << endl;

}

void RR_way() // 时间片轮转算法的调用
{
    int q;  //时间片
    cout <<"<-------- 请输入时间片 ---------->" << endl;
    cin >> q;
    while(EnterReadyQueue.size() > 0)
    {
        PCB now = EnterReadyQueue.front();
        now.CPUtime  =  now.CPUtime - q;
        if(now.CPUtime <= 0)
            EnterReadyQueue.erase(EnterReadyQueue.begin());
            else
            {
                EnterReadyQueue.push_back(now);
                EnterReadyQueue.erase(EnterReadyQueue.begin());
            }
            if(EnterReadyQueue.size() != 0)
            Rprint_queue();
    }
    cout << "<-------- 就绪队列为空,调度进程结束 ---------->" << endl << endl;
}

void m_priority()//优先数算法
{
      int n;
    cout << "请输入要运行的进程数量: ";
    cin >> n;
    for (int i = 1; i <= n; i++) {
        PCB Pro;
        cout << "请输入第 " << i << " 个进程的名字: ";
        cin >> Pro.ID;
        cout << "请输入第 " << i << " 个进程的到达的时间: ";
        cin >> Pro.arrive_time;
        cout << "请输入第 " << i << " 个进程预计需要运行的时间: ";
        cin >> Pro.CPUtime;
        cout << "请输入第 " << i << " 个进程的优先级: ";
        cin >> Pro.priority;
        cout << endl;
        Pro.status = 'W';
        EnterReadyQueue.push_back(Pro); //加入进程就绪队列
    }
    sort(EnterReadyQueue.begin(), EnterReadyQueue.end(), cmp0); //对到来的时间排序

    print_queue();
    priority_way();
}
void m_RR()// 时间片轮转算法
{
     int n;
    cout << "请输入要运行的进程数量: ";
    cin >> n;
    for (int i = 1; i <= n; i++) {
        PCB Pro;
        cout << "请输入第 " << i << " 个进程的名字: ";
        cin >> Pro.ID;
        cout << "请输入第 " << i << " 个进程的到达的时间: ";
        cin >> Pro.arrive_time;
        cout << "请输入第 " << i << " 个进程预计需要运行的时间: ";
        cin >> Pro.CPUtime;
        cout << endl;
        Pro.status = 'W';
         Pro.priority = 0;
        EnterReadyQueue.push_back(Pro); //加入进程就绪队列
    }
    sort(EnterReadyQueue.begin(), EnterReadyQueue.end(), cmp0); //对到来的时间排序

    Rprint_queue();
    RR_way();

}

int main() {
    int x;
   cout << "<--------请选择使用哪一种算法 ---------->" << endl;
   cout << "1:优先级调度算法    2:时间片轮转调度算法 " <<endl;
   cin >> x;
   switch(x){
   case 1:m_priority();break;
   case 2:m_RR();break;
   }
   return 0;
}

(1)使用优先级调度算法

           

 优先级调度算法可以通过https://mbd.baidu.com/ma/s/asLPWulS此链接先进行学习,了解优先级调度算法的具体内容,再自己进行算法的实现。书本也有算法的介绍,但是我觉得上面链接讲的更简洁明了。

(2)时间片轮转调度算法

 时间片轮转算法相对简单,每次只要把第一个进程减去时间片,然后判断,如果减去之后小于0,那么说明该进程运行完毕,移除该进程,否则如果大于零说明载该时间片内未完成,那么将该进程移到末尾。课本上也讲的非常清楚。

 

 按照书上q = 4,的例子检验该代码可以得到下图:

 

 2.生产者――消费者问题算法的实现

老规矩 先上代码

#include<iostream>
#include<windows.h>
#include<thread>
#include<mutex>
#include<random>
#include<time.h>

using namespace std;

#define N 5


    int buffer[N];   //缓冲池
    int rear;        //指向缓冲池最末尾的产品
    mutex mu;        //互斥信号量
    int empty;       //空缓冲池区
    int full;        //满缓冲池区

    void init();           //初始化
    void insert(int item); //生产者生产产品
    void consumer1();      //消费者1
    void consumer2();       //消费者2
    void consumer2();       //消费者3
    //void remove(string name);
    void display();         //显示情况

void init()
{
    rear = -1;
    empty = N;
    full = 0;
}

void insert(int item)
{
    do {
        while (!empty)
        {
            //cout << "Producer is waiting for an empty slot..." << endl;
        }
          if(rear >= N-1)
        {
            cout <<"缓冲池已满" <<endl;
            break;
        }
        empty--;              //P(empty)
        mu.lock();            //P(mutex)
        cout << "生产的数为:" << item << endl;

        buffer[++rear] = item;  //产品放入缓冲区
        display();
        mu.unlock();            //V(mutex)
        full++;                //V(full)
        break;
    } while (1);
}


void display()
{
    cout << "缓冲区:";
    if (rear == -1)
        cout << "空" << endl;
    else {
        for (int i = 0; i <= rear; i++)
            cout << buffer[i] << " ";
        cout << endl;
    }
    cout << endl;
}

void producer()
{
    int item;
    srand((unsigned int)time(NULL));
    for (int i = 0; i < 20; i++)
    {
       item = rand() % 100 + 1;
       int e = rand() % 500;
        insert(item);
        Sleep(e);
    }
}

void consumer1()
{
    //for (int i = 0; i < 20; i++)
    while(1)
    {
        int e = rand() % 3000 ;
       // p->remove("消费者1号");
       int item;

    do {
        while (!full )
        {
           // cout << "Consumer is waiting for items..." << endl;
        }
        full--;

        mu.lock();
        if(rear != -1)
       item = buffer[rear--];    //从缓冲区取出产品
        cout << "消费者1号" << "消费的数为:" << item << endl;
        display();
        mu.unlock();            //V(mutex)
        empty++;             //V(empty)
        break;

    } while (1);
        Sleep(e);
    }
}

void consumer2()
{
    //for (int i = 0; i < 20; i++)
 while(1)
    {
        int e = rand() % 2000 ;
       // p->remove("消费者1号");
       int item;

    do {
        while (full <= 0)
        {
           // cout << "Consumer is waiting for items..." << endl;
        }
        full--;

        mu.lock();
        if(rear != -1)
       item = buffer[rear--];    //从缓冲区取出产品
        cout << "消费者2号" << "消费的数为:" << item << endl;
        display();
        mu.unlock();            //V(mutex)
        empty++;             //V(empty)
        break;

    } while (1);
        Sleep(e);
    }
}

void consumer3()
{
    //for (int i = 0; i < 20; i++)
 while(1)
    {
        int e = rand() % 2000 ;
       // p->remove("消费者1号");
       int item;

    do {
        while (full <= 0)
        {
           // cout << "Consumer is waiting for items..." << endl;
        }
        full--;

        mu.lock();
        if(rear != -1)
       item = buffer[rear--];    //从缓冲区取出产品
        cout << "消费者3号" << "消费的数为:" << item << endl;
        display();
        mu.unlock();            //V(mutex)
        empty++;             //V(empty)
        break;

    } while (1);
        Sleep(e);
    }
}

int main()
{
    init();
    thread pro(producer);    //创建生产者子线程
    thread con1(consumer1);    //创建消费者子线程
    thread con2(consumer2);    //创建消费者子线程
    thread con3(consumer3);
    pro.join();                  //阻塞主线程
    con1.join();
    con2.join();
    con3.join();
    cout << "结束!" << endl;
    return 0;
}

 

 

以上的例子可以先通过链接:https://mbd.baidu.com/ma/s/DhKQhJ7Q 进行学习,生产者消费者的问题其实很好理解,主要是代码实现不太容易。

上面链接主要写了如何创建线程,join和detach,传递参数,获取id和休眠,结束线程,并发访问,线程同步等,还有具体的例子。我觉得看完之后完全可以自己动手实现生产者――消费者问题算法。

下面是我补充的链接没有但是用的的知识。

(1)头文件的#include<mutex>

mutex互斥量是一个类,这个类有有一个lock()方法,和一个unlock()方法。 如果第一次运行了lock()这个方法,而没有运行unlock()这个方法,第二次再运行lock()这个方法时,程序就会卡停在这里,只有当运行了unlock()这个方法运行后,第二个lock()方法才会运行通过。就是运用这种“锁”的机制就可以保证两段代码独立运行。

(2) rand() % 100 + 1;

1到100的随机数,具体学习可以看https://www.bilibili.com/video/BV1et411b73Z?p=32

我上面所写的和书上的有所不同,这里用到的是栈,每次从最后一位存取。而书上用的是循环队列,感兴趣的小伙伴可以自己试试修改一下。

3.银行家算法的实现

#include<iostream>

using namespace std;

#define P 5  //进程数
#define R 3  //资源种类
int maxs[P][R] = {{7,5,3},{3,2,2},{9,0,2},{2,2,2},{4,3,3}};
int allocation[P][R] = {{0,1,0},{2,0,0},{3,0,2},{2,1,1},{0,0,2}}; //分配矩阵
int need[P][R] = {{7,4,3},{1,2,2},{6,0,0},{0,1,1},{4,3,1}};   //需求矩阵
int available[R] = {3,3,2}; //可用资源向量
int request[R];   //请求向量当前进程对各类资源的申请量,算法的入口参数
bool Finish[P];
int safeSeries[P]={0,0,0,0,0};//安全进程序列号
int num;

void showInfo()
{
	cout <<"\n------------------------------------------------------------------------------------\n" ;
	cout <<"当前系统各类资源剩余:";
    for(int j = 0; j < R; j++)
	{
        cout <<available[j] << " ";
    }
    cout <<"\n\n当前系统资源情况:\n";
    cout <<" PID\t Max\t\tAllocation\t Need\n";
    for(int i = 0; i < P; i++)
	{
       cout << "P" << i << "\t";
        for(int j = 0; j < R; j++)
		{
            cout <<maxs[i][j] << " ";
        }
        cout <<"\t\t";
        for(int j = 0; j < R; j++)
		{
           cout <<allocation[i][j] << " ";
        }
       cout <<"\t\t";
        for(int j = 0; j < R; j++)
		{
            cout <<need[i][j] << " ";
        }
        cout <<"\n";
    }
}

//打印安全检查信息
void SafeInfo(int *work, int i)
{
    int j;
    cout << "P" << i<< "\t";
    //打印工作向量work
    for(j = 0; j < R; j++)
        cout <<work[j]<<" ";
    cout <<"\t\t";

    //打印需求矩阵need
    for(j = 0; j < R; j++)
        cout <<need[i][j]<<" ";;
   cout <<"\t\t";

    //打印可分配矩阵allocation
    for(j = 0; j < R; j++)
       cout <<allocation[i][j]<<" ";;
	cout <<"\t\t";

    //打印work + allocation
    for(j = 0; j < R; j++)
        cout <<allocation[i][j]+work[j]<<" ";;
    cout <<"\n";
}


//判断一个进程的所需资源是否全为零
bool isAllZero(int kang)
{
	num = 0;
	for(int i = 0; i < R; i++ )
		if(need[kang][i] == 0)
			num ++;

	if(num == R)
		return true;
	else
		return false;
}

//安全检查
bool isSafe()
{
	bool flag = true;
	int safeIndex = 0;	//安全进程个数
	int allFinish = 0;	//可需资源为0的进程数
	//工作变量work:系统可提供给进程继续运行所需的各类资源数目
    int work[R] = {0};
	int r = 0;	//进程序号
	int temp = 0;	//辅助判断所有进程是否全部分配完成

	//预分配为了保护available
    for(int i = 0; i < R; i++)
        work[i] = available[i];

	//把未完成进程置为false
    for(int i = 0; i < P; i++)
	{
		bool result = isAllZero(i);
		if(result == true)
		{
			Finish[i] = true;
			allFinish++;
		}
		else
			Finish[i] = false;
    }
	//预分配开始
    while(allFinish != P)
	{
		num = 0;
		//检测进程所需资源是否符合剩余资源
        for(int i = 0; i < R; i++)
			if(need[r][i] <= work[i] && Finish[r] == false)
				num ++;

		//符合
		if(num == R)
		{
			if(flag)
			{
				flag = false;
				cout << "\n系统安全情况分析:\n";
				cout <<" PID\t Work\t\t Need\t \tAllocation\tWork+Allocation\n";
			}
			SafeInfo(work,r);
			//释放资源
			for(int i = 0; i < R; i++ )
				work[i] = work[i] + allocation[r][i];

			allFinish ++;
			safeSeries[safeIndex] = r;
			safeIndex ++;
			Finish[r] = true;
		}
		r ++;
		if(r >= P)
		{
			r = r % P;
			if(temp == allFinish)
				break;
			temp = allFinish;
		}
    }
	//判断系统是否安全
	for(int i = 0; i < P; i++)
	{
		if(Finish[i] == false)
		{
			cout <<"\n当前系统不安全!\n\n";
			return false;
		}
	}
	//打印安全序列
	cout <<"\n当前系统安全!\n\n安全序列为:";

	//打印安全序列
	for(int i = 0; i < allFinish; i++)
		cout <<safeSeries[i];
    return true;
}


int main()
{
    //输入的进程序号
    int curProcess = 0;
    //用于控制输入内容的准确性(非字符)
	int a = -1;
    showInfo();
	bool isStart = isSafe();
	//用户输入或者预设系统资源分配合理才能继续进行进程分配工作
    while(isStart)
	{
		//限制用户输入,以防用户输入大于进程数量的数字,以及输入其他字符(乱输是不允许的)
      	do
		{
			if(curProcess >= P || a < 0)
			{
				cout <<"\n请不要输入超出进程数量的值或者其他字符:\n";
				while(getchar() != '\n');//清空缓冲区
				a = -1;
			}
			cout <<"\n------------------------------------------------------------------------------------\n";
			cout <<"\n输入要分配的进程:";
			cin >> curProcess;
			a = curProcess;
			cout <<"\n";

		}while(curProcess >= P || a < 0);

		//限制用户输入,此处只接受数字,以防用户输入其他字符(乱输是不允许的)
		for(int i = 0; i < R; i++)
		{
			do
			{
				if(a < 0 )
				{
					cout << "\n请不要输入除数字以外的其他字符,请重新输入:\n";
					while(getchar() != '\n');//清空缓冲区
					a = -1;
				}
				cout <<"请输入要分配给进程 P" << curProcess << "的第 "<< i +1 << "类资源:";
				cin >> request[i];
				a = request[i];
			}while( a < 0);
		}

		//判断用户输入的分配是否合理,如果合理,开始进行预分配
		num  = 0;
        for(int i = 0; i < R; i++)
		{
            if(request[i] <= need[curProcess][i] && request[i] <= available[i])
				num ++;
            else
			{
				cout << "\n发生错误!可能原因如下:\n(1)您请求分配的资源可能大于该进程的某些资源的最大需要!\n(2)系统所剩的资源已经不足了!\n";
				break;
			}
        }

        //合理
        if(num == R)
		{
			num = 0;
            for(int j = 0; j < R; j++)
			{
				//分配资源
                available[j] = available[j] - request[j];
                allocation[curProcess][j] = allocation[curProcess][j] + request[j];
                need[curProcess][j] = need[curProcess][j] - request[j];
				//记录分配以后,是否该进程需要值为0了
				if(need[curProcess][j] == 0)
					num ++;
            }
			//如果分配以后出现该进程对所有资源的需求为0了,即刻释放该进程占用资源(视为完成)
			if(num == R)
			{
				//释放已完成资源
				for(int i = 0; i < R; i++ )
					available[i] = available[i] + allocation[curProcess][i];
				cout << "\n\n本次分配进程 P" << curProcess<< "完成,该进程占用资源全部释放完毕!\n";
			}
			else
				//资源分配可以不用一次性满足进程需求
				cout << "\n\n本次分配进程 P" << curProcess << "未完成!\n";

			showInfo();

			//预分配完成以后,判断该系统是否安全,若安全,则可继续进行分配,若不安全,将已经分配的资源换回来
            if(!isSafe())
			{
				for(int j = 0; j < R; j++)
				{
					available[j] = available[j] + request[j];
					allocation[curProcess][j] = allocation[curProcess][j] - request[j];
					need[curProcess][j] = need[curProcess][j] +request[j];
				}
				cout <<"资源不足,等待中...\n\n分配失败!\n";
            }
        }
    }

}

 

 

 银行家算法主要的原理也不是很难,书上也有给出银行家算法中的数据结构,银行家算法,安全性算法。认真阅读书本上的内容再结合代码就很容易理解。

最后,希望这篇文章能够对你们有帮助!

  • 6
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值