总体设计
- 数据结构定义:
结构体PCB:进程名、ID、运行时间、优先级等,队列的排序按优先级排序。
PCB空间:结构体PCB数组
就绪队列指针
首尾指针 - 函数
InitQueue():初始化就绪队列
Create()—进程创建:从PCB空间申请一个空PCB,填入进程参数,插入就绪队列;
kill()—进程终止:将指定的就绪进程移出就绪队列,清除PCB中的信息;
display()—就绪队列输出函数:输出就绪队列中的进程信息,以便观察创建或撤消活动的结果;
Sort()—进程优先级排序,根据你定义的优先级,把进程进行排序。
menu()—功能选择:调用创建函数;调用终止函数;显示就绪进程;退出系统等。 - 功能测试:
在菜单中选择执行各功能,从显示出的就绪队列状态,查看操作的正确与否。
详细设计
在本次模拟实验中,我主要写了六个函数。
——在InitQueue()中,我主要将指向就绪队列的头指针和尾指针初始化,方便后面进程的创建。
——在Create()函数中,我主要将要创建的进程的参数填入PCB,并插入到就绪队列中。在Create()函数中我进行了三次判断,第一次是n是否大于100,如果n>100,说明PCB数组已满(即模拟内存已满)就不能再继续创建进程了,反之可以;第二次是判断L.front->next是否为NULL,如果为NULL,说明这时创建的进程是系统中第一个进程,不用考虑进程id是否会与其他进程id重复,可直接将参数填入数组,反之我们就要判断id是否会与其他进程id重复,即第三次判断,如果id重复,我们就要重新输入,直至成功为止,然后将填入参数的PCB节点插入到就绪队列中,即进程创建成功。
—— Sort()函数主要是对进程的优先级进行排序,这里我采用了冒泡排序将优先级高的进程放在了就绪队列的前面。
——display()函数主要是输出当前就绪队列中的所有就绪队列的信息,我们可以借助这个函数来查看我们的每一次操作是否成功。
——kill()函数主要是用来终止进程,我们进行进程的终止操作是将进程移出就绪队列,重新找到首位指针应该指向的位置,并且删除已终止的进程在PCB中的相关信息。
——menu()是菜单函数,让我们进行功能选择,我们可以从菜单中选择调用上述的任一函数,从而进一步对进程的创建与撤销进行操作。
代码实现
#include <stdio.h>
#include <stdlib.h>
///pcb控制块信息
typedef struct P_node{
char t_name[20];///进程名
long t_id;///进程id
float t_time;///进程运行时间
int priority;///进程优先级
}PCB;
///就绪队列
typedef struct Tnode *T;
struct Tnode{
int data;
T next;///指向就绪队列的下一个位置
};
///消息缓冲队列
typedef struct Linkqueue{
T front,rear;///头指针和尾指针分别指向就绪队列的头和尾
}LQ;
LQ L;
PCB pcb[100];///结构体PCB数组,模拟当前内存大小
int N=0;///当前已经创建的进程数目
///就绪队列初始化
void InitQueue(){
L.rear=L.front=malloc(sizeof(T));
if(!L.front)
exit(-2);
L.front->next=NULL;
return 0;
}
///创建进程:申请PCB,填入进程参数
void Create(){
int n;///要创建的进程的数目
printf("请输入要创建的进程的数目:");
scanf("%d",&n);
///要申请的进程数大于当前系统的内存
if(n>100){
printf("当前内存已满");
return 0;
}
int i,j;
long id;
T t;
for(i=1;i<=n;i++){
///当就绪队列为空时,第一个进程id可以直接写入
if(L.front->next==NULL){
printf("请输入进程id:");
scanf("%ld",&pcb[i+N].t_id);
getchar();
printf("请输入进程名:");
gets(pcb[i+N].t_name);
printf("请输入进程运行时间:");
scanf("%f",&pcb[i+N].t_time);
getchar();
printf("请输入进程优先级:");
scanf("%d",&pcb[i+N].priority);
N++;///当前进程数加1
}else{
printf("请输入进程id:");
scanf("%ld",&id);
///当就绪队列不为空时,需要检查所创建的进程id是否重复
for(j=1;j<i+N;){
if(id==pcb[j].t_id){
printf("进程ID已经存在!\n请重新输入:");
scanf("%ld",&id);
j=0;
}else{
j++;
}
}
pcb[i+N].t_id=id;
getchar();
printf("请输入进程名:");
gets(pcb[i+N].t_name);
printf("请输入进程运行时间:");
scanf("%f",&pcb[i+N].t_time);
getchar();
printf("请输入进程优先级:");
scanf("%d",&pcb[i+N].priority);
N++;///当前进程数加1
}
///将当前进程加入就绪队列
t=malloc(sizeof(T));
t->data=N;
t->next=NULL;
///将就绪队列中的进程加入消息缓冲队列
L.rear->next=t;
L.rear=t;
}
Sort();
return 0;
}
void Sort(){
int i,j;
///将进程按优先级排序
for(i=1;i<=N;i++){
for(j=i+1;j<=N;j++){
if(pcb[i].priority<pcb[j].priority){
PCB temp=pcb[i];
pcb[i]=pcb[j];
pcb[j]=temp;
}
}
}
}
///显示已经就绪的进程
void display(){
T p;
p=L.front;
if(p->next==NULL){
printf("当前无进程!");
}
while(p->next!=NULL){
p=p->next;
printf(" 进程ID:%ld\n 进程名:%s \n运行时间:%f \n优先级:%d\n",pcb[p->data].t_id,pcb[p->data].t_name,pcb[p->data].t_time,pcb[p->data].priority);
}
}
///进程终止
void kill(){
int id;
T p;
p=L.front;
if(p->next==NULL){
printf("当前无进程!\n\n");
}else{
printf("输入要终止的进程的id:");
scanf("%ld",&id);
while(pcb[p->next->data].t_id!=id){
if(p->next==NULL){
printf("该进程不存在!\n");
return 0;
}
p=p->next;
}
if(pcb[p->next->data].t_id==id){
p->next=p->next->next;
/*当L.front->next==NULL时,
说明当前杀死的进程是系统中最后一个进程,
此时首位指针指向同一个位置*/
if(L.front->next==NULL){
L.front=L.rear;
}
/*当p->next==NULL时,
说明当前杀死的进程是队尾进程,
此时尾指针指向p*/
if(p->next==NULL){
L.rear=p;
}
///删除已终止进程的PCB进程控制块信息
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;
}
运行截图: