模拟多进程-生产者消费者具体实现代码

/* DEFINITION.h */

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<ctype.h>
#include<malloc.h> 	/* malloc()等 */
#include<limits.h> 	/* INT_MAX等 */
#include<stdio.h> 	/* EOF(=^Z或F6),NULL */
#include<stdlib.h> 	/* atoi() */
#include<io.h> 		/* eof() */
#include<math.h> 	/* floor(),ceil(),abs() */
#include<process.h> /* exit() */
#include<time.h>	
 
#define BUF 3  		// 缓存的大小
#define MAX 30  	// 最大可以输入的字符
#define MMAX 256	// 默认内存大小

typedef struct PCB {
	char name[10];      // 进程名
	int PID;			// 进程PID 
	char state[10];    	// 运行状态
	int arrive_time;	// 到达时间
	int priority;		// 优先级
	int start_time;		// 实际到达时间
	int running_time;	// 运行时间 
	int end_time;		// 结束时间
	int copy_run_time;	// 用于时间片轮转
	int zztime;			// 周转时间 
	double dqzztime;	// 带权周转时间 
	char reason[10];    // 若阻塞,其原因
	int Address;		// 内存的位置

	int breakp;         // 断点保护
	int break_time;		// 断点时间

	int flag;			// 0为生产者,1为消费者 
	struct PCB* next;   // 阻塞时的顺序
}PCB, Process;

typedef struct semaphore
{
	char name[10];
	int num;
	int flag;			// 0为empty, 1为filled,2为rw_mux 
}Semaphore;

typedef struct PCBQueue
{
	PCB* first_pro;
	PCB* last_pro;
	int size;
}PCBQueue;

extern Semaphore* empty, * filled, * rw_mux;	// 初始化信号量 
extern int PRODUCT;								// 生产者数量
extern int CONSUME; 							// 消费者数量
extern PCB pro[MAX];							// 生产者进程 + 消费者进程 
extern int PROCESS; 							// 进程最大并行数量 
extern char str[MAX]; 							// 输入的字符串
extern char buffer[BUF]; 						// 缓冲池
extern int mem;									// 内存
extern int tp_mem;								// 临时内存
extern int* m;									// 内存数组
extern int len; 								// 输入长度
extern int sp; 									// string的指针
extern int in; 									// 生产者指针
extern int out; 								// 消费者指针
extern char temp; 								// 供打印的临时产品
extern char rec_p[MAX];							// 生产记录
extern int p_f;									// 生产记录头指针
extern int p_l;									// 生产记录尾指针
extern char rec_c[MAX];							// 消费记录
extern int c_f;									// 消费记录头指针
extern int c_l;									// 消费记录尾指针
extern PCBQueue* ready_queue;					// 就绪队列 
extern PCBQueue* block_queue;					// 阻塞队列 
extern PCBQueue* product_block_queue;			// 生产者阻塞队列 
extern PCBQueue* consume_block_queue;			// 消费者阻塞队列 
extern PCBQueue* run_queue;						// 运行队列 
extern int pc;									// 程序计数器
extern int count;								// 字符计数器
extern int con_cnt;								// 消费计数器
extern int tp_time;								// 计时 
extern int alo;									// 选择算法的标记:1为FCFS,2为短进程,3为优先级,4为时间片,5为高响应比


void QueueInit(PCBQueue* q);			// 初始化就绪队列
void SemaphoreInit();					// 初始化信号量 
void setMem();							// 初始化内存
void CopyProcess(PCB* pro1, PCB* pro2);	// 将进程pro2的信息复制到进程pro1中
void Init();							// 初始化  
int memBlock(PCB* p);					// 内存是否有足够空间
void memClear(PCB* p);					// 内存中清除指定进程
void EnQueue(PCBQueue* q, PCB* p);		// 插入队列 
void Clean_Queue(PCBQueue* q);			// 清空队列
void ReorderQueue(PCBQueue* q);			// 重排队列
int BlockProCount();					// 阻塞进程计数
PCB* DeQueue(PCBQueue* q);				// 输出队列
void P(Semaphore* mux, PCB* p);     	// P操作
void V(Semaphore* mux, PCB* p);    		// V操作
void Block(Semaphore* mux, PCB* p);		// 阻塞函数
void Wakeup(Semaphore* mux, PCB* p);	// 唤醒函数
void Control();   						// 处理机调度
void Processor(PCB* p);					// 处理机执行
void Print(PCB* p);  					// 打印函数
void CloseProcess();					// 关闭剩余进程
void DestroyQueue(PCBQueue* q);			// 释放队列
void Destroymaphore(Semaphore* mux);	// 释放信号量 
void memClose();						// 内存清空
void Close();							// 释放内存
// 调度算法 
void FCFS(PCB** arr, int n);			// 先进先出调度算法 
void SPF(PCB** arr, int n);				// 非抢占式短进程优先调度算法
void PRIORITY(PCB** arr, int n);		// 静态优先级调度算法
void HRRN(PCB** arr, int n);			// 高响应比优先调度算法
void Alogorithm();						// 算法

/* Global.c */

#include"DEFINITION.h"

Semaphore* empty, * filled, * rw_mux;	// 初始化信号量 
int PRODUCT = 2;						// 生产者数量
int CONSUME = 3; 						// 消费者数量
PCB pro[MAX];							// 生产者进程 + 消费者进程 
int PROCESS = 2; 						// 进程最大并行数量
char str[MAX]; 							// 输入的字符串
char buffer[BUF]; 						// 缓冲池
int mem = MMAX;							// 内存
int tp_mem;								// 临时内存
int* m;									// 内存数组
int len; 								// 输入长度
int sp = 0; 							// string的指针
int in = 0; 							// 缓冲区的生产者指针
int out = 0; 							// 缓冲区的消费者指针
char temp; 								// 供打印的临时产品
char rec_p[MAX];						// 生产记录
int p_f = 0;							// 生产记录头指针
int p_l = 0;							// 生产记录尾指针
char rec_c[MAX];						// 消费记录
int c_f = 0;							// 消费记录头指针
int c_l = 0;							// 消费记录尾指针
PCBQueue* ready_queue;					// 就绪队列 
PCBQueue* block_queue;					// 阻塞队列 
PCBQueue* product_block_queue;			// 生产者阻塞队列 
PCBQueue* consume_block_queue;			// 消费者阻塞队列 
PCBQueue* run_queue;					// 运行队列 
int pc;									// 程序计数器
int count;								// 字符计数器
int con_cnt;							// 消费计数器
int tp_time = 0;						// 计时 
int alo;								// 选择算法的标记:1为FCFS,2为短进程,3为优先级,4为时间片,5为高响应比

/*  Queue.c */

#include"DEFINITION.h"

// 插入队列
void EnQueue(PCBQueue* q, PCB* p)
{
	if (NULL == q)
	{
		return;
	}
	PCB* tp = q->first_pro->next;
	// 避免插入相同值
	for (int i = 0; i < q->size && tp != NULL; i++)
	{
		if (tp->flag == p->flag && tp->PID == p->PID)
		{
			return;
		}
	}

	q->last_pro->next = (PCB*)malloc(sizeof(PCB));
	q->last_pro = q->last_pro->next;
	CopyProcess(q->last_pro, p);
	q->last_pro->next = NULL;

	q->size++;
}

// 清空队列
void Clean_Queue(PCBQueue* q)
{
	if (NULL == q)
	{
		return;
	}

	for (PCB* tpp = DeQueue(q); tpp != NULL; tpp = DeQueue(q)) {};
}

// 重排队列
void ReorderQueue(PCBQueue* q)
{
	if (NULL == q)
	{
		return;
	}
	
	int n = q->size;

	if (n != 0)
	{
		PCB* tp_p;			// 临时PCB
		PCB* tp_arr[MAX];	// 临时PCB数组

		tp_p = q->first_pro->next;
		for (int i = 0; i < n; i++)
		{
			tp_arr[i] = DeQueue(q, tp_p);
		}

		switch (alo)
		{
		case 1:
			printf("按FCFS调度算法重新排序!\n");
			FCFS(tp_arr, n);
			break;
		case 2:
			printf("按SPF调度算法重新排序!\n");
			SPF(tp_arr, n);
			break;
		case 3:
			printf("按PRIORITY调度算法重新排序!\n");
			PRIORITY(tp_arr, n);
			break;
		case 4:
			printf("按HRRN调度算法重新排序!\n");
			HRRN(tp_arr, n);
			break;
		default:
			printf("按FCFS调度算法重新排序!\n");
			FCFS(tp_arr, n);
			break;
		}

		for (int i = 0; i < n; i++)
		{
			EnQueue(q, tp_arr[i]);
		}
	}
}

// 输出队列
PCB* DeQueue(PCBQueue* q)
{
	if (NULL == q || NULL == q->first_pro->next)
	{
		return NULL;
	}

	PCB* tp;
	tp = q->first_pro->next;

	if (tp == q->last_pro)
	{
		q->first_pro->next = NULL;
		q->last_pro = q->first_pro;

		q->size--;
		return tp;
	}
	q->first_pro->next = q->first_pro->next->next;
	q->size--;

	return tp;
}

// 找到指定进程并删除
void Look_DeQueue(PCBQueue* q, PCB* p)
{
	if (NULL == q || NULL == p)
	{
		return;
	}

	PCB* tp = q->first_pro;
	PCB* ttp = tp->next;
	while (ttp != NULL)
	{
		if (ttp->PID == p->PID && ttp->flag == p->flag)
		{
			// 删除指定结点时,需要注意最后一个结点 
			if (ttp == q->last_pro)
			{
				q->last_pro = tp;
				q->last_pro->next = NULL;
				q->size--;
				break;
			}
			tp->next = ttp->next;
			q->size--;
			break;
		}
		tp = ttp;
		ttp = ttp->next;
	}
}

int BlockProCount()
{
	int n = 0;
	n = block_queue->size + product_block_queue->size + consume_block_queue;

	return n;
}

/*  Init.c */

#include"DEFINITION.h"

// 初始化就绪、阻塞、运行队列
void QueueInit(PCBQueue** q)
{
	*q = (PCBQueue*)malloc(sizeof(PCBQueue));
	(*q)->first_pro = (PCB*)malloc(sizeof(PCB));
	(*q)->first_pro->next = NULL;
	(*q)->last_pro = (*q)->first_pro;
	(*q)->size = 0;
}

// 初始化信号量 
void SemaphoreInit()
{
	empty = (Semaphore*)malloc(sizeof(Semaphore));
	filled = (Semaphore*)malloc(sizeof(Semaphore));
	rw_mux = (Semaphore*)malloc(sizeof(Semaphore));

	strcpy(empty->name, "empty");
	empty->num = BUF;
	empty->flag = 0;

	strcpy(filled->name, "filled");
	filled->num = 0;
	filled->flag = 1;

	strcpy(rw_mux->name, "rw_mux");
	rw_mux->num = 1;
	rw_mux->flag = 2;
}

// 将进程pro2的信息复制到进程pro1中
void CopyProcess(PCB* pro1, PCB* pro2)
{
	memcpy(pro1->name, pro2->name, sizeof(pro2->name));
	//strcpy(pro1->name, pro2->name);
	pro1->PID = pro2->PID;
	memcpy(pro1->state, pro2->state, sizeof(pro2->state));
	//strcpy(pro1->state, pro2->state);
	memcpy(pro1->reason, pro2->reason, sizeof(pro2->reason));
	//strcpy(pro1->reason, pro2->reason);
	pro1->Address = pro2->Address;
	pro1->breakp = pro2->breakp;
	pro1->flag = pro2->flag;
	pro1->priority = pro2->priority;
	pro1->arrive_time = pro2->arrive_time;
	pro1->start_time = pro2->start_time;
	pro1->running_time = pro2->running_time;
	pro1->end_time = pro2->end_time;
	pro1->copy_run_time = pro2->copy_run_time;
	pro1->next = pro2->next;
	pro1->zztime = pro2->zztime;
	pro1->dqzztime = pro2->dqzztime;
	pro1->break_time = pro2->break_time;
}

// 初始化 
void Init()
{
	// 初始化四个队列
	QueueInit(&ready_queue);
	QueueInit(&block_queue);
	QueueInit(&product_block_queue);
	QueueInit(&consume_block_queue);
	QueueInit(&run_queue);

	// 初始化信号量 
	SemaphoreInit();

	// 内存初始化
	setMem();

	printf("请输入生产者个数: ");
	scanf("%d", &PRODUCT);
	printf("请输入消费者数量个数: ");
	scanf("%d", &CONSUME);
	/*printf("请输入进程最大并行数量(<=3): ");
	scanf("%d", &PROCESS);*/

	// 初始化生产者进程 
	for (int i = 0; i < PRODUCT; i++)
	{
		strcpy(pro[i].name, "Producer");
		pro[i].PID = i + 1;
		strcpy(pro[i].state, "Ready");
		strcpy(pro[i].reason, "Null");
		pro[i].start_time = 0;
		pro[i].end_time = 0;
		pro[i].zztime = -1;
		pro[i].breakp = 0;
		pro[i].next = NULL;
		pro[i].flag = 0;
		pro[i].Address = -1;
	}
	// 初始化消费者进程 
	for (int i = PRODUCT; i < PRODUCT + CONSUME; i++)
	{
		strcpy(pro[i].name, "Consume");
		pro[i].PID = i + 1;
		strcpy(pro[i].state, "Ready");
		strcpy(pro[i].reason, "Null");
		pro[i].start_time = 0;
		pro[i].end_time = 0;
		pro[i].zztime = -1;
		pro[i].breakp = 0;
		pro[i].next = NULL;
		pro[i].flag = 1;
		pro[i].Address = -1;
	}

	// 用户输入进程到达时间 
	printf("请依次输入进程的:到达时间\t运行时间\t优先级\n");
	for (int i = 0; i < PRODUCT + CONSUME; i++)
	{
		printf("%s %d\t  ", pro[i].name, pro[i].PID);
		if (scanf("%d %d %d", &pro[i].arrive_time, &pro[i].running_time, &pro[i].priority) != 3)
		{
			printf("输入错误,请重新输入正确的整数值。\n");
		}
		pro[i].start_time = pro[i].arrive_time;

		EnQueue(ready_queue, &pro[i]);
	}

	// 就绪队列重新排序 
	Alogorithm();

	pc = 0;
	con_cnt = 0; //消费计数器
}

/*  Main.c */



/*
	用户输入到达时间, 运行时间, 优先级
	进程记录 到达时间,中断时的时间与断点
	CPU记录pc、控制进程阻塞与运行
	引用 时间概念 来实现 模拟多进程运行

	设定:每两秒完成一道小步骤(PV操作不算) ,故而实际运行时间固定为 8s

	注意:进入队列的进程均为复制品,不能为本体,所以需要实时更新实体信息
*/



#include"DEFINITION.h"

void Print() 
{
	printf("————————生产者消费者模拟———————\n");
	printf("* 模拟过程的字符串为:\t");
	printf("%s\n", &str);

	printf("* 已生产:");
	for (int j = p_f; j <= p_l; j++)
		printf("%c", rec_p[j]);
	printf("\n* 空缓存:");
	for (int j = out; j != in; j = (j + 1) % BUF)
		printf("%c", buffer[j]);
	printf("\n* 已消费:");
	for (int j = 0; j <= c_l; j++)
		printf("%c", rec_c[j]);

	printf("\n———————进程控制块的信息————————\n");
	printf("进程名\t\t状态\t开始时间\t运行时间\t高响应比\t优先级\t等待原因\t断点\n");
	for (int i = 0; i < PRODUCT + CONSUME; i++)
	{
		if (pro[i].flag == 0)
			printf("生产者%d\t\t%s\t%7d\t\t%7d\t\t%.3lf\t\t%6d\t%s\t\t%d\n", pro[i].PID, pro[i].state, pro[i].start_time, pro[i].running_time, pro[i].dqzztime, pro[i].priority, pro[i].reason, pro[i].breakp);
		else
			printf("消费者%d\t\t%s\t%7d\t\t%7d\t\t%.3lf\t\t%6d\t%s\t\t%d\n", pro[i].PID, pro[i].state, pro[i].start_time, pro[i].running_time, pro[i].dqzztime, pro[i].priority, pro[i].reason, pro[i].breakp);
	}
	printf("———————————————————————\n");
	
	printf("\n————————内存存储情况————————\n");
	printf("**********************************************\n");
	printf("*\n");
	printf("* ");
	for (int i = 0; i < tp_mem; i++)
	{
		if (mem == tp_mem)	break;
		if (m[i] > 0)
		{
			printf("|%d 进程%d占用 %d| ", i, m[i + 1], m[i]);
			i = m[i];
		}
	}
	printf("\n*\n");
	printf("**********************************************\n");



	printf("1.继续 0.退出\n");
	int n;
	scanf("%d", &n);
	if (n == 0)	exit(0);
}

int main() {
	printf("*生产者消费者模拟\n");
	printf("—————————\n");
	printf("*请输入字符串:\n");
	scanf("%s", str);    // string数组存放将要产生的字符
	getchar();
	len = strlen(str);
	count = len;		 // 输入字符的个数

	// 初始化
	Init();        

	while (con_cnt < len) //消费完所有的字符为结束
	{
		system("cls");  //清屏操作	
		printf("—————————模拟指令流程————————\n");
		Control();      //处理器调度程序
		Print();        //输出显示各个信息
	}

	Close();
	printf("\n程序结束!\n");
}

/*  Alogorithm.c */

#include"DEFINITION.h"

// 根据到达时间进行排序 
void FCFS(PCB** arr, int n)
{
	PCB* tpp;

	for (int i = 1; i < n; i++)
	{
		for (int j = 0; j < n - i; j++)
		{
			if (arr[j]->start_time > arr[j + 1]->start_time)
			{
				tpp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tpp;
			}
		}
	}
}

// 按照运行时间排序
void SPF(PCB** arr, int n)
{
	PCB* tpp;

	for (int i = 1; i < n; i++)
	{
		for (int j = 0; j < n - i; j++)
		{
			if (arr[j]->running_time > arr[j + 1]->running_time)
			{
				tpp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tpp;
			}
		}
	}
}

// 按照优先级排序
void PRIORITY(PCB** arr, int n)
{
	PCB* tpp;

	for (int i = 1; i < n; i++)
	{
		for (int j = 0; j < n - i; j++)
		{
			// 数越大,优先级越小
			if (arr[j]->priority > arr[j + 1]->priority)
			{
				tpp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tpp;
			}
		}
	}
}

void HRRN(PCB** arr, int n)
{
	PCB* tpp;
	int tp_num = 0;
	
	for (int i = 0; i < n; i++)
	{
		if (arr[i]->breakp != 0 || arr[i]->breakp != -1)
		{
			if (tp_num != i)
			{
				tpp = arr[tp_num];
				arr[tp_num] = arr[i];
				arr[i] = tpp;
			}
			tp_num++;
		}
	}

	for (int i = 0; i < n - 1; i++)
	{
		for (int j = n - 1; j >= tp_num + i; j--)
		{
			if (arr[j]->dqzztime < arr[j + 1]->dqzztime)
			{
				tpp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tpp;
			}
		}
	}
}

void Alogorithm()
{
	system("cls");
	printf("******************************\n*请选择以下的一种调度算法:\n");
	printf("*\t1:先来先服务调度\n");
	printf("*\t2:非抢占式短进程优先调度\n");
	printf("*\t3:静态优先级调度\n");
	printf("*\t4:高响应比调度\n");
	printf("******************************\n");
	scanf("%d", &alo);

	ReorderQueue(ready_queue);
}

/*  PV.c */

#include"DEFINITION.h"

/* 0为empty, 1为filled,2为rw_mux */

void P(Semaphore* mux, PCB* p)
{
	mux->num--;

	// 彩色文本实现
	printf("\033[35m");
	if (mux->num < 0)
	{
		Block(mux, p);
		pc--;						// 程序计数器记录位置
	}
	else
	{

		printf("\t* %s信号申请成功!\n", mux->name);
	}
	printf("\033[34m");
}

void Block(Semaphore* mux, PCB* p)
{
	// 定义两个阻塞队列:生产者和消费者 
	int num = 0;

	strcpy(p->state, "Block");		// 改变状态
	strcpy(p->reason, mux->name);	// 说明原因
	memClear(p);					// 内存中清除该进程

	if (mux->flag == 2)
	{
		Look_DeQueue(run_queue, p);
		EnQueue(block_queue, p);
	}
	else
	{
		if (p->flag == 0)
		{
			Look_DeQueue(run_queue, p);
			EnQueue(product_block_queue, p);
		}
		else
		{
			Look_DeQueue(run_queue, p);
			EnQueue(consume_block_queue, p);
		}
	}

	printf("\t* %s %d进程阻塞了!\n", p->name, p->PID);

	num = block_queue->size;
	printf("\t* 阻塞的进程个数为:%d\n", num);
}

void V(Semaphore* mux, PCB* p)
{
	mux->num++;

	if (mux->num <= 0)
	{
		Wakeup(mux, p);
		pc++;						// 程序计数器记录位置
	}
}

//唤醒函数
void Wakeup(Semaphore* mux, PCB* p)
{
	PCB* tp;

	if (mux->flag == 0)
	{
		tp = DeQueue(product_block_queue);
	}
	else if (mux->flag == 1)
	{
		tp = DeQueue(consume_block_queue);
	}
	else
	{
		tp = DeQueue(block_queue);
	}

	if (tp == NULL)	return;
	strcpy(tp->state, "Ready");
	strcpy(tp->reason, "Null");

	// 同步进程信息 
	for (int k = 0; k < PRODUCT + CONSUME; k++)
	{
		if (pro[k].flag == tp->flag && pro[k].PID == tp->PID)
		{
			CopyProcess(&pro[k], tp);
			break;
		}
	}

	EnQueue(ready_queue, tp);
	// 彩色文本
	printf("\033[35m");
	printf("\t* %s %d进程被唤醒了!\n", tp->name, tp->PID);
	printf("\033[0m");
	printf("\033[34m");
}

/*  MemBlock.c */

#include"DEFINITION.h"

/*
	进程运行前需要申请内存,内存足够且给它分配了才能运行
		* 一个数组表示内存区域,
		* 内存大小由整型类型的全局变量表示,
		* 内存阻塞由标识符表示,也可以直接判断(内存-进程大小 ?< 0)
		* 进程被阻塞或者完成任务,内存要及时清除
*/
void setMem()
{
	printf("请输入内存的大小: \n");
	scanf("%d", &mem);
	while (mem < 128)
	{
		// 彩色文本
		printf("\033[35m");
		printf("内存过小,请重新输入: \n");
		printf("\033[0m");

		scanf("%d", &mem);
	}
	tp_mem = mem;

	m = (int*)malloc(sizeof(int) * mem);
	if (m == NULL)
	{
		exit(0);
	}
	memset(m, 0, sizeof(int) * mem);
}

// 分配内存
int memBlock(PCB* p)
{
	int size = sizeof(*p);
	if (mem - size < 0)
	{
		// 彩色文本
		printf("\033[31m");
		printf("内存不够大,进程无法加载!\n");
		printf("\033[0m");

		Look_DeQueue(run_queue, p);
		strcpy(p->state, "Ready");
		EnQueue(ready_queue, p);

		return 0;
	}
	else
	{
		// 动态分区分配内存
		int tp = 0;
		int add = 0;

		for (int i = 0; tp < size && i < tp_mem; i++)
		{
			if (m[i] == 0)
			{
				tp++;
			}
			else
			{
				tp = 0;
				i = m[i] + 1;
				add = i;
			}
		}

		if (tp < size)
		{
			// 彩色文本
			printf("\033[31m");
			printf("外部碎片过多,进程无法直接插入内存!\n");
			printf("\033[0m");
			Look_DeQueue(run_queue, p);
			strcpy(p->state, "Ready");
			EnQueue(ready_queue, p);
			return 0;
		}
		m[add] = add + size - 1;			// 第一位记录最后一位位置
		m[add + 1] = p->PID;				// 第二位记录进程PID
		p->Address = add;					// 进程记录内存位置
		mem -= size;
		m[add + size - 1] = -1;				// 最后一位为-1

		return 1;
	}
}

void memClear(PCB* p)
{
	mem += sizeof(*p);

	int tp = m[p->Address];
	m[tp] = 0;
	m[p->Address] = 0;
	m[p->Address + 1] = 0;

	p->Address = -1;
}

void memClose()
{
	for (int i = run_queue->size; i > 0; i--)
	{
		PCB* p = DeQueue(run_queue);
		strcpy(p->state, "Stop");
		mem += sizeof(*p);

		// 同步信息
		for (int k = 0; k < PRODUCT + CONSUME; k++)
		{
			if (pro[k].flag == p->flag && pro[k].PID == p->PID)
			{
				CopyProcess(&pro[k], p);
				break;
			}
		}
	}

	free(m);
}

/*  模拟多进程.c */

#include"DEFINITION.h"

void Control() //处理器调度程序
{
	int num;					// 就绪进程数目 
	if (ready_queue->size == 0 && run_queue->size == 0)
	{
		// 彩色文本
		printf("\033[31m");
		printf("死锁!!!");
		printf("\033[0m");
		exit(0);
	}

	num = ready_queue->size;	// 统计就绪进程个数
	printf("\t* 就绪进程个数为:%d\n", num);

	// 高响应比算法 每次 就绪队列重新排序
	if(alo == 4)	ReorderQueue(ready_queue);

	// 插入运行队列,多进程并行最大数量为PROCESS
	PCB* p;
	for (int i = run_queue->size; i < PROCESS && num != 0; i++, num--)
	{
		p = DeQueue(ready_queue);
		strcpy(p->state, "Run");
		EnQueue(run_queue, p);
	}

	// 开启模拟多进程,执行操作 
	for (PCB* p = run_queue->first_pro->next; p != NULL; p = p->next)
	{
		tp_time += 1;
		printf("当前时间: %ds\n", tp_time);

		// 检查断点,如果断点为0,则表示该进程刚开始执行,需特殊处理 
		if (p->breakp == 0)
		{
			if (tp_time >= p->arrive_time)
			{
				// 彩色文本实现
				printf("\033[36m");
				Processor(p);
				printf("\033[0m");
			}
			else if(p->arrive_time - tp_time >= 20)	// 到达时间过长,则特殊处理
			{
				// 如果运行队列内的每个进程的到达时间都很长,且就绪队列没有进程了,则特殊处理
				if(ready_queue->size == 0)
				{
					p->arrive_time = tp_time;
					// 彩色文本实现
					printf("\033[36m");
					Processor(p);
					printf("\033[0m");
				}
				else
				{
					printf("\t* 进程未到达,请等待!\n");
					Look_DeQueue(run_queue, p);
					strcpy(p->state, "Ready");
					EnQueue(ready_queue, p);
					EnQueue(ready_queue, DeQueue(ready_queue));
				}
			}
			else
			{
				printf("\t* 进程未到达,请等待!\n");
				Look_DeQueue(run_queue, p);
				strcpy(p->state, "Ready");
				EnQueue(ready_queue, p);
				EnQueue(ready_queue, DeQueue(ready_queue));
			}
		}
		else if (tp_time - p->break_time >= 2)		// 每步操作是20ms,执行不超过20ms就是没执行完毕
		{
			// 彩色文本实现
			printf("\033[36m");
			Processor(p);
			printf("\033[0m");
		}

		// 同步信息
		for (int k = 0; k < PRODUCT + CONSUME; k++)
		{
			if (pro[k].flag == p->flag && pro[k].PID == p->PID)
			{
				CopyProcess(&pro[k], p);
				break;
			}
		}
		
		// 判断是否已经输入完毕,是则关闭进程
		CloseProcess();
	}
}

//模拟处理器指令执行
void Processor(PCB* p)
{
	// 内存判断
	if (p->Address == -1)
	{
		if (memBlock(p) != 1)
		{
			return;
		}
	}

	
	if (p->flag == 0) //当前进程为生产者
		switch (p->breakp)
		{
		case 0:		// produce
			p->break_time = tp_time;		// 保存时间断点

			if (count <= 0) { 				// 生产结束
				Look_DeQueue(run_queue, p);
				printf("\t* 生产者%d结束生产!\n", p->PID);
				strcpy(p->state, "Stop");
				strcpy(p->reason, "Null");

				p->break_time = tp_time;
				p->end_time = p->break_time;// 保存结束时间
				p->breakp = -1;
				memClear(p);				// 内存中清除该进程
			}
			else
			{
				printf("\t* 开始运行%s %d\n", p->name, p->PID);
				p->start_time = p->break_time;// 记录开始时间 
				printf("\t* %s %d生产了字符%c\n", p->name, p->PID, str[sp]);

				rec_p[p_l] = str[sp];		// 添加到生产记录
				p_l++;
				sp = (sp + 1) % len;
				count--; 					// 剩余字符个数减1

				pc++;						// 程序计数器记录位置
				p->breakp++; 				// 保存断点
			}

			break;
		case 1: 	// 申请 访问临界区 
			pc++;						// 程序计数器记录位置
			p->breakp++; 				// 保存断点
			P(empty, p);

			break;
		case 2:
			// 互斥访问
			pc++;						// 程序计数器记录位置
			p->breakp++; 				// 保存断点
			P(rw_mux, p);
			break;
		case 3: 	// 访问临界区 
			p->break_time = tp_time;	// 保存时间断点

			buffer[in] = rec_p[p_f]; 	// 放到缓冲区
			printf("\t* %c字符成功入驻空缓存!\n", buffer[in]);

			in = (in + 1) % BUF;		// 生产头指针+1
			p_f++;						// 缓冲区尾指针+1
			pc++;						// 程序计数器记录位置
			p->breakp++; 				// 保存断点
			break;
		case 4: 	// 退出临界区 
			p->break_time = tp_time;	// 保存时间断点
			pc++;						// 程序计数器记录位置
			p->breakp++; 				// 保存断点

			V(rw_mux, p);
			printf("\t* 释放一个%s信号\n", rw_mux->name);
			V(filled, p);
			printf("\t* 释放一个%s信号\n", filled->name);

			break;
		case 5:		// goto01  
			printf("\t* %s %d goto 0 操作\n", p->name, p->PID);
			pc = 0;						// 程序计数器归零
			p->breakp = 0;
			Look_DeQueue(run_queue, p); // 从运行队列删除该进程
			printf("\t* 剩余字符count=%d个\n", count);

			p->break_time = tp_time;	// 保存时间断点
			p->end_time = p->break_time;// 保存结束时间 
			p->zztime = p->end_time - p->start_time;		// 周转时间

			memClear(p);				// 内存中清除该进程

			if (count <= 0) { 				// 生产结束
				printf("\t* 生产者%d结束生产!\n", p->PID);
				strcpy(p->state, "Stop");
				strcpy(p->reason, "Null");

				p->breakp = -1;
			}
			else
			{
				strcpy(p->state, "Ready");
				strcpy(p->reason, "Null");
				p->start_time = 0;
				EnQueue(ready_queue, p);
			}

			
		}
	else  //当前进程为消费者
		switch (p->breakp)
		{
		case 0: 	// 判断缓冲区是否有东西 
			printf("\t* 开始运行%s %d\n", p->name, p->PID);

			p->break_time = tp_time;		// 保存时间断点
			p->start_time = p->break_time;	// 记录开始时间 
			pc++;							// 程序计数器记录位置
			p->breakp++;

			P(filled, p);
			break;
		case 1:
			// 互斥访问
			pc++;						// 程序计数器记录位置
			p->breakp++; 				// 保存断点
			P(rw_mux, p);
			break;
		case 2: 	// 将字符取出缓冲区 
			p->break_time = tp_time;	// 保存时间断点

			printf("\t* %s %d取字符!\n", p->name, p->PID);
			rec_c[c_l] = buffer[out];

			out = (out + 1) % BUF;		// 缓冲区头指针加一
			c_l++;						// 输出尾指针+1
			pc++;						// 程序计数器记录位置
			p->breakp++; 				// 保存断点

			break;
		case 3: 	// 释放信号量 
			p->break_time = tp_time;	// 保存时间断点
			pc++;						// 程序计数器记录位置
			p->breakp++;				// 保存断点

			V(rw_mux, p);
			printf("\t* 释放一个%s\n", rw_mux->name);
			V(empty, p);
			printf("\t* 释放一个%s\n", empty->name);

			break;
		case 4: 	// 消费字符 
			p->break_time = tp_time;		// 保存时间断点
			printf("\t* 消费了字符%c\n", rec_c[c_f]);			// 添加到消费记录
			c_f++;
			
			con_cnt++;
			if (con_cnt >= len) 
			{
				strcpy(p->state, "Stop");	// 完成态
				p->breakp = -1;
				DeQueue(run_queue);

				p->break_time = tp_time;	// 保存时间断点
				p->end_time = p->break_time;// 保存结束时间
				p->zztime = p->end_time - p->start_time;		// 周转时间

				memClear(p);				// 内存中清除该进程

				return;
			}

			pc++;						// 程序计数器记录位置
			p->breakp++; 				// 保存断点
			break;
		case 5: 	// goto0
			p->break_time = tp_time;	// 保存时间断点
			printf("\t* 消费进程goto 0 操作\n");
			pc = 0;
			p->breakp = 0;				// 保存断点
			Look_DeQueue(run_queue, p);
			strcpy(p->state, "Ready");
			strcpy(p->reason, "NULL");
			p->start_time = 0;
			p->break_time = tp_time;	// 保存时间断点
			p->end_time = p->break_time;// 保存结束时间
			p->zztime = p->end_time - p->start_time;		// 周转时间

			memClear(p);				// 内存中清除该进程
			
			EnQueue(ready_queue, p);

			break;
		}

		p->dqzztime = (tp_time - p->start_time) / p->running_time;		// 带权周转时间


}

/*  Close.c */

#include"DEFINITION.h"

// 关闭剩余进程
void CloseProcess()
{
	if (con_cnt >= len)
	{
		for (PCB* tpp = DeQueue(ready_queue); tpp != NULL; tpp = tpp->next)
		{
			tpp->breakp = -1;
			strcpy(tpp->state, "Stop");
			strcpy(tpp->reason, "NULL");
			tpp->end_time = tp_time;

			// 同步信息
			for (int k = 0; k < PRODUCT + CONSUME; k++)
			{
				if (pro[k].flag == tpp->flag && pro[k].PID == tpp->PID)
				{
					CopyProcess(&pro[k], tpp);
					break;
				}
			}
		}
		for (PCB* tpp = DeQueue(block_queue); tpp != NULL; tpp = tpp->next)
		{
			tpp->breakp = -1;
			strcpy(tpp->state, "Stop");
			strcpy(tpp->reason, "NULL");
			tpp->end_time = tp_time;

			// 同步信息
			for (int k = 0; k < PRODUCT + CONSUME; k++)
			{
				if (pro[k].flag == tpp->flag && pro[k].PID == tpp->PID)
				{
					CopyProcess(&pro[k], tpp);
					break;
				}
			}
		}
		for (PCB* tpp = DeQueue(product_block_queue); tpp != NULL; tpp = tpp->next)
		{
			tpp->breakp = -1;
			strcpy(tpp->state, "Stop");
			strcpy(tpp->reason, "NULL");
			tpp->end_time = tp_time;

			// 同步信息
			for (int k = 0; k < PRODUCT + CONSUME; k++)
			{
				if (pro[k].flag == tpp->flag && pro[k].PID == tpp->PID)
				{
					CopyProcess(&pro[k], tpp);
					break;
				}
			}
		}
		for (PCB* tpp = DeQueue(consume_block_queue); tpp != NULL; tpp = tpp->next)
		{
			tpp->breakp = -1;
			strcpy(tpp->state, "Stop");
			strcpy(tpp->reason, "NULL");
			tpp->end_time = tp_time;

			// 同步信息
			for (int k = 0; k < PRODUCT + CONSUME; k++)
			{
				if (pro[k].flag == tpp->flag && pro[k].PID == tpp->PID)
				{
					CopyProcess(&pro[k], tpp);
					break;
				}
			}
		}
	}
}

// 释放队列
void DestroyQueue(PCBQueue* q)
{
	PCB* current = q->first_pro->next;
	PCB* next;

	while (current != NULL)
	{
		next = current->next;
		free(current);
		current = next;
	}

	free(q->first_pro);
	free(q);
}

// 释放信号量
void DestroySemaphore(Semaphore* mux)
{
	printf("关闭信号量%s\n", mux->name);
	free(mux);
}

void Close()
{
	// 关闭队列
	printf("关闭队列\n");
	DestroyQueue(ready_queue);
	DestroyQueue(block_queue);
	DestroyQueue(product_block_queue);
	DestroyQueue(consume_block_queue);
	DestroyQueue(run_queue);

	// 关闭信号量
	DestroySemaphore(empty);
	DestroySemaphore(filled);
	DestroySemaphore(rw_mux);

	// 清除内存
	memClose();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值