精华内容
下载资源
问答
  • 磁盘调度算法实验报告
    2021-05-25 00:37:32

    操作系统磁盘调度算法实验报告课案

    《操作系统原理》

    课 程 设 计 报 告 书

    题 目:磁盘调度 专 业:网络工程 学 号: 学生姓名: 指导教师: 完成日期:

    目录 TOC \o "1-3" \h \z \u HYPERLINK \l "_Toc436561075" 第一章 课程设计目的 PAGEREF _Toc436561075 \h 1 HYPERLINK \l "_Toc436561076" 1.1编写目的 PAGEREF _Toc436561076 \h 1 HYPERLINK \l "_Toc436561077" 第二章 课程设计内容 PAGEREF _Toc436561077 \h 2 HYPERLINK \l "_Toc436561078" 2.1设计内容 PAGEREF _Toc436561078 \h 2 HYPERLINK \l "_Toc436561079" 2.1.1、先来先服务算法(FCFS) PAGEREF _Toc436561079 \h 2 HYPERLINK \l "_Toc436561080" 2.1.2、最短寻道时间优先算法(SSTF) PAGEREF _Toc436561080 \h 2 HYPERLINK \l "_Toc436561081" 2.1.3、扫描算法(SCAN) PAGEREF _Toc436561081 \h 3 HYPERLINK \l "_Toc436561082" 2.1.4、循环扫描算法(CSCAN) PAGEREF _Toc436561082 \h 3 HYPERLINK \l "_Toc436561083" 第三章 系统概要设计 PAGEREF _Toc436561083 \h 4 HYPERLINK \l "_Toc436561084" 3.1模块调度关系图 PAGEREF _Toc436561084 \h 4 HYPERLINK \l "_Toc436561085" 3.2模块程序流程图 PAGEREF _Toc436561085 \h 4 HYPERLINK \l "_Toc436561086" 3.2.1 FCFS算法 PAGEREF _Toc436561086 \h 5 HYPERLINK \l "_Toc436561087" 3.2.2 SSTF算法 PAGEREF _Toc436561087 \h 6 HYPERLINK \l "_Toc436561088" 3.2.3 SCAN算法 PAGEREF _Toc436561088 \h 7 HYPERLINK \l "_Toc436561089" 3.2.4 CSCAN算法 PAGEREF _Toc436561089 \h 8 HYPERLINK \l "_Toc436561090" 第四章 程序实现 PAGEREF _Toc436561090 \h 9 HYPERLINK \l "_Toc436561091" 4.1 主函数的代码实现 PAGEREF _Toc436561091 \h 9 HYPERLINK \l "_Toc436561092" 4.2.FCFS算法的代码实现 PAGEREF _Toc436561092 \h 11 HYPERLINK \l "_Toc436561093" 4.3 SSTF算法的代码实现 PAGEREF _Toc436561093 \h 13 HYPERLINK \l "_Toc436561094" 4.4 SCAN算法的代码实现 PAGEREF _Toc436561094 \h 15 HYPERLINK \l "_Toc436561095" 4.5 CSCAN算法的代码实现 PAGEREF _Toc436561095 \h 17 HYPERLINK \l "_Toc436561096" 第五章 测试数据和结果 PAGEREF _Toc436561096 \h 20 HYPERLINK \l "_Toc436561097" 第六章 总结 PAGEREF _Toc

    更多相关内容
  • 操作系统磁盘调度算法实验报告
  • 磁盘调度算法 学生姓名: 学生学号: 专业班级: 指导老师 2013 年6月20日 1实验目的 通过这次实验加深对磁盘调度算法的理解进一步掌握先来先 服务 FCFS最短寻道时间优先 SSTFSCAN和循环 SCAN算法的实现 方法 2问题描述...
  • 磁盘调度算法实验报告(20210919121020).pdf
  • 操作系统实验八 磁盘调度算法实验报告
  • 复习模拟实现一种磁盘调度算法(FCFS、SSTF、Scan、CScan、2-step Scan任选一),进一步加深对磁盘调度效率的理解。本实验模拟实现了电梯扫描算法
  • 实用标准文案 目录 目录 1 1 课程设计目的 1 1.1 编写目的 1 2 课程设计内容 1 2.1 设计...1.1 编写目的 本课程设计的目的是通过磁盘调度算法设计一个磁盘调度模拟系统 从而使磁盘调度算法更加形象化容易使人理解使磁
  • 假设有 n 个磁道号所组成 的磁道访问序列,给定开始磁道号 m 和磁头移动的方向,正向 或者反向,分别利用不同的磁盘调度算法访问磁道序列,给出 每一次访问的磁头移动距离,计算每种算法的平均寻道长度
  • 磁盘调度算法实验报告.doc
  • 操作系统磁盘调度算法实验报告及代码.docx
  • 磁盘调度算法实验报告.pdf
  • 操作系统实验报告 磁盘调度 先进先出算法 lru算法 操作系统实验报告 磁盘调度 先进先出算法 lru算法操作系统实验报告 磁盘调度 先进先出算法 lru算法
  • 操作系统磁盘调度算法实验报告及代码参考.pdf
  • 操作系统实验六 磁盘调度算法(内含源代码和详细实验报告),详细介绍:http://blog.csdn.net/xunciy/article/details/79239096
  • 操作系统实验报告 操作系统实验报告 实验六 磁盘调度算法 班级 学号 姓名 需求分析 1实验目的 通过这次实验加深对磁盘调度算法的理解进一步掌握先来先服务FCFS最短寻道时间优先SSTFSCAN和循环SCAN算法的实现方法 2...
  • 磁盘调度管理实验

    2017-12-30 19:43:47
    (1)理解磁盘调度相关理论 (2)掌握多种磁盘调度算法 (3)彻底掌握SCAN磁盘调度算法 (4)观察不同算法的调度情况并比较异同点
  • 实验报告为课程实验报告,内容齐全,详细介绍了操作系统中作业调度算法
  • 操作系统实验报告三份,基于天津理工大学,实验1:处理机调度.;实验2:存储器的分配与回收;磁盘调度算法的实现
  • 操作系统实验八:磁盘移臂调度算法实验报告。实验目标:加深对于操作系统设备管理技术的了解,体验磁盘移臂调度算法的重要性;掌握几种重要的磁盘移臂调度算法,练习模拟算法的编程技巧,锻炼研究分析试验数据的能力...
  • 实验(四)磁盘调度算法模拟

    千次阅读 2021-12-06 13:10:21
    磁盘调度算法模拟)一、实验名称二、实验目的三、实验内容和要求四、实验设计1、程序流程图:2、实验环境:jdk1.83、代码与注释五、实验步骤及实验结果1、实验内容2、实验结果六、实验中出现的问题及解决方法问题1:...

    一、实验名称

    实验(四)磁盘调度算法模拟

    二、实验目的

    掌握磁盘调度的策略及原理,理解和掌握磁盘调度算法——先来先服务算法(FCFS)、最短寻道时间优先算法(SSTF)、电梯扫描算法(SCAN),比较各算法相关特性。

    三、实验内容和要求

    (1)模拟先来先服务法(FCFS),最短寻道时间优先法(SSTF),电梯扫描算法(SCAN)三种磁盘调度算法;
    (2)输入两组请求访问磁道序列,分别输出每种调度算法的磁头移动轨迹和移动的总磁道数。

    四、实验设计

    1、程序流程图:

    在这里插入图片描述

    2、实验环境:jdk1.8

    3、代码与注释

    package com.symc.dsaa.os.test4;
    
    import java.util.Scanner;
    
    /**
     * @Author: 凤文  沈阳医学院2019级医学信息工程 0213
     * @CreateTime: 2021/12/05 17:28
     * @Description: 磁盘调度算法实验
     */
    public class Test {
        public static void main(String[] args) {
            int[] tracks = getRandomArr();
            System.out.println("随机生成了10个磁道号(0-200)");
            for (int track : tracks) {
                System.out.print(track + "\t");
            }
            System.out.println();
            Scanner sc = new Scanner(System.in);
            System.out.println("请设置一个起始的磁道号(0-200):");
            int startTrack;
            while (true) {
                startTrack = sc.nextInt();
                if (startTrack < 0 || startTrack > 200) {
                    System.out.println("您输入的磁道号越界,请重新设置(0-200):");
                    continue;
                }
                break;
            }
            do {
                printMenu();
            } while (choose(sc, tracks, startTrack));
    
        }
    
        public static void printMenu() {
            System.out.println("##########################");
            System.out.println("请选择您想用的算法:");
            System.out.println("1.先来先服务");
            System.out.println("2.最短寻道时间优先");
            System.out.println("3.扫描算法");
            System.out.println("0.退出本次实验");
            System.out.println("##########################");
    
        }
    
        /**
         * 随机生成一个0-200的序列来代替磁道号
         * 用随机的目的是方便快速测试
         * @return
         */
        public static int[] getRandomArr() {
            int[] arr = new int[10];
            for (int i = 0; i < arr.length; i++) {
                arr[i] = (int) (Math.random() * 200);
            }
            return arr;
        }
    
        public static boolean choose(Scanner sc, int[] tracks, int startTrack) {
            int option = sc.nextInt();
            switch (option) {
                case 0:
                    return false;
                case 1:
                    printFCFS(tracks, startTrack);
                    break;
                case 2:
                    printSSTF(tracks, startTrack);
                    break;
                case 3:
                    printSCAN(tracks, startTrack, 1);
                    break;
                default:
                    System.out.println("输入错误!请重新输入!");
                    choose(sc, tracks, startTrack);
                    break;
            }
            return true;
        }
    
        public static void printFCFS(int[] tracks, int startTrack) {
            int[] sequence = DiskScheduling.FCFS(tracks);
            int[] move = DiskScheduling.move(sequence, startTrack);
            print(sequence, move, startTrack);
        }
    
        public static void printSSTF(int[] tracks, int startTrack) {
            int[] sequence = DiskScheduling.SSTF(tracks, startTrack);
            int[] move = DiskScheduling.move(sequence, startTrack);
            print(sequence, move, startTrack);
        }
    
        public static void printSCAN(int[] tracks, int startTrack, int direction) {
            int[] sequence = DiskScheduling.SSTF(tracks, startTrack);
            int[] move = DiskScheduling.move(sequence, startTrack);
            if (direction > 0) {
                System.out.println("向磁道号增加方向访问");
                print(sequence, move, direction);
            } else {
                System.out.println("向磁道号减少方向访问");
            }
        }
    
        public static void print(int[] sequence, int[] move, int startTrack) {
            System.out.println("从" + startTrack + "号磁道开始");
            System.out.println("被访问的下一个磁道号\t移动距离(磁道数)");
            int averMove = 0;
            for (int i = 0; i < sequence.length; i++) {
                System.out.println(sequence[i] + "\t\t\t\t\t" + move[i]);
                averMove += move[i];
            }
            System.out.println("平均寻道长度:" + (double) averMove / sequence.length);
        }
    }
    
    package com.symc.dsaa.os.test4;
    
    import java.util.Arrays;
    import java.util.Stack;
    
    /**
     * @Author: 凤文  沈阳医学院2019级医学信息工程 0213
     * @CreateTime: 2021/12/05 17:28
     * @Description:
     */
    public class DiskScheduling {
    
        /**
         * 先来先服务
         * @param tracks 传入一组乱序的磁盘轨道序列
         * @return 返回一组FCFS的磁头移动轨迹的序列
         */
        public static int[] FCFS(int[] tracks) {
            int len = tracks.length;
            int[] sequence = new int[len];
            for (int i = 0; i < len; i++) {
                sequence[i] = tracks[i];
            }
            return sequence;
        }
    
        /**
         * 最短寻道时间优先
         * @param tracks 传入一组乱序的磁盘轨道序列
         * @param startTrack 需要知道磁头的起始位置
         * @return 返回一组SSTF的磁头移动轨迹的序列
         */
        public static int[] SSTF(int[] tracks, int startTrack) {
            Stack<Integer> stack1 = new Stack<Integer>();
            Stack<Integer> stack2 = new Stack<Integer>();
            Stack<Integer> stack2Temp = new Stack<Integer>();
            Arrays.stream(tracks).sorted().forEach((track) -> {
                if (track <= startTrack) {
                    stack1.push(track);
                } else if (track > startTrack) {
                    stack2Temp.push(track);
                }
            });
            while (!stack2Temp.isEmpty()) {
                stack2.push(stack2Temp.pop());
            }
            int head = startTrack;
            int[] sequence = new int[tracks.length];
            for (int i = 0; i < sequence.length; i++) {
                if (stack1.isEmpty()) {
                    head = stack2.pop();
                    sequence[i] = head;
                    continue;
                }
                if (stack2.isEmpty()) {
                    head = stack1.pop();
                    sequence[i] = head;
                    continue;
                }
    
                if (stack2.peek() - head < head - stack1.peek()) {
                    head = stack2.pop();
                    sequence[i] = head;
                } else {
                    head = stack1.pop();
                    sequence[i] = head;
                }
            }
            return sequence;
        }
    
        /**
         * 电梯扫描
         * @param tracks 传入一组乱序的磁盘轨道序列
         * @param startTrack 需要知道磁头的起始位置
         * @param direction 扫描算法还需要知道磁头起始的移动方向
         * @return 返回一组SCAN的磁头移动轨迹的序列
         */
        public static int[] SCAN(int[] tracks, int startTrack, int direction) {
            int len = tracks.length;
            int[] sequence = new int[len];
            for (int i = 0; i < len; i++) {
                sequence[i] = tracks[i];
            }
            Arrays.sort(sequence);
            int num =
                    (int) Arrays.stream(sequence).filter(track -> track < startTrack).count();
            int[] reSequence = new int[num];
            for (int i = 0; i < sequence.length; i++) {
                if (sequence[i]<startTrack){
                    reSequence[i]=sequence[i];
                }else {
                    sequence[i-num]=sequence[i];
                }
            }
            for (int i = num-1; i >= 0; i--) {
                sequence[len-i-1] = reSequence[i];
            }
    
            return sequence;
        }
    
    /**
     * 移动序列确定好之后,移动距离的算法都一致,都使用move即可
     * @param sequence
     * @param startTrack
     * @return 返回一个存放移动距离的数组
     */
        public static int[] move(int[] sequence, int startTrack) {
            int len = sequence.length;
            int[] trackValues = new int[len];
            int trackNum;
            for (int i = 0; i < len; i++) {
                if (i == 0) {
                    trackNum = startTrack - sequence[i];
                } else {
                    trackNum = sequence[i] - sequence[i - 1];
                }
                trackValues[i] = trackNum > 0 ? trackNum : -trackNum;
            }
            return trackValues;
        }
    }
    

    五、实验步骤及实验结果

    1、实验内容

    在这里插入图片描述

    2、实验结果

    选择先来先服务结果如下:

    在这里插入图片描述

    最短寻道时间优先:
    在这里插入图片描述
    扫描算法:
    在这里插入图片描述
    结束本次实验:
    在这里插入图片描述
    为了避免偶然性,我们可以进行多次实验,每次运行后都将这个序列按照这三种算法测试。

    六、实验中出现的问题及解决方法

    问题1:SSTF算法的实现

    这个算法需要我们比较当前磁头的位置与哪个序列最近,在实现的时候,无论是使用数组还是ArrayList,发现它实现思路特别麻烦。于是,我想了新的思路,使用双栈。首先,肯定要把磁道序列先排序,就按从小到大升序,然后把比磁头位置大的磁道号全放到一个栈,栈内顺序就是大的放最下面,比磁头位置小的磁道号全放到另一个栈,栈内顺序就是小的放最下面,假如有一个排序好的序列:5,10,12,17,20,40,60,磁头位置在15,结构如图:

    我们只需要比较磁头与两个栈顶的磁道哪个差值最小,那这个栈顶就是下一个访问的磁道,比如这里,12跟15相差3,17跟15相差2,那下一个序列就是17。同时要注意这个栈顶17要取出,然后磁头位置由15变成了17,下一轮继续这么比较。代码实现如下:

    public static int[] SSTF(int[] tracks, int startTrack) {

    Stack<Integer> stack1 = new Stack<Integer>();
    
    Stack<Integer> stack2 = new Stack<Integer>();
    
    Stack<Integer> stack2Temp = new Stack<Integer>();
    
    Arrays.stream(tracks).sorted().forEach((track) -> { //我这里使用了stream去排序
    
        if (track <= startTrack) { //排好序后放到对应的栈内
            stack1.push(track);
        } else if (track > startTrack) {
            stack2Temp.push(track);
        }
    });
    
    while (!stack2Temp.isEmpty()) { 
        stack2.push(stack2Temp.pop());
    }
    
    int head = startTrack;
    int[] sequence = new int[tracks.length];
    for (int i = 0; i < sequence.length; i++) {
        if (stack1.isEmpty()) {//当比较前,如果发现有一个栈是空的,那就不用比较了
            head = stack2.pop();//说明只能访问另一个栈,磁头也要指向对应的位置
            sequence[i] = head;
            continue;
        }
        
        if (stack2.isEmpty()) {
            head = stack1.pop();
            sequence[i] = head;
            continue;
        }
    
        if (stack2.peek() - head < head - stack1.peek()) { //比较出下一个访问的磁道
            head = stack2.pop();
            sequence[i] = head;
        } else {
            head = stack1.pop();
            sequence[i] = head;
        }
    }
    return sequence;
    

    }

    七、结论

    FIFS:其平均寻道时间较大,故只适合请求磁盘I/O进程数目较少的场合
    SSTF:保证每次的寻道时间最短,但不能保证平均寻道时间最短
    可防止低优先级进程出现饥饿现象

    展开全文
  • 操作系统实验——磁盘调度算法

    千次阅读 2021-11-09 22:05:23
    掌握几种基本的磁盘调度算法。 先来先服务法 最短寻道时间优先法 电梯法 二、实验内容和要求 采用模拟先来先服务法(First-Come, First-Served,FCFS),最短寻道时间优先法(Shortest Seek Time


    前言

    提示:本次实验在Linux(Ubuntu)中运行,程序中读取的文件需放在与c文件同一个文件夹中,或者自行在代码中修改路径。

    一、实验目的

    掌握几种基本的磁盘调度算法。

    1. 先来先服务法
    2. 最短寻道时间优先法
    3. 电梯法

    二、实验内容和要求

    1. 采用模拟先来先服务法(First-Come, First-Served,FCFS),最短寻道时间优先法(Shortest Seek Time First, SSTF),电梯法三种磁盘调度算法,对一组请求访问磁道序列输出为每种调度算法的磁头移动轨迹和移动的总磁道数。
    2. 请求访问磁道序列的数据放在文件里,数据间以空格间隔。

    三、实验程序

    c语言代码如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <malloc.h>
    #include <math.h>
    
    typedef int bool;
    #define true 1
    #define false 0
    
    int curTrack;    //当前磁道号
    int trackNum;    //待调度磁道的数量
    int *track;      //磁道号序列
    
    //快速排序
    int position(int *a, int low, int high) {
        int key = a[low];
        while(low < high) {
            while(low < high && a[high] >= key) high--;
            a[low] = a[high];
            while(low < high && a[low] <= key) low++;
            a[high] = a[low];
        }
        a[low] = key;
        return low;
    }
    void quickSort(int *a, int low, int high) {
        if(low < high) {
            int pos = position(a, low, high);
            quickSort(a, low, pos - 1);
            quickSort(a, pos + 1, high);
        }
    }
    
    //二分查找(只能查找有序序列)
    int binaryFind(int *a, int flag, int target) {
        int left = 0;
        int right = flag - 1;
        while(left <= right) {
            int middle = (right + left) / 2;
            if(a[middle] < target) {
                left = middle + 1;
            } else if(a[middle] > target) {
                right = middle - 1;
            } else {
                return middle;
            }
        }
        return -1;  //查找失败
    }
    
    
    void init(FILE *fp) {
    	rewind(fp);		//fp回到开始位置
        //printf("请输入当前磁道号:");
        fscanf(fp, "%d", &curTrack);
        //printf("请输入待调度磁道的数量:");
        fscanf(fp, "%d", &trackNum);
        //printf("请输入磁道号序列:");
        track = (int*)malloc(trackNum  * sizeof(int));
        for(int i = 0; i < trackNum; i++) {
            fscanf(fp, "%d", &track[i]);
        }
    }
    
    //判断数字是几位数,使得打印的轨迹好看
    int digits(int num) {
        int result = 1;
        while(num / 10) {
            result++;
            num = num / 10;
        }
        return result;
    }
    
    //打印磁头移动轨迹
    void showTrack(int j, int cur, int *sortTrack) {
        for(int i = 0; i < digits(sortTrack[0]); i++) {
            printf(" ");
        }
        if(j < cur) {
            for(int i = 0; i < j; i++) {
                printf("    ");
                for(int k = 0; k < digits(sortTrack[i]); k++) {
                    printf(" ");
                }
            }
            printf("\b<");
            for(int i = j; i < cur; i++) {
                printf("----");
                for(int k = 0; k < digits(sortTrack[i]); k++) {
                    printf("-");
                }
            }
        }else {
            for(int i = 0; i < cur; i++) {
                printf("    ");
                for(int k = 0; k < digits(sortTrack[i]); k++) {
                    printf(" ");
                }
            }
            printf("\b");
            for(int i = cur; i < j; i++) {
                printf("----");
                for(int k = 0; k < digits(sortTrack[i]); k++) {
                    printf("-");
                }
            }
            printf("\b>");
        }printf("\n");
    }
    
    
    //先来先服务算法(FCFS)
    void FCFS() {
        printf("先来先服务算法(FCFS)\n");
        //对磁盘序列track进行排序
        int *sortTrack = (int*)malloc((trackNum + 1) * sizeof(int));
        for(int i = 0; i < trackNum; i++) {
            sortTrack[i] = track[i];
        }
        sortTrack[trackNum] = curTrack;
        quickSort(sortTrack, 0, trackNum);
        int curIndex = binaryFind(sortTrack, trackNum + 1, curTrack);
        printf("  磁盘序列:   丨");
        for(int i = 0; i < trackNum + 1; i++) {
            if(i == curIndex)
                printf("\033[1;32m%d    ", sortTrack[i]);    //给当前磁盘号的输出添加眼颜色
                //printf("%d    ", sortTrack[i]);
            else
                printf("\033[0m%d    ", sortTrack[i]);
            	//printf("%d    ", sortTrack[i]);
        }
        printf("\n");
        printf("磁头移动轨迹: 丨");
        int temp = 0;
        int cur = curIndex;
        while(temp < trackNum) {
            if(temp != 0) {
                printf("              丨");
            }
            int j = binaryFind(sortTrack, trackNum + 1, track[temp]);
            showTrack(j, cur, sortTrack);
            cur = j;
            temp++;
        }
        printf("\n");
        int sum = 0;        //记录磁盘移动的磁道数
        double average = 0;    //平均寻找长度
        printf("依次访问的磁盘序列为:");
        for(int i = 0; i < trackNum; i++) {
            printf("%d  ", track[i]);
            sum += abs(curTrack - track[i]);
            curTrack = track[i];
        }printf("\n");
        printf("磁头移动的总磁道数为:%d\n", sum);
        average = (double)sum / trackNum;
        printf("平均寻找长度为:%f\n", average);
        free(sortTrack);
    }
    
    //在当前磁道的左右两个方向中寻找距离最近的磁道,返回对应下标
    int nearFind(int **markTrack, int curIndex) {
        //拷贝一份markTrack
        int **markTrack2 = (int**)malloc(2 * sizeof(int*));
        for(int i = 0; i < 2; i++) {
            markTrack2[i] = (int*)malloc((trackNum + 1) * sizeof(int));
        }
        for(int i = 0; i <= trackNum; i++) {
            markTrack2[0][i] = markTrack[0][i];
            markTrack2[1][i] = markTrack[1][i];
        }
        int leftIndex = -1;
        int rightIndex = trackNum + 1;
        int left = 0;   //在左边找第一个没访问过的磁道的距离
        int right = 0;  //在右边找第一个没访问过的磁道的距离
        for(int i = curIndex - 1; i >= 0; i--) {
            left += markTrack2[0][curIndex] - markTrack2[0][i];
            if(markTrack2[1][i] == 0) {
                leftIndex = i;
                markTrack2[1][i] = 1;    //修改访问位
                break;
            }
        }
        for(int i = curIndex + 1; i <= trackNum; i++) {
            right += markTrack2[0][i] - markTrack2[0][curIndex];
            if(markTrack2[1][i] == 0) {
                rightIndex = i;
                markTrack2[1][i] = 1;
                break;
            }
        }
        //printf("leftIndex = %d, rightIndex = %d\n", leftIndex, rightIndex);
        if(rightIndex == trackNum + 1) {
            markTrack[1][leftIndex] = 1;
            return leftIndex;
        }
        else if(leftIndex == -1) {
            markTrack[1][rightIndex] = 1;
            return rightIndex;
        }
        else {
            if(left <= right) {
                markTrack[1][leftIndex] = 1;
                return leftIndex;
            }else {
                markTrack[1][rightIndex] = 1;
                return rightIndex;
            }
        }
        free(markTrack2);
    }
    
    //最短寻道时间优先法(SSTF)
    void SSTF() {
        printf("最短寻道时间优先法(SSTF)\n");
        int sum = 0;        //记录磁盘移动的磁道数
        double average = 0;    //平均寻找长度
        int *temp = (int*)malloc(trackNum * sizeof(int));
        track[trackNum] = curTrack;
        quickSort(track, 0, trackNum);  //对磁盘track序列排序
        //建立二维数组,大小为 2 * trackNum,第一行元素存放排序后的sortTrack,第二行设置标记位,访问过的置为1,未访问过的置为0
        int **markTrack = (int**)malloc(2 * sizeof(int*));
        for(int i = 0; i < 2; i++) {
            markTrack[i] = (int*)malloc((trackNum + 1) * sizeof(int));
        }
        for(int i = 0; i <= trackNum; i++) {
            markTrack[0][i] = track[i];
            markTrack[1][i] = 0;
        }
        int curIndex = binaryFind(track, trackNum + 1, curTrack);
        markTrack[1][curIndex] = 1; //当前磁盘号被访问过
        printf("  磁盘序列:   丨");
        for(int i = 0; i < trackNum + 1; i++) {
            if(i == curIndex)
                printf("\033[1;32m%d    ", track[i]);    //给当前磁盘号的输出添加眼颜色
                //printf("%d    ", track[i]);
            else
                printf("\033[0m%d    ", track[i]);
            	//printf("%d    ", track[i]);
        }
        printf("\n");
        printf("磁头移动轨迹: 丨");
        int cur = curIndex;
        for(int i = 0; i < trackNum; i++) {
            if(i != 0) {
                printf("              丨");
            }
            int j = nearFind(markTrack, cur);
            showTrack(j, cur, track);
            sum += abs(track[j] - track[cur]);
            cur = j;
            temp[i] = track[cur];
        }
        printf("依次访问的磁盘序列为:");
        for(int i = 0; i < trackNum; i++) {
            printf("%d  ", temp[i]);
        }printf("\n");
        printf("磁头移动的总磁道数为:%d\n", sum);
        average = (double)sum / trackNum;
        printf("平均寻找长度为:%f\n", average);
        free(temp);
        free(markTrack);
    }
    
    
    //电梯算法(LOOK)
    void LOOK() {
        printf("电梯算法(LOOK)\n");
        int sum = 0;        //记录磁盘移动的磁道数
        double average = 0;    //平均寻找长度
        track[trackNum] = curTrack;
        quickSort(track, 0, trackNum);  //对磁盘track序列排序
        //若此时磁头正在往磁道号增大的方向移动
        printf(" === ①  若初始时磁头正在往磁道号增大的方向移动\n");
        int curIndex = binaryFind(track, trackNum + 1, curTrack);
        int cur = curIndex;
        printf("  磁盘序列:   丨");
        for(int i = 0; i < trackNum + 1; i++) {
            if(i == curIndex)
                printf("\033[1;32m%d    ", track[i]);    //给当前磁盘号的输出添加眼颜色
                //printf("%d    ", track[i]);
            else
                printf("\033[0m%d    ", track[i]);
    	        //printf("%d    ", track[i]);
        }
        printf("\n");
        printf("磁头移动轨迹: 丨");
        for(int i = curIndex + 1; i <= trackNum; i++) {
            if(i != curIndex + 1)
                printf("              丨");
            showTrack(i, cur, track);
            sum += abs(track[i] - track[cur]);
            cur = i;
        }
        for(int i = curIndex - 1; i >= 0; i--) {
            printf("              丨");
            showTrack(i, cur, track);
            sum += abs(track[i] - track[cur]);
            cur = i;
        }
        printf("依次访问的磁盘序列为:");
        for(int i = curIndex + 1; i <= trackNum; i++) {
            printf("%d  ", track[i]);
        }
        for(int i = curIndex - 1; i >= 0; i--) {
            printf("%d  ", track[i]);
        }
        printf("\n磁头移动的总磁道数为:%d\n", sum);
        average = (double)sum / trackNum;
        printf("平均寻找长度为:%f\n", average);
        printf("\n\n");
    
        //若此时磁头正在往磁道号减小的方向移动
        printf(" === ②  若初始时磁头正在往磁道号减小的方向移动\n");
        sum = 0;
        average = 0.0;
        curIndex = binaryFind(track, trackNum + 1, curTrack);
        cur = curIndex;
        printf("  磁盘序列:   丨");
        for(int i = 0; i < trackNum + 1; i++) {
            if(i == curIndex)
                printf("\033[1;32m%d    ", track[i]);    //给当前磁盘号的输出添加眼颜色
                //printf("%d    ", track[i]);
            else
                printf("\033[0m%d    ", track[i]);
            	//printf("%d    ", track[i]);
        }
        printf("\n");
        printf("磁头移动轨迹: 丨");
        for(int i = curIndex - 1; i >= 0; i--) {
            if(i != curIndex - 1)
            printf("              丨");
            showTrack(i, cur, track);
            sum += abs(track[i] - track[cur]);
            cur = i;
        }
        for(int i = curIndex + 1; i <= trackNum; i++) {
            printf("              丨");
            showTrack(i, cur, track);
            sum += abs(track[i] - track[cur]);
            cur = i;
        }
        printf("依次访问的磁盘序列为:");
        for(int i = curIndex - 1; i >= 0; i--) {
            printf("%d  ", track[i]);
        }
        for(int i = curIndex + 1; i <= trackNum; i++) {
            printf("%d  ", track[i]);
        }
        printf("\n磁头移动的总磁道数为:%d\n", sum);
        average = (double)sum / trackNum;
        printf("平均寻找长度为:%f\n", average);
    }
    
    
    int main(int argc, char* argv[])
    {
    	FILE *fp = fopen(argv[1], "r");
    	if(fp == NULL) {
    		printf("读取文件失败!\n");
    		return 0;
    	}
    	
        init(fp); //初始化
    	printf("当前磁道号(curTrack):%d\n", curTrack);
    	printf("要访问的磁盘个数(trackNum):%d\n", trackNum);
    	printf("磁道号序列(track):{ ");
    	for(int i = 0; i < trackNum; i++) {
    		printf("%d ", track[i]);
    	}printf("}\n\n");
    
        FCFS();
        printf("\n\n");
    
        init(fp); //初始化
        SSTF();
        printf("\n\n");
    
        init(fp); //初始化
        LOOK();
    
        free(track);
    	fclose(fp);
        return 0;
    }
    
    

    ``

    四、运行结果

    运行结果截图

    提示:此文件需与源文件放同一文件夹
    在这里插入图片描述
    带颜色的磁盘序列号表示初始磁道号
    在这里插入图片描述
    在这里插入图片描述

    五、思考和分析

    程序实现(思路):

    本次实验对磁盘号序列进行排序时我用了快排,查找指定序列的下标采用了折半查找。
    执行三个算法之前分别先进行初始化操作。

    1)先来先服务算法(FCFS)
    轨迹的打印:先将磁盘序列数组track拷贝一份到新建的数组sortTrack中,将初始磁盘号放入其中,然后对sortTrack进行排序,找到初始磁道号在排序后track中的下标curIndex,然后依次访问track中的元素,找到他们在sortTrack中的下标,用cur记录当前磁头所在磁盘号的下标,根据这两个下标绘制出相应的轨迹,然后更新cur,重复执行,将所有轨迹绘制完毕。
    因为先来的磁盘先访问,因此磁头依次访问的磁盘序列就是一开始的磁盘序列数组中的元素。
    其余计算:用sum记录磁头移动的磁道数,遍历一遍track数组,将当前磁盘号与访问的磁盘号距离之差的绝对值加到sum中,然后更新当前磁盘号,遍历完后sum的值就是磁头移动的总磁道数,磁头平均查找长度average = sum / 磁道数量。

    2)最短寻道时间优先法(SSTF)
    轨迹的打印:直接将初始磁盘号curTrack放入磁盘序列数组track中并排序,找到初始磁道号在排序后track中的下标curIndex,然后建立一个带标记的磁道序列二维数组markTrack,第一行元素存放排序后的sortTrack,第二行设置标记位,访问过的置为1,未访问过的置为0,然后在当前磁道的左右两个方向中寻找距离最近的磁道,得到其下标,用cur记录当前磁头所在磁盘号的下标,根据这两个下标绘制出相应的轨迹,然后更新cur,重复执行,将所有轨迹绘制完毕。
    建立一个临时数组temp,存放磁头依次访问的磁道号,在打印轨迹的时候将对应的磁道号插入到该数组中,最后打印这个数组的元素,就是磁头依次访问的磁道号。
    其余计算:用sum记录磁头移动的磁道数,在打印轨迹的时候将移动的距离加到sum中,最终sum值就是磁头移动的总磁道数,磁头平均查找长度average = sum / 磁道数量。

    3)电梯算法(LOOK)
    因为初始状态磁头可能正在向磁道号增大的方向移动,也有可能正在向磁道号减小的方向移动,我将两种情况都做了相应的处理,这里的思路以向磁道号增大的方向移动为例。
    轨迹的打印:将初始磁盘号curTrack放入磁盘序列数组track中并排序,找到初始磁道号在排序后track中的下标curIndex,用cur记录curIndex,然后从curIndex + 1开始遍历,根据当前遍历到的下标和cur下标绘制出相应的轨迹,更新cur为遍历到的下标,遍历完后,向磁道号增大方向的轨迹打印完毕,然后再从curIndex – 1开始从后往前遍历,根据当前遍历到的下标和cur下标绘制出相应的轨迹,更新cur为遍历到的下标,遍历完后,向磁道号减小方向的轨迹也打印完毕,即所有轨迹绘制完毕。
    从curIndex + 1遍历到最后,在从curIndex – 1遍历到最前,遍历的磁道号就是磁头依次访问的磁道号。
    若初始时以磁道号减小的方向移动,就反过来,先从curIndex – 1遍历到最前,再从curIndex + 1遍历到最后即可。
    其余计算:用sum记录磁头移动的磁道数,在打印轨迹的时候将移动的距离加到sum中,最终sum值就是磁头移动的总磁道数,磁头平均查找长度average = sum / 磁道数量。

    分析几种算法:

    1)先来先服务算法(FCFS):
    优点:公平;如果请求访问的磁道比较集中的话,算法性能还算过的去
    缺点:如果有大量进程竞争使用磁盘,请求访问的磁道很分散,则FCFS在性能上很差,寻道时间长。

    2)最短寻道时间优先法(SSTF):
    优点:性能较好,平均寻道时间短
    缺点:可能产生“饥饿”现象,在附录给的测试文件中,假设在处理18号磁道的访问请求时又来了一个38号磁道的访问请求,处理38号磁道的访问请求时又来了一个18号磁道的访问请求。如果有源源不断的18号、38号磁道的访问请求到来的话,150、160、184号磁道的访问请求就永远得不到满足,从而产生“饥饿”现象。

    3)电梯算法(LOOK):
    LOOK算法可以说是扫描算法(SCAN)的优化版,扫描算法中,只有磁头到达最边上的磁道时才能改变磁头移动方向,在测试例子中,184号磁道后还存在一些磁道,只是我们不需要访问,若使用扫描算法,磁头还需要访问这些额外的磁道,事实上处理了184号磁道的访问请求之后就不需要再往右移动磁头了,而LOOK算法就是为了解决这个问题,如果在移动方向上已经没有别的请求了,就可以立即改变磁头移动的方向。
    优点:性能较好,平均寻道时间较短,不会产生饥饿现象。
    缺点:对于各个位置磁道的响应频率不平均(如:假设此时磁头正在往右移动,且刚处理过90号磁道,那么下次处理90号磁道的请求就需要等磁头移动很长一段距离;而响应了184号磁道的请求之后,很快又可以再次响应184号磁道的请求了)。

    建立以下的测试文件:
    //disk_data
    100
    9
    55 58 39 18 90 160 150 38 184

    测试文件的第一行代表当前磁道号;
    第二行代表待调度磁道的数量;
    第三行是磁道号序列。
    测试命令:./Experiment5 ./disk_data,即可利用命令行将disk_data作为参数调用。

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,453
精华内容 1,381
关键字:

磁盘调度算法实验报告