总体设计
数据结构定义:
- 结构体PCB:进程ID、优先级等,增加了消息队列指针
- 结构体消息块:消息发送者,消息内容,指向下一条消息的指针
- 就绪队列:已就绪的进程id,指向下一个进程的指针
- 结构体PCB数组:模拟当前内存大小
函数
Init()——初始化就绪队列;
Create()——进程创建;
isOrNot(int num)——判断进程是否已经创建;
call(Ready r)——调用进程;
kill(Ready r)——进程撤销;
display(Ready r)——就绪队列输出函数:
send()——用于两个进程之间发送消息;
receive()——用于进程接收消息;
showMessage()——消息进程的消息队列;
menu(Ready r)——功能选择界面;
功能测试:
编程实现基于消息缓冲队列机制的进程通信数据结构(创建消息、发送消息、接收消息),在菜单中选择执行各功能,从显示出的就绪队列状态和消息队列状态,查看操作的正确与否。
详细设计
在本次模拟实验中,我主要写了十个函数。
在Init()中,我主要创建了进程的头结点,方便后面进程的调用和撤销。
在Create()函数中,我主要将要创建的进程的参数填入PCB,并插入到就绪队列中。在Create()函数中我首先进行了一次判断,判断n是否大于100,如果n>100,说明PCB数组已满(即模拟内存已满)就不能再继续创建进程了,反之可以;然后输入要创建的进程id,并根据已定义的一个函数来判断当前id是否已被创建;如果id重复,我们就要重新输入,直至成功为止,然后将填入参数的PCB节点中,即进程创建成功。
isOrNot(int num)主要是判断当前进程的id是否已经存在,在进程输入的时候会多次调用进行判断。
call(Ready r)主要是调用进程,输入要调用的进程的id,将进程插入到就绪队列中。
kill(Ready r)主要是撤销进程,输入要撤销的进程的id,将进程从就绪队列中移出。
display()函数主要是输出当前就绪队列中的所有就绪队列的信息,我们可以借助这个函数来查看我们对进程的每一次操作是否成功。
send()主要用于进程之间发送消息,首先要输入发送端和接收端的id,输入要发送的消息,将发送端发送的消息插入到接收端的消息队列中,即发送成功。
receive()用于接收端接收消息,首先输入要接收消息的进程id,将消息从其缓冲队列中移出,即消息接收成功。
showMessage()主要作用是查看消息队列,方便我们判断每一次的消息发送和接收是否成功。
menu()是菜单函数,让我们进行功能选择,我们可以从菜单中选择调用上述的任一函数,从而进一步对进程的创建与撤销进行操作。
代码实现:
#include <stdio.h>
#include <stdlib.h>
#include<malloc.h>
///消息块控制结构
typedef struct MessageNode *Message;
struct MessageNode{
int sender;///发送者
char info[100];///消息内容
Message next;///指向下一条消息的指针
};
///PCB控制块信息
typedef struct PCBnode{
int id;///进程id
int priority;///进程优先级
int status;///进程状态 0:未就绪 1:运行
Message front;///消息队列头指针
}PCB;
///就绪队列
typedef struct ReadyNode *Ready;
struct ReadyNode{
Ready next;///指向下一个进程
int data;///已就绪的进程id
};
PCB pcb[100];///结构体PCB数组,模拟当前内存大小
int N=0;///当前已经创建的进程数目
///创建进程:申请PCB,填入进程参数
void Create(){
int num;
///要申请的进程数大于当前系统的内存
if(N>100){
printf("当前内存已满!\n");
return 0;
}
printf("输入要创建的进程的id:");
scanf("%d",&num);
getchar();
while(isOrNot(num)==1){
printf("请重新输入:");
scanf("%d",&num);
getchar();
}
pcb[N].id=num;
printf("输入要创建的进程的优先级:");
scanf("%d",&pcb[N].priority);
getchar();
pcb[N].status=0;
pcb[N].front=(Message)malloc(sizeof(struct MessageNode));
pcb[N].front->next=NULL;
N++;
return 0;
}
///判断进程是否已创建
int isOrNot(int num){
for(int i=0;i<N;i++){
if(num==pcb[i].id){
printf("该进程已创建!\n");
return 1;
}
}
return 0;
}
///初始化就绪队列
Ready init(){
Ready head;
head=(Ready)malloc(sizeof(struct ReadyNode));
head->next=NULL;
return head;
}
///调用进程
void call(Ready r){
int num;
Ready p;
printf("请输入要调用的进程的id:");
scanf("%d",&num);
if(r==NULL){
printf("当前无可调用进程!\n");
return 0;
}
for(int i=0;i<N;i++){
if(num==pcb[i].id){
pcb[i].status=1;
p=(Ready)malloc(sizeof(struct ReadyNode));
p->data=pcb[i].id;
p->next=r->next;
r->next=p;
printf("调用成功!\n");
return 0;
}
}
printf("内存中无该进程!\n");
return 0;
}
///显示正在被调用的进程
void display(Ready r){
Ready p=r->next;
if(p==NULL){
printf("当前无正在运行的进程!\n");
return 0;
}
while(p!=NULL){
printf("当前正在运行的进程:%d\n",p->data);
p=p->next;
}
return 0;
}
///撤销进程
void kill(Ready r){
int num;
Ready temp,p=r;
if(p->next==NULL){
printf("当前系统中无可运行的进程!\n");
return 0;
}
printf("请输入要撤销的进程的id:");
scanf("%d",&num);
while(p->next!=NULL){
if(p->next->data==num){
for(int i=0;i<N;i++){
if(pcb[i].id==num){
pcb[i].status=0;
}
}
temp=p->next;
p->next=p->next->next;
free(temp);
printf("撤销成功!\n");
return 0;
}
p=p->next;
}
printf("内存中无该进程!\n");
}
///发送消息
void send(){
int send_id,receiver_id;
Message M,h;
printf("请输入消息发送方的id:");
scanf("%d",&send_id);
getchar();
printf("请输入消息接收方的id:");
scanf("%d",&receiver_id);
getchar();
for(int i=0;i<N;i++){
if(receiver_id==pcb[i].id){
M=(Message)malloc(sizeof(struct MessageNode));
M->sender=send_id;
printf("请输入消息内容:");
gets(M->info);
M->next=pcb[i].front->next;
pcb[i].front->next=M;
printf("发送成功!\n");
return 0;
}
}
printf("发送失败!\n");
}
///接收消息
void receive(){
int num;
Message m;
printf("请输入消息接收方的id:");
scanf("%d",&num);
for(int i=0;i<N;i++){
if(pcb[i].id==num){
if(pcb[i].front->next==NULL){
printf("消息队列为空!\n");
}else{
m=pcb[i].front->next;
pcb[i].front->next=pcb[i].front->next->next;
free(m);
printf("接收成功!\n");
}
return 0;
}
}
return 0;
}
///显示消息
void showMessage(){
int num;
Message m;
printf("请输入要显示消息队列的进程id:");
scanf("%d",&num);
for(int i=0;i<N;i++){
if(num==pcb[i].id){
m=pcb[i].front->next;
if(m==NULL){
printf("消息队列为空!\n");
return 0;
}
while(m!=NULL){
printf("%d: %s\n",m->sender,m->info);
m=m->next;
}
return 0;
}
}
printf("该进程不存在!\n");
return 0;
}
void menu(Ready r){
int n;
while(1){
printf("\n***********进程演示系统*************\n");
printf(" 1.创建进程 2.调用进程\n");
printf(" 3.发送消息 4.接收消息\n");
printf(" 5.查看进程 6.撤销进程\n");
printf(" 7.显示消息 8.退出程序\n");
printf("************************************\n\n");
printf("请输入你的选择(1-8):");
scanf("%d",&n);
switch(n){
case 1:Create();
break;
case 2:call(r);
break;
case 3:send();
break;
case 4:receive();
break;
case 5:display(r);
break;
case 6:kill(r);
break;
case 7:showMessage();
break;
case 8:return 0;
default:printf("没有这个选项!");
break;
}
}
return 0;
}
int main()
{
Ready r;
r=init();
menu(r);
return 0;
}
while(p->next!=NULL){
p->next->data--;
pcb[p->next->data]=pcb[p->next->data+1];
p=p->next;
}
}
printf("成功杀死进程!\n");
return 0;
}
}
void menu(){
int n;
while(1){
printf("\n*************进程演示系统*************\n");
printf(" 1.创建进程\n");
printf(" 2.查看进程\n");
printf(" 3.杀死进程\n");
printf(" 4.退出程序\n");
printf("***************************************\n\n");
printf("请输入你的选择(1-4):");
scanf("%d",&n);
switch(n){
case 1:Create();
break;
case 2:display();
break;
case 3:kill();
break;
case 4:return 0;
default:printf("没有这个选项!");
break;
}
}
return 0;
}
int main()
{
InitQueue();
menu();
return 0;
}
运行截图:
进程创建:
进程调用:
进程通信: