实验报告
实验内容
硬盘调度: 编写 C 程序模拟实现课件 Lecture25 中的硬盘柱面访问调度算法包括 FCFS、SSTF、SCAN、C-SCAN、LOOK、C-LOOK,并设计输入用例验证结果。
实验环境
Ubuntu 20.04.2.0(64位)
基础知识
- FCFS(先来先服务): 根据进程请求访问磁盘的先后顺序进行调度。
例1:
例2:
如磁道请求队列为55、58、39、18、90、160、150、38、184,从100号开始。
- SSTF(最短寻道时间优先):其要求访问的磁道与当前磁头所在的磁道距离最近。
例1:
例2:
如磁道请求队列为55、58、39、18、90、160、150、38、184,从100号开始。
- SCAN(扫描算法): 磁臂从磁盘的一端开始向另一端移动,在到达每个柱面时为请求提供服务,直到到达磁盘的另一端,磁头的移动方向相反,服务继续进行。
例1:
例2:
如磁道请求队列为55、58、39、18、90、160、150、38、184,从100号开始。向磁道号增加方向访问。
- LOOK: LOOK就是对应SCAN的改进算法。因为SCAN中每次磁头都要走到磁道尽头,而实际过程中并不需要要求磁头走到尽头,而是到达该方向的最后一个请求后即可返回,这样可以避免一些不必要的磁头移动。
例1:
例2:
如磁道请求队列为55、58、39、18、90、160、150、38、184,从100号开始。向磁道号增加方向访问。
- CSCAN(循环扫描算法): 首先自里向外访问,当磁头移到最外的磁道后,磁头返回到最里的磁道,即将最小磁道号紧接着最大磁道号构成循环,继续循环扫描。
例1:
例2:
如磁道请求队列为55、58、39、18、90、160、150、38、184,从100号开始。
- CLOOK: CLOOK就是对应CSCAN的改进算法。因为CSCAN中每次磁头都要走到磁道尽头,而实际过程中并不需要要求磁头走到尽头,而是到达该方向的最后一个请求后即可返回,这样可以避免一些不必要的磁头移动。
例1:
例2:
如磁道请求队列为55、58、39、18、90、160、150、38、184,从100号开始。
(参考资料1:课件)
(参考资料2)
实验过程
规定硬盘只有200个磁道,从0~199:
一. 用以上例2作为输入样例:
-
FCFS结果:
与例2中的结果一致,计算所得的总寻道长度和平均寻道长度也正确。 -
SSTF结果:
与例2中的结果一致,计算所得的总寻道长度和平均寻道长度也正确。 -
SCAN结果:
可以看到,磁头需要走到磁盘一端的最后一个磁道才会往回移动,其他与例2中的结果一致,计算所得的总寻道长度和平均寻道长度也正确。 -
CSCAN结果:
可以看到,磁头需要走到磁盘一端的最后一个磁道才会往回移动,其他与例2中的结果一致,计算所得的总寻道长度和平均寻道长度也正确。 -
LOOK结果:
可以看到,磁头只需要走到其方向上的最后一个请求即可往回移动,与例2中的结果一致,计算所得的总寻道长度和平均寻道长度也正确。 -
CLOOK结果:
可以看到,磁头只需要走到其方向上的最后一个请求即可往回移动,与例2中的结果一致,计算所得的总寻道长度和平均寻道长度也正确。
一. 用以上例1作为另一输入样例:
-
FCFS结果:
-
SSTF结果:
-
SCAN结果:
-
CSCAN结果:
-
LOOK结果:
-
CLOOK结果:
代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define MAX_TASK 100
#define MAX_track 199
#define waiting 0
#define complete 1
// structure of task
typedef struct task
{
int track; // task's track
int stat; // task's state: wait or complete
} Task;
// structure of read-write head
typedef struct head
{
int track; // head's track
int seek_length; // total seek length
} Head;
void FCFS(Task task[], Head head, int task_n);
void SSTF(Task task[], Head head, int task_n);
void SCAN(Task task[], Head head, int task_n);
void CSCAN(Task task[], Head head, int task_n);
void LOOK(Task task[], Head head, int task_n);
void CLOOK(Task task[], Head head, int task_n);
int main()
{
printf("In this hard disk, the tracks is from 0 to %d.\n", MAX_track);
printf("\n");
int task_n = 9; // the number of tasks
printf("Please enter the number of task(<=100): ");
scanf("%d", &task_n);
if(task_n > 100){
printf("Error: value out of range!\n");
return -1;
}
printf("\n");
printf("Please enter the track in each task:\n");
Task task[task_n]; // array of task
for(int i = 0; i < task_n; i++){
printf("task %d(0 ~ %d): ", i, MAX_track);
scanf("%d", &task[i].track);
if(task[i].track > MAX_track || task[i].track < 0){
printf("Error: value out of range!\n");
return -1;
}
task[i].stat = waiting; // initialize task's state
}
// task[0].track = 55;
// task[1].track = 58;
// task[2].track = 39;
// task[3].track = 18;
// task[4].track = 90;
// task[5].track = 160;
// task[6].track = 150;
// task[7].track = 38;
// task[8].track = 184;
printf("\n");
Head head;
int head_track;
printf("Please enter initial track of read-write head(0 ~ %d): ", MAX_track);
scanf("%d", &head_track);
if(head_track > MAX_track || head_track < 0){
printf("Error: value out of range!\n");
return -1;
}
printf("\n");
// creat copy
head.track = head_track;
head.seek_length = 0;
Task task_FCFS[task_n];
for(int i = 0; i < task_n; i++){
task_FCFS[i].track = task[i].track;
task_FCFS[i].stat = task[i].stat;
}
printf("Scheduling Mode: FCFS.\n");
FCFS(task_FCFS, head, task_n);
printf("\n");
// creat copy
head.track = head_track;
head.seek_length = 0;
Task task_SSTF[task_n];
for(int i = 0; i < task_n; i++){
task_SSTF[i].track = task[i].track;
task_SSTF[i].stat = task[i].stat;
}
printf("Scheduling Mode: SSTF.\n");
SSTF(task_SSTF, head, task_n);
printf("\n");
// creat copy
head.track = head_track;
head.seek_length = 0;
Task task_SCAN[task_n];
for(int i = 0; i < task_n; i++){
task_SCAN[i].track = task[i].track;
task_SCAN[i].stat = task[i].stat;
}
printf("Scheduling Mode: SCAN.\n");
printf("Assume that the disk arm is moving toward 199.\n");
SCAN(task_SCAN, head, task_n);
printf("\n");
// creat copy
head.track = head_track;
head.seek_length = 0;
Task task_CSCAN[task_n];
for(int i = 0; i < task_n; i++){
task_CSCAN[i].track = task[i].track;
task_CSCAN[i].stat = task[i].stat;
}
printf("Scheduling Mode: CSCAN.\n");
CSCAN(task_CSCAN, head, task_n);
printf("\n");
// creat copy
head.track = head_track;
head.seek_length = 0;
Task task_LOOK[task_n];
for(int i = 0; i < task_n; i++){
task_LOOK[i].track = task[i].track;
task_LOOK[i].stat = task[i].stat;
}
printf("Scheduling Mode: LOOK.\n");
printf("Assume that the disk arm is moving toward 199.\n");
LOOK(task_LOOK, head, task_n);
printf("\n");
// creat copy
head.track = head_track;
head.seek_length = 0;
Task task_CLOOK[task_n];
for(int i = 0; i < task_n; i++){
task_CLOOK[i].track = task[i].track;
task_CLOOK[i].stat = task[i].stat;
}
printf("Scheduling Mode: CLOOK.\n");
CLOOK(task_CLOOK, head, task_n);
return 0;
}
void FCFS(Task task[], Head head, int task_n)
{
printf("track visited\tseek length\n");
for(int i = 0; i < task_n; i++){
task[i].stat = complete;
int temp = abs(task[i].track - head.track); // absolute value: distance between track and head
printf("%13d\t%11d\n", task[i].track, temp);
head.track = task[i].track;
head.seek_length += temp;
}
printf("Total seek length: %d.\n", head.seek_length);
printf("Average seek length: %.1f.\n", 1.0 * head.seek_length/task_n);
}
void SSTF(Task task[], Head head, int task_n)
{
printf("track visited\tseek length\n");
for(int i = 0; i < task_n; i++){
int min_dis = 200; // the least distance from the head
int min_task = 0; // the track with the least distance from the head
int temp = 0; // absolute value: distance between track and head
for(int j = 0; j < task_n; j++){ // find the task with the least distance from the head
if(task[j].stat == waiting){
temp = abs(task[j].track - head.track);
if(temp < min_dis){
min_dis = temp;
min_task = j;
}
}
}
printf("%13d\t%11d\n", task[min_task].track, min_dis);
head.track = task[min_task].track;
head.seek_length += min_dis;
task[min_task].stat = complete;
}
printf("Total seek length: %d.\n", head.seek_length);
printf("Average seek length: %.2f.\n", 1.0 * head.seek_length/task_n);
}
void SCAN(Task task[], Head head, int task_n)
{
printf("track visited\tseek length\n");
int temp_head = head.track;
while(temp_head <= MAX_track){ // head: from head track to max track
for(int i = 0; i < task_n; i++){
if(task[i].stat == waiting){
if(task[i].track == temp_head){
task[i].stat = complete;
int temp = abs(task[i].track - head.track);
printf("%13d\t%11d\n", task[i].track, temp);
head.track = task[i].track;
head.seek_length += temp;
break;
}
}
}
temp_head++;
}
while(temp_head >= 0){ // head: from max track to 0
for(int i = 0; i < task_n; i++){
if(task[i].stat == waiting){
if(task[i].track == temp_head){
task[i].stat = complete;
int temp = abs(task[i].track - head.track);
printf("%13d\t%11d\n", task[i].track, temp);
head.track = task[i].track;
head.seek_length += temp;
break;
}
}
}
temp_head--;
}
printf("Total seek length: %d.\n", head.seek_length);
printf("Average seek length: %.1f.\n", 1.0 * head.seek_length/task_n);
}
void CSCAN(Task task[], Head head, int task_n)
{
printf("track visited\tseek length\n");
int temp_head = head.track;
while(temp_head <= MAX_track){ // head: from head track to max track
for(int i = 0; i < task_n; i++){
if(task[i].stat == waiting){
if(task[i].track == temp_head){
task[i].stat = complete;
int temp = abs(task[i].track - head.track);
printf("%13d\t%11d\n", task[i].track, temp);
head.track = task[i].track;
head.seek_length += temp;
break;
}
}
}
temp_head++;
}
temp_head = 0; // head: back to the beginning
while(temp_head <= MAX_track){ // head: from beginning to max track
for(int i = 0; i < task_n; i++){
if(task[i].stat == waiting){
if(task[i].track == temp_head){
task[i].stat = complete;
int temp = abs(task[i].track - head.track);
printf("%13d\t%11d\n", task[i].track, temp);
head.track = task[i].track;
head.seek_length += temp;
break;
}
}
}
temp_head++;
}
printf("Total seek length: %d.\n", head.seek_length);
printf("Average seek length: %.1f.\n", 1.0 * head.seek_length/task_n);
}
void LOOK(Task task[], Head head, int task_n)
{
int min_track = 200;
int max_track = -1;
for(int i = 0; i < task_n; i++){ // find min task's track and max task's track
if(task[i].track < min_track){
min_track = task[i].track;
}
if(task[i].track > max_track){
max_track = task[i].track;
}
}
printf("track visited\tseek length\n");
int temp_head = head.track;
while(temp_head <= max_track){ // head: from head track to max task's track
for(int i = 0; i < task_n; i++){
if(task[i].stat == waiting){
if(task[i].track == temp_head){
task[i].stat = complete;
int temp = abs(task[i].track - head.track);
printf("%13d\t%11d\n", task[i].track, temp);
head.track = task[i].track;
head.seek_length += temp;
break;
}
}
}
temp_head++;
}
while(temp_head >= min_track){ // head: from max task's track to min task's track
for(int i = 0; i < task_n; i++){
if(task[i].stat == waiting){
if(task[i].track == temp_head){
task[i].stat = complete;
int temp = abs(task[i].track - head.track);
printf("%13d\t%11d\n", task[i].track, temp);
head.track = task[i].track;
head.seek_length += temp;
break;
}
}
}
temp_head--;
}
printf("Total seek length: %d.\n", head.seek_length);
printf("Average seek length: %.1f.\n", 1.0 * head.seek_length/task_n);
}
void CLOOK(Task task[], Head head, int task_n)
{
int min_track = 200;
int max_track = -1;
for(int i = 0; i < task_n; i++){ // find min task's track and max task's track
if(task[i].track < min_track){
min_track = task[i].track;
}
if(task[i].track > max_track){
max_track = task[i].track;
}
}
printf("track visited\tseek length\n");
int temp_head = head.track;
while(temp_head <= max_track){ // head: from head track to max task's track
for(int i = 0; i < task_n; i++){
if(task[i].stat == waiting){
if(task[i].track == temp_head){
task[i].stat = complete;
int temp = abs(task[i].track - head.track);
printf("%13d\t%11d\n", task[i].track, temp);
head.track = task[i].track;
head.seek_length += temp;
break;
}
}
}
temp_head++;
}
temp_head = min_track; // head: back to min task's track
while(temp_head <= max_track){ // head: from min task's track to max task's track
for(int i = 0; i < task_n; i++){
if(task[i].stat == waiting){
if(task[i].track == temp_head){
task[i].stat = complete;
int temp = abs(task[i].track - head.track);
printf("%13d\t%11d\n", task[i].track, temp);
head.track = task[i].track;
head.seek_length += temp;
break;
}
}
}
temp_head++;
}
printf("Total seek length: %d.\n", head.seek_length);
printf("Average seek length: %.1f.\n", 1.0 * head.seek_length/task_n);
}