1、理解设备管理的概念和任务。
2、掌握独占设备的分配、回收等主要算法的原理并编程实现。
设备管理是指计算机系统对除CPU和内存以外的所有输入、输出设备的管理。设备管理不但要管理实际I/O操作的设备(如磁盘机、打印机),还要管理诸如设备控制器、DMA控制器、中断控制器、I/O处理机(通道)等支持设备。如何有效而又方便地管理好种类繁多的设备是设备管理的重要任务。
设备管理的目标:提高设备的利用率。为此,应尽量提高CPU与I/O设备之间的并行操作程度;为用户提供方便、统一的界面。所谓方便,是指用户能独立于具体设备的复杂物理特性之外而方便地使用设备。所谓统一,是指对不同的设备尽量使用统一的操作方式。
实验内容:编写程序实现对独占设备的分配回收的模拟。
代码(详情见代码注释):
#include
#include
using namespace std;
//进程类
class PCB
{
public:
//构造函数
PCB(string n, string e, int nu)
{
name = n;
equipment = e;
num = nu;
next = NULL;
}
string name;//进程名
string equipment;//所需设备类
int num;//设备相对号
PCB* next;
};
//设备控制表
class DCT
{
public:
DCT()
{
state = 0;
work_now = new PCB("空", "", NULL);
wait = NULL;
}
int state;//设备状态
PCB* work_now;//当前运行的进程
PCB* wait;//设备队列队首指针
};
//SDT节点
class SDT_node
{
public:
SDT_node(string eq, string i)
{
equipment = eq;
id = i;
}
string equipment;//设备类
string id;//设备标识符
DCT dct;//设备控制表
};
//SDT
class SDT
{
public:
SDT(int i1,int i2,int i3,int i4)
{
Len[0] = i1; Len[1] = i2;
Len[2] = i3; Len[3] = i4;
for (int i = 0; i < i1; i++)
{
mouse[i] = new SDT_node("鼠标", "M" + to_string(i));
}
for (int i = 0; i < i2; i++)
{
keyboard[i] = new SDT_node("键盘", "K" + to_string(i));
}
for (int i = 0; i < i3; i++)
{
screen[i] = new SDT_node("显示屏", "S" + to_string(i));
}
for (int i = 0; i < i4; i++)
{
printer[i] = new SDT_node("打印机", "P" + to_string(i));
}
}
void show();
void show_class();
void add(PCB *work);
void del(string equipment, int num);
private:
SDT_node* mouse[10];//鼠标
SDT_node* keyboard[10];//键盘
SDT_node* screen[10];//显示器
SDT_node* printer[10];//打印机
int Len[4];
};
//显示系统设备表(包括各阻塞队列)
void SDT::show()
{
cout << "————————————————————————————————————————————" << endl;
cout << " 系统设备表SDT" << endl;
cout << "设备标识 ";
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < Len[i]; j++)
{
if (i == 0)
{
cout << mouse[j]->id << "\t";
}
else if (i == 1)
{
cout << keyboard[j]->id << "\t";
}
else if (i == 2)
{
cout << screen[j]->id << "\t";
}
else if (i == 3)
{
cout << printer[j]->id << "\t";
}
}
}
cout << endl;
cout << "设备类 ";
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < Len[i]; j++)
{
if (i == 0)
{
cout << mouse[j]->equipment << "\t";
}
else if (i == 1)
{
cout << keyboard[j]->equipment << "\t";
}
else if (i == 2)
{
cout << screen[j]->equipment << "\t";
}
else if (i == 3)
{
cout << printer[j]->equipment << "\t";
}
}
}
cout << endl;
cout << "设备状态 ";
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < Len[i]; j++)
{
if (i == 0)
{
cout << mouse[j]->dct.state << "\t";
}
else if (i == 1)
{
cout << keyboard[j]->dct.state << "\t";
}
else if (i == 2)
{
cout << screen[j]->dct.state << "\t";
}
else if (i == 3)
{
cout << printer[j]->dct.state << "\t";
}
}
}
cout << endl;
cout << "当前运行 ";
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < Len[i]; j++)
{
if (i == 0)
{
cout << mouse[j]->dct.work_now->name << "\t";
}
else if (i == 1)
{
cout << keyboard[j]->dct.work_now->name << "\t";
}
else if (i == 2)
{
cout << screen[j]->dct.work_now->name << "\t";
}
else if (i == 3)
{
cout << printer[j]->dct.work_now->name << "\t";
}
}
}
cout << endl;
//显示阻塞队列
cout << "\n阻塞队列:" << endl;
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < Len[i]; j++)
{
if (i == 0)
{
cout << mouse[j]->id << ":";
PCB *temp = mouse[j]->dct.wait;
while (temp != NULL)
{
cout << " --> " << temp->name;
temp = temp->next;
}
cout << endl;
}
else if (i == 1)
{
cout << keyboard[j]->id << ":";
PCB *temp = keyboard[j]->dct.wait;
while (temp != NULL)
{
cout << " --> " << temp->name;
temp = temp->next;
}
cout << endl;
}
else if (i == 2)
{
cout << screen[j]->id << ":";
PCB *temp = screen[j]->dct.wait;
while (temp != NULL)
{
cout << " --> " << temp->name;
temp = temp->next;
}
cout << endl;
}
else if (i == 3)
{
cout << printer[j]->id << ":";
PCB *temp = printer[j]->dct.wait;
while (temp != NULL)
{
cout << " --> " << temp->name;
temp = temp->next;
}
cout << endl;
}
}
}
cout << endl;
cout << "————————————————————————————————————————————\n" << endl;
}
//显示设备类表
void SDT::show_class()
{
cout << "————————————————————" << endl;
cout << " 设备类表" << endl;
cout << "设备类 鼠标\t键盘\t显示屏\t打印机" << endl;
cout << "设备数 " << Len[0] << "\t" << Len[1] << "\t" << Len[2] << "\t" << Len[3] << "\t" << endl;
cout << "————————————————————\n" << endl;
}
//设备分配
void SDT::add(PCB *work)
{
SDT_node** point;
//找到对应设备类
if (work->equipment == "鼠标")
{
point = mouse;
}
else if(work->equipment == "键盘")
{
point = keyboard;
}
else if (work->equipment == "显示屏")
{
point = screen;
}
else if (work->equipment == "打印机")
{
point = printer;
}
else
{
cout << "所需设备类不存在" << endl;
return;
}
if (point[work->num]->dct.state == 0)
{
//若当前设备为空,则分配给该进程
point[work->num]->dct.state = 1;
point[work->num]->dct.work_now = work;
cout << "设备分配成功,进程" << work->name << "正在运行" << endl;
}
else
{
//若设备不空闲则加入阻塞队列
PCB *temp = point[work->num]->dct.wait;
if (temp == NULL)
{//如果阻塞队列为空
point[work->num]->dct.wait = work;
}
else
{//若阻塞队列不为空则找到队尾,并放入
while (temp->next != NULL)
{
temp = temp->next;
}
temp->next = work;
}
cout << "该设备被占用,进程"<name<<"被放入阻塞队列" << endl;
}
}
//设备回收
void SDT::del(string equipment, int num)
{
SDT_node** point;
//找到对应设备类
if (equipment == "鼠标")
{
point = mouse;
}
else if (equipment == "键盘")
{
point = keyboard;
}
else if (equipment == "显示屏")
{
point = screen;
}
else if (equipment == "打印机")
{
point = printer;
}
else
{
cout << "回收设备类不存在" << endl;
return;
}
if (point[num]->dct.wait == NULL)
{
//阻塞队列为空
point[num]->dct.state = 0;
free(point[num]->dct.work_now);
point[num]->dct.work_now = new PCB("空", "", NULL);
cout << "设备" << point[num]->id << "被成功回收" << endl;
}
else
{
//阻塞队列不为空,调入等待进程
free(point[num]->dct.work_now);
cout << "设备" << point[num]->id << "被成功回收" << endl;
cout << "设备" << point[num]->id << "阻塞队列存在进程" << endl;
point[num]->dct.work_now = point[num]->dct.wait;
point[num]->dct.wait = point[num]->dct.wait->next;
cout << "进程" << point[num]->dct.work_now->name << "调入,设备被再次占用" << endl;
}
}
int main()
{
cout << "**************************" << endl;
cout << "*** 设备管理器 ***" << endl;
cout << "*** 1.显示设备类表 ***" << endl;
cout << "*** 2.显示系统设备表 ***" << endl;
cout << "*** 3.设备分配 ***" << endl;
cout << "*** 4.设备回收 ***" << endl;
cout << "*** 5.退出 ***" << endl;
cout << "**************************\n" << endl;
//指定各类设备数量
int a, b, c, d;
cout << "请依次输入4类设备的数量:" << endl;
cin >> a >> b >> c >> d;
SDT My_SDT(a, b, c, d);
int flag;
while (true)
{
cout << "\n请选择功能:";
cin >> flag;
if (flag == 1)
{
//显示设备类表
My_SDT.show_class();
}
else if (flag == 2)
{
//显示系统设备表
My_SDT.show();
}
else if (flag == 3)
{
//设备分配
string name;//进程名
string equipment;//所需设备类
int num;//设备相对号
cout << "请输入进程名:";
cin >> name;
cout << "请输入所需设备类:";
cin >> equipment;
cout << "请输入设备相对号:";
cin >> num;
PCB *work = new PCB(name, equipment, num);
My_SDT.add(work);
}
else if (flag == 4)
{
//设备回收
string equipment;//设备类
int num;//设备相对号
cout << "请输入回收设备类:";
cin >> equipment;
cout << "请输入设备相对号:";
cin >> num;
My_SDT.del(equipment, num);
}
else if (flag == 5)
{
//退出
cout << "成功退出!" << endl;
break;
}
}
return 0;
}
运行演示:
这一次的实验是有一定难度的,我觉得困难主要是在实验的复杂程度上。这次我建了四个类来实现设备管理的功能:1、进程类PCB;2、设备控制表DCT;3、SDT节点SDT_node;4、系统设备表SDT。其中DCT、SDT_node、SDT是依次嵌套的,SDT使用了SDT_node,而SDT_node又使用了DCT。这里使用类的组合的原因是:SDT是整个系统的设备表,包括所有设备类的所有设备;而SDT_node是用来表示单个设备的,而每个设备都需要一个单独的设备控制表,所以我又建立了一个DCT类。由于这个类的组合比较复杂,类的初始化、修改的时候就比较复杂,而且这其中又涉及到类的指针、类的指针的指针,这就稍微有点烧脑,我也是认真整理好久思路,并在debug中不断改进。
我在实验的基本要求上稍微扩充了两点,其一是题目中各类设备数是固定的。我设计的就灵活一些,各类设备的数量是可以任意指定的,这一点也使得问题稍微复杂了些;其二就是进程的申请时我使用的是设备相对号,这一点虽然老师说了这比较复杂是不要求的,但是我觉得对于这个问题自己有解决思路,所以就仍然加入进来了。