/* 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();
}