2.完整程序
#include<iostream> #include<vector> #include<queue> #include<iomanip> #include<cstdlib> #include<cmath> using namespace std; vector<int> sameCylinderpos;//当前柱面号相同访问者 struct process { int id;//进程号 int cylinder;//柱面号 int track;//盘面号 int sector;//扇区号 process(int _id = 0, int _cylinder = 0, int _track = 0, int _sector = 0) { id = _id; cylinder = _cylinder; track = _track; sector = _sector; } void print() {//输出 cout << "Process id:" <<setw(5)<< id; cout << " Cylinder id:" << setw(5)<<cylinder ; cout << " Track id:" << setw(5)<<track; cout << " Sector id:" << setw(5)<<sector; cout << endl; } }; bool direction;//0 up,1out int curCylinder;//当前柱面号 int curSector;//当前扇区号 vector<process> iorequests;//请求I/O表 void init() {//初始化 direction = 0; curCylinder = 0; curSector = 0; } void driveScheduling() {//驱动调度 if (iorequests.empty()) {//当前有无等待访问者 cout << "\nNo requests!\n"; return; } else { cout << "\n*****************************************\n"; for (int i = 0; i < iorequests.size(); i++) iorequests[i].print(); cout << "\n*****************************************\n"; bool sameCylinder = 0;//有无与当前柱面号相同访问者 bool greaterCylinder = 0;//有无大于当前柱面号访问者 bool lesserCylinder = 0;//有无小于当前柱面号访问者 sameCylinderpos.clear(); int mingtCylinderpos=-1;//大于当前柱面号的最小者 int maxltCylinderpos=-1;//小于当前柱面号的最大者 int iorequestPos=0;//位置 for (int i = 0; i < iorequests.size(); i++) {//判断有无与当前柱面号相同访问者,比当前大的请求、比当前小的请求 if (iorequests[i].cylinder == curCylinder) { sameCylinder = 1; sameCylinderpos.push_back(i);//与当前柱面号相同的访问者,放入可变长数组中暂存 } if (iorequests[i].cylinder > curCylinder) {//从大于当前柱面号请求中选一个最小者 greaterCylinder = 1; if (mingtCylinderpos == -1) mingtCylinderpos = i; if (iorequests[i].cylinder < iorequests[mingtCylinderpos].cylinder) mingtCylinderpos = i; } if (iorequests[i].cylinder < curCylinder) {//从小于当前柱面号请求中选一个最大者 lesserCylinder = 1; if (maxltCylinderpos == -1) maxltCylinderpos = i; if (iorequests[i].cylinder > iorequests[maxltCylinderpos].cylinder) maxltCylinderpos = i; } } if (sameCylinder == 1) {//选使得旋转距离最短的访问者 int rotateDist = 20; iorequestPos = sameCylinderpos[0]; for (int i=0;i<sameCylinderpos.size();i++) { int pos = sameCylinderpos[i]; int& x = iorequests[pos].sector; int& y = curSector; int dist = ((x+8-y)%8); if (dist < rotateDist) {//选择能使旋转距离最短的访问者 rotateDist = dist; iorequestPos = pos; } } } else { if (direction == 0) { if (greaterCylinder) iorequestPos = mingtCylinderpos; else { direction = 1;//置移臂方向 iorequestPos = maxltCylinderpos; } } else { if (lesserCylinder) iorequestPos = maxltCylinderpos; else { direction = 0;//置移臂方向为往里 iorequestPos = mingtCylinderpos; } } } curCylinder = iorequests[iorequestPos].cylinder; curSector = iorequests[iorequestPos].sector; cout << "\n*****************************************\n"; iorequests[iorequestPos].print(); cout << "Current Cylinder:" << curCylinder << endl; cout << "Current Sector:" << curSector << endl; cout << "Current direction:"; if (direction == 0) cout << "up!" << endl; else cout << "down!" << endl; cout << "\n*****************************************\n"; iorequests.erase(iorequests.begin() + iorequestPos); } } void acceptRequest() { cout << "\nAccepting requests!"; cout << "\ninput request num:"; int n; cin >> n; if (n == 0) {//不发送请求 cout << "No requests!"; return; } else while(n--) { cout << "input process id,cylinder,track,sector"; int id, cylinder, track, sector; cin >> id >> cylinder >> track >> sector; process newp(id, cylinder, track, sector); iorequests.push_back(newp); } } void cpuwork() { srand(time(NULL)); while (1) { cout << "1. Drive scheduling 2.Accept Requests"; double opnum= rand() / double(RAND_MAX); if (opnum > 0.5) driveScheduling(); else acceptRequest(); cout << "Continue?Y/N"; char op; cin >> op; if (op == 'Y'); else break; } } int main() { init(); cpuwork(); }
(4)运行结果
打印驱动调度进程每次选择访问请求前的请求“I/O”表以及每次选中的进程名、访问的柱面号、物理记录号和当前移臂方向。打印的格式为:
首先,手动提交并输入5个进程号。
利用磁盘调度算法,在每次处理调度时,都打印了“请求I/O”表,并正确地运行了大于当前柱面号访问请求的最小者2号进程。当前移臂方向为向里移动。
在运行完一个进程后,提交一个新的I/O请求,柱面号比当前柱面号小。该请求会正确地在下一次磁盘调度时不会被运行到。
第二次磁盘调度时,选择了大于柱面号5的最小者。这个进程柱面号为10。
第三次磁盘调度前,再提交一个柱面号为10的新请求。
第三次磁盘调度时,因为有多个请求都在柱面号10,所以选择了旋转距离最短的访问者。从扇区号4移动到了扇区号5。
第四次磁盘调度时,同理,因为有多个请求都在柱面号10,所以选择了旋转距离最短的访问者。从扇区号5移动到了扇区号7。
第五次磁盘调度时,同理,因为还有请求都在柱面号10,所以选择了旋转距离最短的访问者。从扇区号7移动到了扇区号1。此时,磁盘已经转完了一圈。
第六次磁盘调度时,当前移臂方向为向里,选择了大于当前柱面号的最小者,20号柱面。
最后一次磁盘调度时,原移臂方向为向里,但没有大于当前柱面号的访问者,只能将当前移臂方向置为向外移动,并选择了小于20号柱面的访问请求中的最大者。最大者的柱面号为1,运行该进程。
通过这几组数据,测试完成了有当前柱面号相同的访问者,移臂向里移时有无比当前柱面号大的访问请求的情况。移臂向外时磁盘调度也与移臂向里的情况是相反的。体现了本程序的正确性。