DDD操作系统实验(七)最终版

实验目的

  1. 理解死锁产生原因,避免死锁与预防死锁的方法
  2. 能够编写代码实现银行家算法以避免死锁。

实验内容

学习课本上关于银行家算法的流程描述,明确每个步骤的含义,完成下面习题(如下英文所示)。要求:

  1. 以书上或者老师PPT的例子为例,可以input.txt文件形式,也可以手动输入的形式,依次读入进程数,资源数和实例数,分配矩阵,最大需求矩阵和可用资源向量。注意下面标黄色的英语。

  2. 输出可能的安全序列。

  3. 鼓励同学自己实现,实在有困难,可参考附件代码。

    Write a multithreaded program that implements the banker’s algorithm. Create n threads that request and release resources from the bank. The banker will grant the request only if it leaves the system in a safe state. You should write this program using Pthreads.

    It is important that access to shared data is safe from concurrent access. Such data can be safely accessed using mutex locks, which are available in Pthread API.

实验准备

实验前请学习课本关于银行家算法的描述,明确求取安全序列的步骤。

实验要求

实现平台:ubuntu
完成程序后,填写本报告,并贴出结果、给出分析。实验报告与代码一起打包上传。
另外,如果你使用了参考代码,则需要通过在代码旁添加注释等多种方式体现你对代码的理解。(其实不用)

实验结果与分析

实验结果

与课本给出的实例对照,验证是否正确实现
在这里插入图片描述
在这里插入图片描述

结果分析

  • 首先由用户输入数据(这里用input.txt代替),分别对可利用资源向量矩阵AVAILABLE、最大需求矩阵MAX、分配矩阵ALLOCATION,并计算出需求矩阵
  • 在避免死锁的方法中,所施加的限制条件较弱,有可能获得令人满意的系统性能。在该方法中把系统的状态分为安全状态和不安全状态,只要能使系统始终都处于安全状态,便可以避免发生死锁。
  • 对于进程提出的请求REQUEST,如果小于NEED,则再判断是否小于AVALIABLE,再进行修改 AVALIABLE=AVALIABLE-REQUEST,ALLOCATION=REQUEST,NEED=NEED-REQUEST,否则任意一步均会出错

附上测试文件与代码

input.txt

5 3
0 1 0
2 0 0
3 0 2
2 1 1
0 0 2
7 5 3
3 2 2
9 0 2
2 2 2
4 3 3
3 3 2
1
1 0 2

ddd提供的残缺代码

#include <pthread.h>
#include <stdio.h>

/**********************************************************************************
银行家算法是用于避免死锁的,本次实验,我们要模拟出这样的一种有可能产生死锁的情形:
系统中目前有很多线程,每个线程都有自己的最大资源需求、也已经分配了一些资源、还需要一些资源。
在这种情形下,系统容易发生死锁(原因思考下)。
然后,我们使用银行家算法来找到这些线程的一种可能的执行顺序,保证不会发生死锁。
************************************************************************************/


/*********************************************************************************
下列代码的各种矩阵是用手动输入的方式,建议同学们改成读文件的方式,这样方便调试
**********************************************************************************/


void *start_banker(void *param);

#define MAX_PRO 256   /* max process count */
#define MAX_RES 256	/* max resource type */

int available[MAX_RES];
int max[MAX_PRO][MAX_RES];
int allocation[MAX_PRO][MAX_RES];
int need[MAX_PRO][MAX_RES];
int request[MAX_RES];
int work[MAX_RES];
int finish[MAX_PRO];
int stop_flag = 0;
int m,n;
pthread_mutex_t mutex;
int proc_ids[MAX_PRO];

int main(int argc, char *argv[]){
	pthread_t tid[MAX_PRO];
	pthread_attr_t attr[MAX_PRO];

	int id;
	int i,j;
  //输入当前系统中有几个并发的线程
	printf ("please input the process count(<=%d).\n",MAX_PRO);
	scanf("%d", &n);
  //输入当前系统中有几种资源
	printf ("please input the resource type count(<=%d).\n",MAX_RES);
	scanf("%d", &m);
	
	if (m>256 || n>256 || m<0 || n<0)
	{
		printf ("input error\n");
		return -1;
	}
	//输入已经分配的资源矩阵
	printf ("please input allocation matrix\n");
	for (i=0;i<n;i++)
		for (j=0;j<m;j++)
			scanf("%d", &allocation[i][j]);
			
	//输入最大资源需求矩阵
	printf ("please input max matrix\n");
	for (i=0;i<n;i++)
		for (j=0;j<m;j++)
			scanf("%d", &max[i][j]);

  //输入当前系统中还可得的资源向量
	printf ("please input available vector\n");
	for (j=0;j<m;j++)
		scanf("%d", &available[j]);

	for (i=0;i<n;i++)
		for (j=0;j<m;j++)
			/****************** get the need matrix here ************************/	
      //在这里计算下need矩阵

  //当前某个线程又发出了新的请求,还记得上课讲的发出新请求的银行家算法吗?
  //输入是哪个线程,请求了多少资源
	printf ("please input the process No. that request new resources\n");
	scanf("%d", &id);

	printf ("please input the request vector\n");
	for (j=0;j<m;j++)
		scanf("%d", &request[j]);

	
	printf ("#########################################\n");
	printf ("Allocation Matrix\n");
	for (i=0;i<n;i++){
		printf ("P%d\t\t",i);
		for (j=0;j<m;j++)
			printf ("%d\t",allocation[i][j]); 
		printf ("\n");
	}

	printf ("Max Matrix\n");
	for (i=0;i<n;i++){
		printf ("P%d\t\t",i);
		for (j=0;j<m;j++)
			printf ("%d\t",max[i][j]); 
		printf ("\n");
	}

	printf ("Available Vector\n");
	for (j=0;j<m;j++)
		printf ("%d\t",available[j]);
	printf ("\n");

	printf ("with additional resouces requests\nP%d\t\t",id);
	for (j=0;j<m;j++)
		printf ("%d\t", request[j]);
	printf ("\n");

	for (j=0;j<m;j++){
		/************** a new request, available matrix should be modified **********************/
		//既然某个线程发出了新的请求,相应的available矩阵、allocation矩阵、need矩阵是不是都要修改?
	  //是不是直接修改它们就可以了?需要额外判断什么?
	  
		
		if (available[j]<0){
			printf ("unsafe!\n");
			return 0;
		}
		
		
		/************** a new request, allocation and need matrix should be modified ******************/
		
		
		
	}
	
  //n表示线程数目,一开始,每个线程都标记成未完成,finish[i] = 0;
	for (i=0;i<n;i++)
		finish[i] = 0;
	//m表示资源种类数目,例如有ABC三类资源,那么m=2
	//开始时,把available赋值给work。
	for (j=0;j<m;j++)
		work[j] = available[j];
   
  //pay attention to the thread mutual exclusion
	printf ("start...\n");
	for (i=0;i<n;i++){
		proc_ids[i] = i;
		/******************** init and creat threads here, which will implement start_banker with parameter "process id" *********/
		//我们开始创建n个线程,想想怎么创建线程?第4章我们是不是实践过了?需要哪几个函数?
		//创建出来的线程就去执行start_banker
		
		
	}
	sleep(1);
	for (i=0;i<n;i++){
		if (finish[i]==0){//最后,只要发现有一个线程的finish=0,就说明没找到机会给该线程分配资源,系统就是不安全的,有可能死锁
			printf ("unsafe!!\n");
			break;
		}
	}
	if (i==n)
		printf ("safe!!\n");
	stop_flag = 1;
	printf ("Finish...\n");
	sleep(1);
	for (i=0;i<n;i++)
		/******************** use XX function here to wait the threads to finish **********************/
		//既然创建出来线程,那我们就要等待线程结束,想想用什么函数等待线程结束?
		
		
		
	return 0;
}

void *start_banker(void *param){
	int j;
	int id = *(int *)param; //process id
	
	while (!stop_flag && !finish[id]) {
		for (j=0;j<m;j++){
			if (need[id][j]> ?? /************* fill the condition to break ***********/) //对于id这个线程,它需要的某资源数目怎么样,就不需要继续执行了,这个线程现在肯定不能执行,need>work
				break;
		}
		//如果每个种类的资源都比较了一遍,发现都不break,那就说明对该线程的每个种类的资源need<work,那么这个线程可以执行。
		if (j==m) // need <= work{
			/******************** fill the code here to calculate work matrix and set finish value *******************/
			//这个线程执行完毕了,要修改哪个矩阵?work矩阵要修改,因为该线程执行完毕,会释放它的allocation
			//这个线程执行完毕了,还要记得把这个线程的finish标记下,说明它做完了,下次不要检查它了。
			//完成了上面的work和finish,我们再思考一下,如果现在有好几个线程都满足j==m这个条件,都能进到这个if语句里,那么他们是不是会一起修改work与finish呢?多个线程并发访问共享变量会有什么问题?怎么解决?
			
			
			
			
			printf ("P%d finished\n",id);
			
		}
	}
	pthread_exit(0);
}

填充完整的代码

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
/**********************************************************************************
银行家算法是用于避免死锁的,本次实验,我们要模拟出这样的一种有可能产生死锁的情形:
系统中目前有很多线程,每个线程都有自己的最大资源需求、也已经分配了一些资源、还需要一些资源。
在这种情形下,系统容易发生死锁(原因思考下)。
然后,我们使用银行家算法来找到这些线程的一种可能的执行顺序,保证不会发生死锁。
************************************************************************************/


/*********************************************************************************
下列代码的各种矩阵是用手动输入的方式,建议同学们改成读文件的方式,这样方便调试
**********************************************************************************/	
void *start_banker(void *param);
#define MAX_PRO 256   /* max process count */
#define MAX_RES 256	/* max resource type */

int available[MAX_RES];
int max[MAX_PRO][MAX_RES];
int allocation[MAX_PRO][MAX_RES];
int need[MAX_PRO][MAX_RES];
int request[MAX_RES];
int work[MAX_RES];
int finish[MAX_PRO];
int stop_flag = 0;
int m,n;
pthread_mutex_t mutex;
int proc_ids[MAX_PRO];

int main(int argc, char *argv[]){
	pthread_t tid[MAX_PRO];
	pthread_attr_t attr[MAX_PRO];

	int id;
	int i,j;

    FILE *input = fopen("input.txt","r");
    // scanf("%d", &n);
	// scanf("%d", &m);
    fscanf(input,"%d", &n);
    fscanf(input,"%d", &m);

	if (m>256 || n>256 || m<0 || n<0){
		printf ("input error\n");
		return -1;
	}
	printf ("please input allocation matrix\n");
	for (i=0;i<n;i++)
		for (j=0;j<m;j++)
			// scanf("%d", &allocation[i][j]);
			fscanf(input,"%d",&allocation[i][j]);
		
	printf ("please input max matrix\n");
	for (i=0;i<n;i++)
		for (j=0;j<m;j++)
			// scanf("%d", &max[i][j]);
			fscanf(input,"%d",&max[i][j]);

	printf ("please input available vector\n");
	for (j=0;j<m;j++)
		// scanf("%d", &available[j]);
		fscanf(input,"%d",&available[j]);

	for (i=0;i<n;i++)
		for (j=0;j<m;j++)
			need[i][j] = max[i][j] - allocation[i][j];
			
	printf ("please input the process No. that request new resources\n");
	fscanf(input, "%d", &id);

	printf ("please input the request vector\n");
	for (j=0;j<m;j++)
		fscanf(input, "%d", &request[j]);

	
	printf ("#########################################\n");
	printf ("Allocation Matrix\n");
	for (i=0;i<n;i++){
		printf ("P%d\t\t",i);
		for (j=0;j<m;j++)
			printf ("%d\t",allocation[i][j]); 
		printf ("\n");
	}

	printf ("Max Matrix\n");
	for (i=0;i<n;i++){
		printf ("P%d\t\t",i);
		for (j=0;j<m;j++)
			printf ("%d\t",max[i][j]); 
		printf ("\n");
	}

	printf ("Available Vector\n");
	for (j=0;j<m;j++)
		printf ("%d\t",available[j]);
	printf ("\n");

	printf ("with additional resouces requests\nP%d\t\t",id);
	for (j=0;j<m;j++)
		printf ("%d\t", request[j]);
	printf ("\n");

	for (j=0;j<m;j++){
		if(request[j] > need[id][j]){
			printf("unsafe!\n");
			return 0;
		}
		available[j] -= request[j];
		if (available[j]<0)
		{
			printf ("unsafe!\n");
			return 0;
		}
		allocation[id][j] += request[j];
		need[id][j] -= request[j];
	}
	
	for (i=0;i<n;i++)
		finish[i] = 0;
	for (j=0;j<m;j++)
		work[j] = available[j];
		
	printf ("start...\n");
	for (i=0;i<n;i++){
		proc_ids[i] = i;
		pthread_attr_init(&attr[i]);
        pthread_create(&tid[i], &attr[i], start_banker, (void*)&proc_ids[i]);
	}
	sleep(1);
	for (i=0;i<n;i++){
		if (finish[i]==0)
		{
			printf ("unsafe!!\n");
			break;
		}
	}
	if (i==n)
		printf ("safe!!\n");
	stop_flag = 1;
	printf ("Finish...\n");
	sleep(1);
	for (i=0;i<n;i++)
		pthread_join(tid[i],NULL);
	return 0;
}

void *start_banker(void *param){
	int j;
	int id = *(int *)param; //process id
	
	while (!stop_flag && !finish[id]) {
		for (j=0;j<m;j++){
			if (need[id][j]> work[j])
				break;
		}
		if (j==m){ // need <= work{
			pthread_mutex_lock(&mutex);
            for (j=0;j<m;j++)
                work[j] += allocation[id][j];
            pthread_mutex_unlock(&mutex);
            finish[id] = 1;
			printf ("P%d finished\n",id);
		}
	}
	pthread_exit(0);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值