- 实验目的与要求
本实验要求学生模拟设计一个驱动调度程序,观察驱动调度程序的动态运行过程。以此来加深对驱动调度职能的理解和掌握。
设计模拟电梯调度的算法,来对磁盘进行移臂和旋转调度。
- 数据结构及符号说明
本节将说明设计的电梯调度算法中相关的数据结构和全局变量。
Request:作为结构体,包含4个元素,用于记录I/O请求相关信息。
① name:字符串,记录请求的进程名。
② cylinder:整形,记录访问磁盘的柱面号。
③ magnetic:整形,记录访问磁盘的磁道号。
④ record:整形,记录访问的物理记录号。
Table:Request数组,请求I/O表,记录目前所有请求磁盘访问的信息。
currentProcess:Request结构体类型,指向当前得到磁盘访问资源的进程的Request项。
tableNum:整形,记录I/O请求表内的请求记录的数目。
- 实验截图
- 源代码
#include <string>
#include <iomanip> // setw
#include <iostream>
using namespace std;
#define MAXCYLINDERNUMBER 200
#define MAXMAGNETICNUMBER 20
#define MAXRECORDNUMBER 8
struct Request
{ //请求I/O表
string name; //进程名
int cylinder = -1; //柱面号
int magnetic = -1; //磁道号
int record = -1; //物理记录号
} Table[100], currentProcess;
int tableNum = 0; //请求I/O表记录数
void InitcurrentProcess() //初始化初始进程
{
currentProcess.name = "初始进程";
currentProcess.cylinder = 0;
currentProcess.magnetic = 0;
currentProcess.record = 0;
//假定表中已经存在的请求
Table[0].name = "P1";
Table[0].cylinder = 10;
Table[0].magnetic = 3;
Table[0].record = 2;
Table[1].name = "P2";
Table[1].cylinder = 54;
Table[1].magnetic = 12;
Table[1].record = 7;
Table[2].name = "P3";
Table[2].cylinder = 10;
Table[2].magnetic = 15;
Table[2].record = 1;
}
int FindNearest()
{
int min = 8, minSub = -1; //最小距离,最小距离的编号
int distance = 8; //当前距离
for (int i = 0; i < tableNum; i++)
{
if (Table[i].cylinder == currentProcess.cylinder)
{
distance = abs(Table[i].record - currentProcess.record);
if (distance < min)
{
min = distance;
minSub = i;
}
}
}
return minSub;
}
void print_io() //打印请求I/O表
{
cout << "***************************请求I/O表**************************" << endl;
cout << "进程名: 柱面号: 磁道号: 物理记录号:" << endl;
for (int i = 0; i < tableNum; i++)
cout << setfill(' ') << setw(6) << Table[i].name << setfill(' ') << setw(15) << Table[i].cylinder << setfill(' ') << setw(16) << Table[i].magnetic << setfill(' ') << setw(17) << Table[i].record << endl;
cout << "------------------This is the dividing line.------------------" << endl;
}
void PrintProcess(bool direction)
{
string directionStr;
if (direction == 1)
directionStr = "up";
else
directionStr = "down";
cout << "************************选中的进程信息************************" << endl;
cout << "进程名: 柱面号: 物理记录号: 方向:" << endl;
cout << setfill(' ') << setw(6) << currentProcess.name << setfill(' ') << setw(15) << currentProcess.cylinder << setfill(' ') << setw(16) << currentProcess.record << setfill(' ') << setw(19) << directionStr << endl;
cout << "------------------This is the dividing line.------------------" << endl;
}
// 遍历请求表判断是否有与当前柱面号相同的访问者
int CylinderSameJudge()
{
for (int i = 0; i < tableNum; i++)
{
if (Table[i].cylinder == currentProcess.cylinder)
return i;
}
return -1;
}
int CylinderGreaterMin()
{
int difference = 200; //柱面号之差
int minrecord = 8; //最小物理记录
int minCylinder = currentProcess.cylinder + difference; //选择出的最小柱面号
int bestProcess; //选择出的最佳请求号
for (int i = 0; i < tableNum; i++)
{
if (abs(Table[i].cylinder - currentProcess.cylinder) < difference && Table[i].cylinder > currentProcess.cylinder)
{
difference = Table[i].cylinder - currentProcess.cylinder;
minCylinder = currentProcess.cylinder + difference;
}
}
for (int i = 0; i < tableNum; i++)
{
if (Table[i].cylinder == minCylinder && Table[i].record < minrecord)
{
minrecord = Table[i].record;
bestProcess = i;
}
}
if (difference == 200) //没有比当前柱面号大的访问请求
return -1;
else
return bestProcess;
}
int CylinderLessMax()
{
int difference = 200; //柱面号之差
int minrecord = 8; //最小物理记录
int maxCylinder = currentProcess.cylinder - difference; //选择出的最大柱面号
int bestProcess; //选择出的最佳请求号
for (int i = 0; i < tableNum; i++)
{
if (abs(Table[i].cylinder - currentProcess.cylinder) < difference && Table[i].cylinder < currentProcess.cylinder)
{
difference = abs(Table[i].cylinder - currentProcess.cylinder);
maxCylinder = currentProcess.cylinder - difference;
}
}
for (int i = 0; i < tableNum; i++)
{
if (Table[i].cylinder == maxCylinder && Table[i].record < minrecord)
{
minrecord = Table[i].record;
bestProcess = i;
}
}
if (difference == 200) //没有比当前柱面号小的访问请求
return -1;
else
return bestProcess;
}
void PopProcess(int process)
{
for (int i = process; i < tableNum; i++)
{
Table[i] = Table[i + 1];
}
tableNum--;
}
void Scan()
{
int process; //选择的进程号
bool direction = 1; //方向0=out,1=in,默认移臂方向为向里移
print_io();
if (tableNum == 0)
{ //无等待访问者
cout << "无等待访问者!!!" << endl;
return;
}
else //有等待访问者
{
if (CylinderSameJudge() != -1) // 有与当前柱面号相同的访问者
{
process = FindNearest(); // 找到旋转距离最短的访问者
}
else // 没有与当前柱面号相同的访问者
{
if (direction == 1) // 移臂方向为向里
{
process = CylinderGreaterMin();
if (process == -1) // 没有比当前柱面号大的访问请求
{
direction = 0;
process = CylinderLessMax();
}
}
else //移臂方向为向外
{
process = CylinderLessMax();
if (process == -1) //没有比当前柱面号小的访问请求
{
direction = 1;
process = CylinderGreaterMin();
}
}
}
currentProcess = Table[process];
PrintProcess(direction);
PopProcess(process);
}
return;
}
void Accept()
{
string select;
do
{
Request temp;
cout << "输入:进程名、柱面号、磁道号、物理记录号" << endl;
cin >> temp.name >> temp.cylinder >> temp.magnetic >> temp.record;
if (temp.cylinder < MAXCYLINDERNUMBER && temp.magnetic < MAXMAGNETICNUMBER && temp.record < MAXRECORDNUMBER)
{
Table[tableNum] = temp;
tableNum++;
cout << "登记成功! exit.退出 others.继续" << endl;
cin >> select;
}
else
cout << "输入错误,请重输!!! 柱面号需小于200,磁道号需小于20,物理记录号需小于8." << endl;
} while (select != "exit");
cout << "------------------This is the dividing line.------------------" << endl;
}
int main()
{
float roundNumber;
string select;
InitcurrentProcess(); //初始化当前位置
for (int i = 0; Table[i].cylinder != -1; i++) //统计IO请求表中请求数目
tableNum++;
do
{
cout << "*******Simulate elevator scheduling algorithms********" << endl;
cout << "Enter a random number in the range [0,1] !!!" << endl;
cin >> roundNumber;
if (roundNumber > 0.5)
Scan();
else
Accept();
getchar();
cout << "是否继续进行电梯调度算? exit.退出 others.继续" << endl;
cin >> select;
} while (select != "exit");
return 0;
}