#include
#include
#include
/*临资源定义区*/
#define keyboard 0 //设置键盘这一临界资源为device[0]
#define mouse 1 //设置鼠标这一临界资源为device[1]
#define printer 2 //设置打印机这一临界资源为device[2]
/*
数据结构区
*/
struct PCB//PCB块结构体(待完善)
{
char name[20];//进程名称
int state = 0;//表示PCB单元的状态(空闲0,就绪1,执行2)态
int server_time = 0;//进程服务时间
int ready_time = 0;//PCB处于就绪队列中则此项为等待时间
int block_time = 0;//PCB处于阻塞队列中此项为剩余等待时间
int device[5];//表示临界资源
struct PCB* next = NULL;//下一PCB节点
}PCBS[10];//声明PCB块队列
struct semaphore//信号量结构体
{
int value = 0;
struct PCB* next = NULL;
} semaphores[10];//数组大小为临界资源数量
struct PCB* free_listHEAD = &PCBS[0];//空闲PCB队列头指针
struct PCB* free_listTAIL = &PCBS[9];//空闲PCB队列尾指针
struct PCB* ready_listHEAD = NULL;//就绪队列头指针
struct PCB* ready_listTAIL = NULL;//就绪队列尾指针
struct PCB* running = NULL;//执行队列头指针
struct PCB* wait_listHEAD = NULL;//阻塞队列头指针
struct PCB* wait_listTAIL = NULL;//阻塞队列尾指针
void chain_append(struct PCB* temp, struct PCB** chain_head_point, struct PCB** chain_tail_point, int state);//将指定节点,加入到指定链表尾部,指定更改状态
void chain_appendInit(struct PCB* temp, struct PCB** chain_head_point, struct PCB** chain_tail_point);//将指定节点,初始化后加入到指定链表尾部
struct PCB* chain_pop(struct PCB** chain_head_point, struct PCB** chain_tail_point);
struct PCB* chain_delByName(char name[], struct PCB** chain_head_point, struct PCB** chain_tail_point);//删除链表中指定名称的进程,若删除成功则返回指针,若删除不成功则返回NULL
struct PCB* chain_delByPointer(struct PCB* targetpointer, struct PCB** chain_head_point, struct PCB** chain_tail_point);
struct PCB* chain_DoForEach(struct PCB** chain_head_point, struct PCB** chain_tail_point, int statue);
int check_doing();//检测是否有进程在执行,若没有则将执行就绪队列进程
struct PCB* block_process(int time);//阻塞当前正在执行的进程,并将其加入到阻塞队列中
void cancel_process(char name[]);//撤销就绪队列或阻塞队列中的进程
void re_processByName(char name[]);//通过名称把阻塞态恢复到就绪态
void re_processByPointer(struct PCB* targetpointer);//通过指针将阻塞态恢复到就绪态
int create_process(char name[], int server_time);//创建进程函数
void show_process(struct PCB* free_list, struct PCB* ready_list, struct PCB* wait_list);//将目前系统内的所有进程队列(包括就绪,空闲,执行态)全部打印出来
void show_single_process(struct PCB* chain_head_point);
/*
链表操作区
*/
void chain_append(struct PCB* temp, struct PCB** chain_head_point, struct PCB** chain_tail_point, int state)//将指定节点,加入到指定链表尾部,指定更改状态
{
temp->state = state;
if (*chain_head_point == NULL)
{
*chain_head_point = temp;
*chain_tail_point = temp;
}
else
{
(*chain_tail_point)->next = temp;
(*chain_tail_point) = (*chain_tail_point)->next;
}
}
void chain_appendInit(struct PCB* temp, struct PCB** chain_head_point, struct PCB** chain_tail_point)//将指定节点,初始化后加入到指定链表尾部
{
*temp->name = NULL;//对PCB进行初始化
temp->server_time = 0;
temp->next = NULL;
temp->state = 0;
temp->block_time = 0;
temp->ready_time = 0;
memset((*temp).device, 0, sizeof((*temp).device));
if (*chain_head_point == NULL)
{
*chain_head_point = temp;
*chain_tail_point = temp;
}
else
{
(*chain_tail_point)->next = temp;
(*chain_tail_point) = (*chain_tail_point)->next;
}
}
struct PCB* chain_pop(struct PCB** chain_head_point, struct PCB** chain_tail_point)
{
struct PCB* temp = NULL;
if (*chain_head_point == NULL)
{
printf("无空闲PCB或已空\n");
}
else
{
temp = *chain_head_point;
if ((*chain_head_point)->next == NULL)
{
*chain_head_point = NULL;
*chain_tail_point = NULL;
}
else
{
*chain_head_point = (*chain_head_point)->next;
}
temp->next = NULL;
}
return temp;
}
struct PCB* chain_delByName(char name[], struct PCB** chain_head_point, struct PCB** chain_tail_point)//删除链表中指定名称的进程,若删除成功则返回指针,若删除不成功则返回NULL
{
if (*chain_head_point == NULL)
{
return NULL;
}
else
{
struct PCB* headpointer = *chain_head_point;
struct PCB* pointer = *chain_head_point;
if (!strcmp(name, pointer->name))//如果头节点是要找的进程
{
if (pointer->next == NULL)
{
*chain_head_point = NULL;
*chain_tail_point = NULL;
}
else
{
*chain_head_point = (*chain_head_point)->next;
}
return pointer;
}
while (pointer != NULL && pointer->next != NULL)
{
if (!strcmp((pointer->next)->name, name))//如果找到相同名称的进程
{
struct PCB* temp = pointer->next;
if ((pointer->next)->next == NULL)
{
pointer->next = NULL;
}
else
{
pointer->next = (pointer->next)->next;
}
return temp;
}
pointer = pointer->next;
}
}
return NULL;
}
struct PCB* chain_delByPointer(struct PCB* targetpointer, struct PCB** chain_head_point, struct PCB** chain_tail_point)
{
if (*chain_head_point == NULL)
{
*chain_tail_point = NULL;
return NULL;
}
else
{
struct PCB* headpointer = *chain_head_point;
struct PCB* pointer = *chain_head_point;
if (pointer == targetpointer)//如果头节点是要找的进程
{
if (pointer->next == NULL)
{
*chain_head_point = NULL;
*chain_tail_point = NULL;
}
else
{
*chain_head_point = (*chain_head_point)->next;
}
return pointer;
}
while (pointer != NULL && pointer->next != NULL)
{
if (pointer->next == targetpointer)//如果找到相同名称的进程
{
struct PCB* temp = pointer->next;
if ((pointer->next)->next == NULL)
{
pointer->next = NULL;
}
else
{
pointer->next = (pointer->next)->next;
}
return temp;
}
pointer = pointer->next;
}
}
return NULL;
}
/*以上为链表操作,不可直接调用已有的链表头尾指针*/
/*
进程管理区
*/
int check_doing()//检测是否有进程在执行,若没有则将执行就绪队列进程
{
if (running == NULL)
{
struct PCB* temp;
temp = chain_pop(&ready_listHEAD, &ready_listTAIL);
if (temp == NULL)
{
if (wait_listHEAD == NULL)
{
printf("CPU任务完成\n");
return 2;//这种情况为系统无任务执行,完全空闲
}
else
{
printf("CPU正在闲逛\n");
return 3;//这种情况为系统阻塞队列里仍有任务,但其他队列全部为空
}
}
else
{
temp->ready_time = 0;
chain_append(temp, &running, &running, 2);
printf("装载完成\n");
return 1;
}
}
return 0;//这种情况为有程序在运行
}
/*
返回值状态:
0.现在有程序在运行
1.装载成功
2.cpu运行结束
3.等待阻塞队列进程结束阻塞
*/
struct PCB* block_process(int time)//阻塞当前正在执行的进程,并将其加入到阻塞队列中
{
struct PCB* temp;
temp = chain_pop(&running, &running);
if (temp == NULL)
{
return NULL;
}
else
{
temp->block_time = time;
chain_append(temp, &wait_listHEAD, &wait_listTAIL, 3);
return temp;
}
check_doing();
}
void cancel_process(char name[])//撤销就绪队列或阻塞队列中的进程
{
struct PCB* temp = NULL;
if (temp == NULL)
{
temp = chain_delByName(name, &ready_listHEAD, &ready_listTAIL);
}
if (temp == NULL)
{
temp = chain_delByName(name, &wait_listHEAD, &wait_listTAIL);
}
if (temp == NULL)
{
printf("删除失败,请检查名称是否正确\n");
}
else
{
printf("删除成功!\n");
chain_appendInit(temp, &free_listHEAD, &free_listTAIL);
}
}
void re_processByName(char name[])//通过名称把阻塞态恢复到就绪态
{
struct PCB* temp = NULL;
temp = chain_delByName(name, &wait_listHEAD, &wait_listTAIL);
if (temp == NULL)
{
printf("恢复失败,请检查名称是否正确\n");
}
else
{
temp->block_time = 0;
chain_append(temp, &ready_listHEAD, &ready_listTAIL, 1);
printf("恢复成功!\n");
}
}
void re_processByPointer(struct PCB* targetpointer)//通过指针将阻塞态恢复到就绪态
{
struct PCB* temp = NULL;
if (targetpointer == NULL)
{
;
}
else
{
temp = chain_delByPointer(targetpointer, &wait_listHEAD, &wait_listTAIL);
}
if (temp== NULL)
{
printf("恢复失败,请检查名称是否正确\n");
}
else
{
temp->block_time = 0;
chain_append(temp, &ready_listHEAD, &ready_listTAIL, 1);
printf("恢复成功!\n");
}
}
int create_process(char name[], int server_time)//创建进程函数!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!要使用的临界资源的整个流程没有实现
{
int i;
for (i = 0; i < 10; ++i)
{
if (!strcmp(name, PCBS[i].name))
{
printf("名称重复\n");
return 0;
}
}
struct PCB* temp;
temp = chain_pop(&free_listHEAD, &free_listTAIL);
if (temp == NULL)
{
return 0;
}
else
{
strcpy_s(temp->name, name);
temp->server_time = server_time;
/*
在此处给新创建的进程赋值
*/
chain_append(temp, &ready_listHEAD, &ready_listTAIL, 1);
return 1;
}
check_doing();
}
void show_process(struct PCB* free_list, struct PCB* ready_list, struct PCB* wait_list)//将目前系统内的所有进程队列(包括就绪,空闲,执行态)全部打印出来
{
printf("PCB名称\tPCB状态\t服务时间\t等待时间\t阻塞时间\n");
for (int i = 0; i < 10; ++i)
{
printf("%s\t%d\t%d\t%d\t%d\n", PCBS[i].name, PCBS[i].state, PCBS[i].server_time, PCBS[i].ready_time, PCBS[i].block_time);
}
printf("free_list///\n");
while (free_list != NULL && free_list->next != NULL)
{
printf("%s\t%d\t%d\t%d\t%d\n", free_list->name, free_list->state, free_list->server_time, free_list->ready_time, free_list->block_time);
free_list = free_list->next;
}
if (free_list != NULL)
{
printf("%s\t%d\n", free_list->name, free_list->state);
}
printf("ready_list///\n");
while (ready_list != NULL && ready_list->next != NULL)
{
printf("%s\t%d\t%d\t%d\t%d\n", ready_list->name, ready_list->state, ready_list->server_time, ready_list->ready_time, ready_list->block_time);
ready_list = ready_list->next;
}
if (ready_list != NULL)
{
printf("%s\t%d\t%d\t%d\t%d\n", ready_list->name, ready_list->state, ready_list->server_time, ready_list->ready_time, ready_list->block_time);
}
printf("wait_list///\n");
while (wait_list != NULL && wait_list->next != NULL)
{
printf("%s\t%d\t%d\t%d\t%d\n", wait_list->name, wait_list->state,wait_list->server_time,wait_list->ready_time,wait_list->block_time);
wait_list = wait_list->next;
}
if (wait_list != NULL)
{
printf("%s\t%d\t%d\t%d\t%d\n", wait_list->name, wait_list->state, wait_list->server_time, wait_list->ready_time, wait_list->block_time);
}
printf("running///\n");
while (running != NULL && running->next != NULL)
{
printf("%s\t%d\t%d\t%d\t%d\n", running->name, running->state, running->server_time, running->ready_time, running->block_time);
running = running->next;
}
if (running != NULL)
{
printf("%s\t%d\t%d\t%d\t%d\n", running->name, running->state, running->server_time, running->ready_time, running->block_time);
}
}
void show_single_process(struct PCB* chain_head_point)
{
printf("whatever///\n");
while (chain_head_point != NULL && chain_head_point->next != NULL)
{
printf("%s\t%d\n", chain_head_point->name, chain_head_point->state);
chain_head_point = chain_head_point->next;
}
if (chain_head_point != NULL)
{
printf("%s\t%d\n", chain_head_point->name, chain_head_point->state);
}
}
struct PCB* chain_DoForEach(struct PCB** chain_head_point, struct PCB** chain_tail_point, int statue)
{
if (*chain_head_point == NULL)
{
return NULL;
}
else
{
struct PCB* pointer = *chain_head_point;
if (statue == 0)//使等待时间++
{
while (pointer != *chain_tail_point)
{
pointer->ready_time++;
pointer = pointer->next;
}pointer->ready_time++;
}
else if (statue == 1)//使阻塞时间--
{
while (pointer != *chain_tail_point && pointer!=NULL)
{
pointer->block_time--;
pointer = pointer->next;
}
if (pointer != NULL)
{
pointer->block_time--;
}
}
else if (statue == 2)//恢复阻塞时间清零的节点
{
struct PCB* temp;
while (pointer != NULL)
{
if (pointer->block_time <= 0)
{
temp = pointer;
pointer = pointer->next;
re_processByPointer(temp);
}
else
{
pointer = pointer->next;
}
}
}
}
return NULL;
}
/*
以下为cpu代码
*/
int sys_timer = 0;//系统计时时间片
int process_timer_limit = 0;
void go_around()
{
printf("CPU在闲逛\n");
}
void TIME_PASS()//检测阻塞时间,如果阻塞时间清零,则恢复
{
++sys_timer;
chain_DoForEach(&ready_listHEAD, &ready_listTAIL, 0);
chain_DoForEach(&wait_listHEAD, &wait_listTAIL, 1);
chain_DoForEach(&wait_listHEAD, &wait_listTAIL, 2);
//show_process(free_listHEAD, ready_listHEAD, wait_listHEAD);
//system("pause");
}
void CPU()
{
while (1)
{
//如果没有进程,则装载进程
int flag = check_doing();
if (flag == 1)
{
printf("下一进程装载成功\n");
}
else if (flag == 0)
{
if (sys_timer == running->server_time)//如果进程执行完毕,时间片归零,将进程PCB释放
{
char name[20];
strcpy_s(name, running->name);
printf("\t%s\t进程已执行完毕\n", name);
sys_timer = 0;
struct PCB* temp = chain_delByName(name, &running, &running);
chain_appendInit(temp, &free_listHEAD, &free_listTAIL);
}
else if (sys_timer == process_timer_limit)
{
char name[20];
int block_time = int(rand() % 10);
struct PCB* temp = NULL;
strcpy_s(name, running->name);
running->server_time -= process_timer_limit;
sys_timer = 0;
printf("时间片已耗尽,切换至下一个进程\n");
printf("\t%s\t进程剩余服务时间为%d\t\n", name, running->server_time);
temp = block_process(block_time);
}
TIME_PASS();
}
else if (flag == 2)
{
return;
}
else if (flag == 3)
{
TIME_PASS();
sys_timer = 0;
}
}
}
/*
简化操作区
*/
void CLEAN_BUFF()
{
char ch;
while ((ch = getchar()) != EOF && ch != '\n');
}
void CLEAR()
{
system("cls");
}
/*
初始化程序区
*/
void Init_PCBS()//初始化PCBS队列
{
int i;
for (i = 0; i < 9; ++i)
{
PCBS[i].state = 0;//将所有PCB置为空闲状态
PCBS[i].server_time = 0;//将时间片大小设置为0
memset(PCBS[i].device, 0, sizeof(PCBS[i].device));//将临界资源需求初始化
PCBS[i].next = &PCBS[i + 1];
PCBS[i].block_time = 0;
PCBS[i].ready_time = 0;
}
PCBS[9].state = 0;
}
void Init_System()
{
printf("请输入时间片大小\n");
scanf_s("%d", &process_timer_limit);
CLEAN_BUFF();
CLEAR();
while (1)
{
char command[30];
printf("\n#user > ");
gets_s(command);
if (!strcmp(command, "clear") || !strcmp(command, "cls"))
{
CLEAR();
}
else if (!strcmp(command, "run"))
{
CPU();
}
else if (!strncmp(command, "load ", 5) && strlen(command)>5)
{
char name[20];
int device[5];
memset(device, 0, sizeof(device));
int server_time = 0;
strcpy_s(name, command + 5);
if (name == NULL)
{
printf("创建进程失败\n");
break;
}
printf("请输入所需的服务时间:\n");
scanf_s("%d", &server_time);
CLEAN_BUFF();
printf("程序是否需要使用键盘,鼠标,打印机:\n");
scanf_s("%d %d %d", &device[keyboard], &device[mouse], &device[printer]);
CLEAN_BUFF();
if (server_time != 0)
{
if (create_process(name, server_time) == 1)
{
printf("已装载进程\t%s\n", name);
}
else
{
printf("创建进程\t%s\t失败\n", name);
}
}
}
else if (!strcmp(command, "help"))
{
printf("啥也没有(= W =)\n");
}
else if (!strcmp(command, "exit"))
{
exit(0);
}
else
{
printf("未知命令,若想查看更多命令用法,请输入help命令\n");
}
}
}
int main()
{
Init_PCBS();
Init_System();
}
之后会继续更新其他部分