一、要求
1、假定模拟系统中已有键盘、鼠标、打印机和显示器四个设备,另有三个控制器和两个通道。
2、实现上述设备、控制器以及通道的层次关系,同时能够添加或删除新的设备、控制器或通道。
3、通过键盘命令模拟进程执行过程中提出的设备分配或释放请求,并为此请求分配或释放设备。分配设备成功后可将进程状态调整为阻塞,释放设备后变为就绪状态。
4、分配设备时应如果该设备已被其它进程占用,则设备分配失败,请求进程进入阻塞状态,同时等待该设备的释放。如果设备空闲,进程占用设备的同时还应提出申请控制器请求,直到与设备相关的通道都已申请成功为止。
提示:
1、设备管理子系统涉及到系统设备表(SDT)、通道控制表(CHCT)、控制器控制表(COCT)和设备控制表(DCT)来体现输入输出系统的四级结构和三级控制。应实现上述数据结构来完成对外围设备的管理。
2、设备、控制器或通道的释放应引起对应节点的等待队列中的第一个阻塞进程被唤醒。如果被唤醒的进程还未完成申请操作,应继续执行上级节点的申请操作。
二、实现
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#define OK 1
#define ERROR 0
#define FREE 1
#define BUSY 0
#define READY 1
#define BLOCK 0
typedef int Status;
typedef struct PCB
{
char name[20]; // 进程名
char state; // 进程状态 R——表示“执行”状态 W——表示“就绪”状态 B——表示“阻塞”状态
struct PCB *next;
} PCB;
typedef struct Node
{
char name[15]; // 通道/控制器/设备标识符
Status state; // 状态,BUSY/FREE
struct PCB *process; // 占用该节点的进程
struct PCB *waitinglist; // 等待该节点的进程队列
struct Node *next; // 下一个节点,即下一个通道/控制器/设备
struct Node *parent; // 父节点,即通道/控制器/设备
} Node;
struct Node *SDT; // 系统设备表
struct Node *CHCT; // 通道队列头节点
struct Node *COCT; // 控制器队列头节点
struct Node *DCT; // 设备队列头节点
// Node进队
Status enterQ(Node *q, Node *p)
{
if (q->next == NULL)
{
q->next = p;
return OK;
}
else
{
while (q)
{
if (q->next == NULL)
{
q->next = p;
p->next = NULL;
return OK;
}
q = q->next;
}
}
}
// Process进队
Status enterP(PCB *q, PCB *p)
{
if (q->next == NULL)
{
q->next = p;
return OK;
}
else
{
while (q)
{
if (q->next == NULL)
{
q->next = p;
p->next = NULL;
return OK;
}
q = q->next;
}
}
}
// 出队
Node *exitQ(Node *q)
{
Node *p;
if (q->next == NULL)
{
exit(0);
}
else
{
p = q->next;
q->next = p->next;
return p;
}
}
// 创建节点
Node *createNode(char name[10])
{
Node *newNode = (Node *)malloc(sizeof(Node));
strcpy(newNode->name, name);
newNode->state = FREE;
newNode->process = newNode->waitinglist = NULL;
newNode->next = newNode->parent = NULL;
return newNode;
}
// 创建进程
PCB *createProcess(char name[20])
{
PCB *newProcess = (PCB *)malloc(sizeof(PCB));
strcpy(newProcess->name, name);
newProcess->state = FREE;
return newProcess;
}
// 展示各设备关系
void display(Node *q)
{
q = q->next; // 从第一个节点开始
while (q)
{
printf("name:%-12s parent:%-12s process:%-12s wattings:%-12s next:%-12s state:%-12d\n", q->name, q->parent->name, q->process->name, q->waitinglist->name, q->next->name, q->state);
q = q->next;
}
}
Status init()
{
/**
* 键盘、鼠标、打印机和显示器4个设备
* 3个控制器
* 2个通道
*/
SDT = (Node *)malloc(sizeof(Node));
DCT = (Node *)malloc(sizeof(Node));
COCT = (Node *)malloc(sizeof(Node));
CHCT = (Node *)malloc(sizeof(Node));
SDT->state = DCT->state = COCT->state = CHCT->state = FREE;
SDT->process = DCT->process = COCT->process = CHCT->process = SDT->waitinglist = DCT->waitinglist = COCT->waitinglist = CHCT->waitinglist = NULL;
SDT->next = DCT->next = COCT->next = CHCT->next = SDT->parent = DCT->parent = COCT->parent = CHCT->parent = NULL;
// 4个设备keyboard mouse printer display,然后入队SDT、DCT
enterQ(SDT, createNode("keyboard-sdt"));
enterQ(SDT, createNode("mouse-sdt"));
enterQ(SDT, createNode("printer-sdt"));
enterQ(SDT, createNode("display-sdt"));
enterQ(DCT, createNode("keyboard-dct"));
enterQ(DCT, createNode("mouse-dct"));
enterQ(DCT, createNode("printer-dct"));
enterQ(DCT, createNode("display-dct"));
// 3个控制器 controller1-3,然后入队
enterQ(COCT, createNode("Controller-1"));
enterQ(COCT, createNode("Controller-2"));
enterQ(COCT, createNode("Controller-3"));
// 2个通道,然后入队
enterQ(CHCT, createNode("Channel-1"));
enterQ(CHCT, createNode("Channel-2"));
/**
* 确定三层关系。
* 系统设备表4个设备对应4个设备控制表。
* 4个设备控制表都对应控制器控制表1
* 控制器控制表1对应通道控制表1
*/
SDT->next->parent = DCT->next;
SDT->next->next->parent = DCT->next->next;
SDT->next->next->next->parent = DCT->next->next->next;
SDT->next->next->next->next->parent = DCT->next->next->next->next;
DCT->next->parent = COCT->next;
DCT->next->next->parent = COCT->next;
DCT->next->next->next->parent = COCT->next;
DCT->next->next->next->next->parent = COCT->next;
COCT->next->parent = CHCT->next;
/**
* 设置不相关的控制器控制表和通道控制表
*/
COCT->next->next->parent = COCT->next->next->next->parent = NULL;
CHCT->next->next->parent = NULL;
}
void SetParent(Node *q, Node *p, char parentName[15])
{
q = q->next; // 从第一个找起
p = p->next;
while (q)
{
if (q->next == NULL)
{
while (p)
{
if (strcmp(parentName, p->name) == 0)
{
q->parent = p;
}
p = p->next;
}
}
q = q->next;
}
}
// 添加设备, 设备:1、2;控制器:3;通道:4
void addDevice(int num, char name[15], char parentName[15])
{
switch (num)
{
case 1:
{
enterQ(SDT, createNode(name));
SetParent(SDT, DCT, parentName);
break;
}
case 2:
{
enterQ(DCT, createNode(name));
SetParent(DCT, COCT, parentName);
break;
}
case 3:
{
enterQ(COCT, createNode(name));
SetParent(COCT, CHCT, parentName);
break;
}
case 4:
{
enterQ(CHCT, createNode(name));
break;
}
}
}
// 删除设备
void deleteDevice(Node *q, char name[15])
{
Node *s;
while (q)
{
if (strcmp(q->next->name, name) == 0)
{
s = q->next;
printf("\n你删除的是%s结果如下:\n", s->name);
free(s);
q->next = q->next->next;
}
q = q->next;
}
}
// 分配设备
void allocateDevice(PCB *process, Node *a, Node *b, Node *c, Node *d, char name[15])
{
a = a->next; // SDT
while (a)
{
if (strcmp(a->name, name) == 0)
{
if (a->state == FREE)
{
a->state = BUSY; // 设为BUSY
a->process = process; // 将该系统控制表的进程队列设置为当前进程
b = b->next; // DCT
while (b)
{
if (strcmp(a->parent->name, b->name) == 0)
{
if (b->state == FREE)
{
b->state = BUSY;
b->process = process;
c = c->next; // COCT
while (c)
{
if (strcmp(b->parent->name, c->name) == 0)
{
if (c->state == FREE)
{
c->state = BUSY;
c->process = process;
d = d->next; // CHCT
while (d)
{
if (strcmp(c->parent->name, d->name) == 0)
{
if (d->state == FREE)
{
d->state = BUSY;
d->process = process;
// 走到这一步说明成功分配!
// 设置进程为阻塞
printf("进程%s分配设备成功\n", process->name);
process->state = BLOCK;
return;
}
else
{
process->state = BLOCK;
enterP(CHCT->waitinglist, process);
}
}
d = d->next;
}
}
else
{
process->state = BLOCK;
enterP(COCT->waitinglist, process);
}
}
c = c->next;
}
}
else
{
process->state = BLOCK;
enterP(DCT->waitinglist, process);
}
}
b = b->next;
}
}
else
{
process->state = BLOCK;
enterP(SDT->waitinglist, process);
}
}
a = a->next;
}
}
// 回收设备
void recycleDevice(PCB *process, Node *a, Node *b, Node *c, Node *d, char name[15])
{
a = a->next;
while (a)
{
if (strcmp(a->name, name) == 0)
{
if (a->state == BUSY)
{
a->state = FREE;
a->process = NULL;
b = b->next;
while (b)
{
if (strcmp(a->parent->name, b->name) == 0)
{
if (b->state == BUSY)
{
b->state = FREE;
b->process = NULL;
c = c->next;
while (c)
{
if (strcmp(b->parent->name, c->name) == 0)
{
if (c->state == BUSY)
{
c->state = FREE;
c->process = NULL;
d = d->next;
while (d)
{
if (strcmp(c->parent->name, d->name) == 0)
{
if (d->state == BUSY)
{
d->state = FREE;
d->process = NULL;
// 走到这一步说明成功回收!
// 设置进程为就绪
printf("进程%s回收设备成功\n", process->name);
process->state = READY;
free(process);
return;
}
}
d = d->next;
}
}
}
c = c->next;
}
}
}
b = b->next;
}
}
}
a = a->next;
}
}
int main()
{
init();
Node *a[4] = {SDT, DCT, COCT, CHCT};
printf("-------初始总览-----\n");
for (int i = 0; i < 4; i++)
{
display(a[i]);
}
printf("\n\n\n");
// 添加设备
printf("添加了Channel-3,结果如下:\n");
addDevice(4, "Channel-3", NULL);
display(a[3]);
printf("添加了Controller-4,结果如下:\n");
addDevice(3, "Controller-4", "Channel-3");
display(a[2]);
printf("添加了video-dct,结果如下:\n");
addDevice(2, "video-dct", "Controller-4");
display(a[1]);
printf("添加了video-sdt,结果如下:\n");
addDevice(1, "video-sdt", "video-dct");
display(a[0]);
printf("-------添加总览-----\n");
for (int i = 0; i < 4; i++)
{
display(a[i]);
}
printf("\n\n\n");
// 删除设备
deleteDevice(SDT, "video-sdt");
display(a[0]);
deleteDevice(DCT, "video-dct");
display(a[1]);
deleteDevice(COCT, "Controller-4");
display(a[2]);
deleteDevice(CHCT, "Channel-3");
display(a[3]);
printf("----删除总览----\n");
for (int i = 0; i < 4; i++)
{
display(a[i]);
}
printf("\n\n\n");
// 分配设备
PCB *process = createProcess("newProcess");
process->next = NULL;
process->state = FREE;
allocateDevice(process, SDT, DCT, COCT, CHCT, "keyboard-sdt");
printf("----分配总览----\n");
for (int i = 0; i < 4; i++)
{
display(a[i]);
}
printf("\n\n\n");
// 回收设备
recycleDevice(process, SDT, DCT, COCT, CHCT, "keyboard-sdt");
printf("----回收总览----\n");
for (int i = 0; i < 4; i++)
{
display(a[i]);
}
}