操作系统实验一

操作系统实验一

进程调度算法

一、实验目的

1.理解操作系统进程管理中进行进程调度的过程和调度算法的思想原理;

创建进程控制块PCB,并合理组织就绪队列。

2.理解进程的状态及变化,动态显示每个进程的当前状态及进程的调度情况。

掌握几种调度算法。

  • 理解几种进程调度的方式

  • 用代码将几种进程调度的方式表现出来

二、实验原理

(1)先到先服务调度算法:按照进程提交给系统的先后次序来进行调度。

(2)短作业优先调度算法:按照进程所要求的运行时间来衡量。

(3)时间片轮转调度算法:根据先来先服务排序,以一个时间片为单位,依次执行不同的进程。

(4)优先权调度算法:按照进程的优先权来衡量。

三、实验要求

能够考虑社会、健康、安全、法律、文化及环境等因素的影响,针对先来先服务、短进程优先、时间片轮转、高相应比优先调度算法进行建模,设计实验方案,运用恰当的集成开发工具编程模拟实现上述算法,要求:

  1. 有录入界面,动态录入进程个数、时间片大小、创建进程控制块(PCB)通过录入界面录入进程标识符、进程到达时间、服务时间等信息;
  2. 有算法选择界面,能够根据需要选择不同调度算法;
  3. 有输出界面,能够输出不同调度算法下诸进程的进程标识符、到达时间、服务时间、开始时间、完成时间、周转时间、带权周转时间以及一批作业的平均周转时间、平均带权周转时间;
四、实现过程
  1. 定义一个静态内部类,代码初始化时优先加载,放入进程标识符、进入时间以及服务时间等
  2. 将进程放入到一个数组中
  3. 对于FCFS算法思想:因为是按照进入时间的前后作为进入内存的优先级,所以先按照进入时间从小到大排序,使用直接选择排序算法,将进程按照进入时间排成从小到大的队列,设置一个标志位,temover记录上次进程的结束时间,需要考虑:如果上一个结束的时间比这个进程进入时间大,则这个进程已经进入,需要等待到temover时间才能开始,直接使用temover作为这个进程的开始时间。
  4. 对于SJF算法思想:先按照进入时间从小到大排序,然后对进来的进程再次进行排序,这次排序需要按照服务时间进行排序。
  5. 对于高响应比优先级算法:首先要知道优先级的计算公式,然后还是先按照进入时间排序,再按照优先级排序
  6. 对于RR算法:照样是先按照进入时间进行排序,然后创建一个队列queue,将进程放入队列中。
五、实现截图

在这里插入图片描述

在这里插入图片描述

六、源代码

注解挺多,可以作为参考

package com.zkb;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class process {

    static class pro{
        public String name; //进程标识符
        public int insertTime;//进入时间
        public int serviceTime;//服务时间
        public int startTime;//开始时间
        public int overTime;//完成时间
        public int turnoverTime;//周转时间
        public double turnAroundTime;//带全周转时间
    }
    pro[] processes;
    public void init(){

        Scanner scanner = new Scanner(System.in);
        System.out.println("你要输入的进程数:");
        int amount = scanner.nextInt();
        processes = new pro[amount];
        for (int i=0;i<amount;i++){

            System.out.println("第"+(i+1)+"进程是:");
            System.out.println("请输入你的进程名");
            processes[i] = new pro();
            processes[i].name= scanner.next();
            System.out.println("你的进入时间是:");
            processes[i].insertTime = scanner.nextInt();
            System.out.println("你的估计运行时间是:");
            processes[i].serviceTime = scanner.nextInt();
        }
    }
    //先来先服务进程调度算法
    public void FCFS(){
        sort();
        int temover=0;//记住每次进程结束的时间,作为下次的开始时间
        for (int i = 0; i < processes.length; i++) {
            if (i==0){
                processes[i].startTime = processes[i].insertTime;
                processes[i].overTime = processes[i].startTime+processes[i].serviceTime;
                temover = processes[i].overTime;//记住结束的时间
            }else {//如果上一个结束的时间比这个进程进入时间大,则这个进程已经进入
                //需要等待到temover时间才能开始,直接使用temover作为这个进程的开始时间
                if (temover>=processes[i].insertTime){
                    processes[i].startTime=temover;
                    processes[i].overTime = processes[i].startTime+processes[i].serviceTime;
                    temover = processes[i].overTime;
                }else{
                    //否则这个进程还没有进入,需要等到这个进程的进入时间才能开始
                    processes[i].startTime = processes[i].insertTime;
                    processes[i].overTime = processes[i].startTime+processes[i].serviceTime;
                    temover = processes[i].overTime;//记住结束的时间
                }
            }
            computationTime();//计算周转时间和带全周转时间
        }
    }
    //短进程优先算法
    public void SJF(){
        sort();
        int temover= processes[0].insertTime;
        for (int i = 0; i < processes.length; i++) {
            int effect = effective(temover,i);//查看进来了几个进程
            sort1(i,effect);//对进来的进程进行排序
            if(temover >= processes[i].insertTime){
                processes[i].startTime=temover;
                processes[i].overTime = processes[i].startTime+processes[i].serviceTime;
                temover = processes[i].overTime;
            }else {
                //否则这个进程还没有进入,需要等到这个进程的进入时间才能开始
                processes[i].startTime = processes[i].insertTime;
                processes[i].overTime = processes[i].startTime+processes[i].serviceTime;
                temover = processes[i].overTime;//记住结束的时间
            }
        }
        computationTime();
    }

    //优先级调度算法
    public void priority(){
        sort();
        int temover= processes[0].insertTime;
        for (int i = 0; i < processes.length; i++) {
            int effect = effective(temover,i);//查看进来了几个进程
            sort2(i,effect,temover);//对进来的进程进行优先级排序
            if(temover >= processes[i].insertTime){
                processes[i].startTime=temover;
                processes[i].overTime = processes[i].startTime+processes[i].serviceTime;
                temover = processes[i].overTime;
            }else {
                //否则这个进程还没有进入,需要等到这个进程的进入时间才能开始
                processes[i].startTime = processes[i].insertTime;
                processes[i].overTime = processes[i].startTime+processes[i].serviceTime;
                temover = processes[i].overTime;//记住结束的时间
            }
        }
        computationTime();
    }
    //时间片调度算法
    public void RR(){
        sort();//首先按照进入的时间进行排个小序
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入你的时间片是多少:");
        int RR = scanner.nextInt();
        int temover = processes[0].insertTime;//记录上个进程结束时间
        Queue<Integer> queue = new LinkedList<>();//建一个队列去更新进来的进程,模拟进程调度
        int[] serviceTem = new int[processes.length];//存放所有的进程估计运行的时间的,开始全部置位0
        int i=1; //看队列进入了几个进程
        queue.offer(0);//排完序,肯定先执行第一个
        while (!queue.isEmpty()||i<processes.length){
            //RR的值重新赋予
            int cur=RR;
            //如果某一个当某一个进程执行完之后,但后面的进程还没有入队,就会有队列为空的表现.
            // 所以他就得再次执行陷入先服务,所以我们得给队列手动进入后面的进程.
            if (queue.isEmpty()){
                for (int tep = 0; tep < processes.length; tep++) {
                    if (serviceTem[tep]==0){
                        queue.offer(tep);
                        temover = processes[tep].insertTime;//更改下结束时间
                        i=i+1;
                        break;
                    }

                }
            }
            //出队列,进行执行
            int tem=queue.poll();
            if (serviceTem[tem]==0){//当数组里估计运行时间为0的话,那就是第一次初始化,可以进行赋初值
                processes[tem].startTime=temover;
            }
            while(cur!=0){//模拟实现时间片轮转,执行RR次,只等相等或者用完时间片
                if (serviceTem[tem]!=processes[tem].serviceTime){
                    ++serviceTem[tem];
                    temover++;
                }
                if (serviceTem[tem] == processes[tem].serviceTime){
                    processes[tem].overTime = temover;
                    break;
                }
                cur--;
            }
            //注意我这个进程进入顺序.
            //i记录进程个数,去遍历所有进程,看还有那个没进入,如果进程到了,就插入队列.
            if (i<processes.length){
                int j=i;
                for (; j < processes.length ;j++) {
                    if (processes[j].insertTime<=temover){
                        queue.offer(j);
                        i=i+1;
                    }
                }
            }
            //如果当前进程没有执行完,就再次进入队列
            if (serviceTem[tem] != processes[tem].serviceTime){
                queue.offer(tem);
            }
        }
        computationTime();
    }

    public void print(){
        System.out.println("| 作业 | 进入时间 | 估计运行时间 | 开始时间 | 结束时间 | 周转时间 | 带权周转时间 |");
        System.out.println("----------------------------------------------------------------------------------------------");
        for(int i = 0; i < processes.length; i++){
            System.out.print("|   " + processes[i].name + "  |");
            System.out.print("   " + processes[i].insertTime + "     |");
            System.out.print("      " + processes[i].serviceTime + "      |");
            System.out.print("     " + processes[i].startTime + "    |");
            System.out.print("    " + processes[i].overTime + "    |");
            System.out.print("    " + processes[i].turnoverTime + "     |");
            System.out.printf("%11.2f", processes[i].turnAroundTime);
            System.out.print("  |");
            System.out.println();

            //            System.out.printf("       " + processes[i].turnAroundTime + "    |");
        }
        double s=0,t=0,a=0,b=0;

        for(int i = 0; i < processes.length; i++) {

            s=s+processes[i].turnoverTime;
            a = a + processes[i].turnAroundTime;
        }
        t=s/processes.length;
        b=a/processes.length;
        System.out.println("平均周转时间:" +t);
        System.out.println("平均带权周转时间:"+b);
        System.out.println("----------------------------------------------------------------------------------------------");
    }
    public void menu() {
        System.out.println("欢迎来到进程调度");
        System.out.println("***********************");
        System.out.println("*****1.初始化**********");
        System.out.println("*****2.FCFS算法********");
        System.out.println("*****3.SJF算法*********");
        System.out.println("*****4.优先级算法******");
        System.out.println("*****5.RR算法**********");
        System.out.println("*****6.exit************");
        System.out.println("***********************");
    }
    public  void perform(){
        Scanner scanner = new Scanner(System.in);
        int choice = 0;
        while(true) {
            menu();
            System.out.println("请输入你的选择");
            choice = scanner.nextInt();
            if (choice == 1) {
                init();
            } else if (choice == 2) {
                System.out.println("FCFS算法结果:");
                FCFS();
            } else if (choice == 3) {
                System.out.println("SJF算法结果:");
                SJF();
            } else if (choice == 4){
                System.out.println("优先级算法结果:");
                priority();
            }
            else if(choice == 5){
                System.out.println("RR算法结果:");
                RR();
            }
            else if (choice == 6) {
                System.out.println("Good bye !!!");
                break;
            }
            else{
                System.out.println("你的输入有误,请重输");
                continue;
            }
            print();
        }
    }
    public static void main(String[] args) {
        process m1 = new process();
        m1.perform();
    }
    private void sort2(int start, int end, int temover) {//根据优先级排序
        for (int i = start; i < end ; i++) {
            for (int j = i+1; j < end ; j++) {
                int now = (temover-processes[i].insertTime+processes[i].serviceTime)/processes[i].serviceTime;
                int next = (temover-processes[j].insertTime+processes[j].serviceTime)/processes[j].serviceTime;
                if (next>now){
                    pro tem= processes[i];
                    processes[i] = processes[j];
                    processes[j] = tem;
                }
            }
        }
    }


    private void sort1(int start, int end) {//根据服务时间排序
        for (int i = start; i < end ; i++) {
            for (int j = i+1; j < end ; j++) {
                if (processes[i].serviceTime>processes[j].serviceTime){
                    pro tem= processes[i];
                    processes[i] = processes[j];
                    processes[j] = tem;
                }
            }
        }
    }


    private int effective(int temover, int start) {
        int end;//返回有效值的下标
        for(end = start;end<processes.length;end++){
            if (processes[end].insertTime>temover){
                break;
            }
        }
        return end;
    }


    private void computationTime() {

        for (int i = 0; i < processes.length; i++) {
            processes[i].turnoverTime=processes[i].overTime-processes[i].insertTime;
            processes[i].turnAroundTime = (double) processes[i].turnoverTime/processes[i].serviceTime;
        }
    }

    private void sort() {//根据进入时间直接选择排序
        for (int i = 0; i < processes.length; i++) {
            for (int j = i+1; j <processes.length ; j++) {
                if (processes[i].insertTime>=processes[j].insertTime){
                    pro tem= processes[i];
                    processes[i] = processes[j];
                    processes[j] = tem;
                }

            }
        }
    }
}
= 0; i < processes.length; i++) {
            for (int j = i+1; j <processes.length ; j++) {
                if (processes[i].insertTime>=processes[j].insertTime){
                    pro tem= processes[i];
                    processes[i] = processes[j];
                    processes[j] = tem;
                }

            }
        }
    }
}
专业方向:软件工程-软件工程(ID:07701) 修订人:金虎 ________________________________________ 《操作系统大作业》教学大纲 第一部分 课程目的与任务 一、课程基础: 在学这门课之前,学生必须预修过高级语言、数据结构、离散数学方面的基本知识,先修操作系统课程,延时完成操作系统大作业。 二、适应对象: 计算机科学与技术-计算机应用; 软件工程-软件工程; 电子信息科学类-电子信息科学与技术;管理类-信息管理专业 三、教学目的: 为配合《操作系统》课程的教学,通过模拟操作系统原理的实现,使学生能更深刻地领会操作系统工作原理和操作系统实现方法,并提高程序设计能力, 特开设此课程设计。 四、内容提要: 本课要求模拟采用多道程序设计方法的单用户操作系统,该操作系统包括进程管理、存储管理、设备管理和文件管理四部分。 第二部分 内容及基本要求 第1章、进程控制管理实现 ●基本要求:利用简单的结构和控制方法模拟进程结构、进程状态和进程控制。 ●参考学时:8学时 ●参考资料: 用PCB表示整个进程实体,利用随机数方法或键盘控制方法模拟进程执行中产生的事件。或者利用鼠标或者键盘中断的基于图形接口方式的进程控制管理。 1、 定义PCB(可以采用静态结构或动态结构):包括理论PCB中的基本内容,如内部ID、外部ID、进程状态、队列指针。由于无法实现真正的进程创建功能,在实验中只需建立PCB,用它代表完整的进程。 2、 定义进程状态转换方式:进程的状态转换是由进程内部操作或操作系统的控制引起,由于无法实现这些功能,学生可以采用随机数方法或键盘控制方法模拟,并实现对应的控制程序。随机方法指产生1-6的随机数,分别代表创建进程(c)、结束进程(e)、进程阻塞(b)、激活进程(w)、调度进程(p)、时间片到(t)等事件;键盘模拟方法指定义6种按键代表以上6种事件。 3、 根据四种事件处理就绪队列、阻塞队列和当前执行中的进程。 每次事件处理后应形象地显示出当前系统中的执行进程是哪一个,就绪队列和阻塞队列分别包含哪些进程。 第2章、请求分页式存储管理的地址转换过程实现: ●基本要求:实现分页式存储地址转换过程,在此基础上实现请求分页的地址转换。实现请求页式地址转换中出现的缺页现象时,用到的先进先出FIFO、最近最久未使用LRU、最佳OPT置换算法。 ●参考学时:8学时 ●参考资料: 利用键盘输入本模拟系统的物理块的大小,作业的页表中的块号;完成逻辑地址转换成相应的物理地址的过程。 1、建立一张位示图,用来模拟内存的分配情况,利用随机数产生一组0和1的数对应内存的使用情况。 2、输入块(页)的大小,通过模拟位示图为本作业分配内存空间建立相应的页表(长度不定); 3、录入逻辑地址转换成相应的物理地址 4、扩充页表,变成请求式的二维页表(增加存在位等)完成地址转换。 5、输入分配给本作业的块数,模拟作业执行的逻辑地址转换成页面调度次序; 6、分别采用OPT、FIFO、LRU置换算法,利用堆栈结构完成页面置换;记录被换出的页面和新换入的页面。 第3章、设备管理实现: ●基本要求:设备管理主要包括设备的添加和删除、设备的分配和回收、同时实现设备独立性。 ●参考学时:6学时 ●参考资料: 假定模拟系统中有键盘、鼠标、打印机和显示器四个设备,三个控制器和两个通道,采用安全分配方式。 1、设备管理子系统涉及到系统设备表(SDT)、通道控制表(CHCT)、控制器控制表(COCT)和设备控制表(DCT)来体现输入输出系统的四级结构和三级控制。我们模拟这样的数据结构来完成对外围设备的管理。 (1)添加设备:增加对应的设备控制表和系统设备表中的表项,如果需要新建对应的控制器控制表。 (2)删除设备:删除对应的设备控制表和系统设备表中的表项,如果需要删除对应的控制器控制表。 2、设备的分配和回收,进程申请设备的时候,建立起通路,即获成功;否则阻塞到通道、控制器或设备上面。进程回收设备的时候,把阻塞进程唤醒。 3、设备分配必须满足设备的独立性要求。为了实现设备独立性,要求在驱动程序之上设计一层设备无关软件,其主要功能可分为: (1)执行所有设备的公有操作,主要包括:(a)独占设备的分配与回收;(b)将逻辑设备名映射为物理设备(LUT),进一步可以找到相应物理设备的驱动程序。 (2)向用户层(或文件层)软件提供统一的接口。例如,对各种设备的读操作,在应用程序中都用read; 而对各种设备的写操作,则都使用write。 第4章、文件管理系统实现: ●基本要求:利用交互式命令实现树型目录结构和文件管理,同时利用位示图表示外存的分配情况,新建文件时分配必要的空间,模拟文件分配表记录文件在外存上的存储方式。 ●参考学时:8学时 ●参考资料: 在文件中保存目录内容,创建文件或子目录可以用命令行命令:MD、CD、RD、MK(创建文件)、DEL(删除文件)和DIR。目录项包括文件或目录名称、类型(文件、目录或空目录项)、创建日期以及下一个目录项指针、下一级目录项指针。 1、创建初始文件,建立根目录的“.”和“..”目录项。 2、显示命令提示符“$”。 3、输入命令后根据命令含义完成相应文件操作: MD:在目录文件中创建子目录,同时搜索当前目录最后一个目录项,并保存指针信息; CD:根据当前目录切换到指定目录; RD:搜索所要删除的目录是否为空目录,若是则删除; MK:在当前目录中创建文件名称;(申请空间利用位示图修改FAT) DEL:搜索所要删除的文件是否存在,若是则删除;(恢复位示图修改FAT) DIR:列出当前目录的所有目录项。 4、在创建文件的时候分配空闲的磁盘空间,采用显示链接的方式,利用文件分配表(FAT)记录文件在外存上的存储情况。 5、当删除文件时,回收外存上的空间,修改位示图和文件分配表。 第5章、进程调度算法的实现: ●基本要求:实现先来先服务FCFS、短作业优先SJF以及时间片轮转调度算法。 ●参考学时:6学时 ●参考资料: 根据创建进程的系统时钟,取相对时钟作为进程的到达时间,利用随机数产生每个进程的估计运行时间。利用模拟系统中提供的算法分别计算其相应的周转时间和带权周转时间。 1、利用绝对时间和相对时钟产生一组进程的到达时刻和运行时间。 2、实现FCFS算法:根据进程的到达时间的先后次序来完成对若干进程的调度。 3、实现SJF算法:根据当前时间已经到达进程的需要运行时间选取其中时间最小的进程最先运行。 4、实现时间片轮转算法:首先要求确定时间片的大小,依据进程的到达时间依次加入队列,每次分配一个时间片大小的时间,如果没有完成参与下一次的竞争,当最后需要一个小于等于时间片的时间时本进程完成,同时退出队列。 5、计算每种算法调度后,系统的平均周转时间和平均带权周转时间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值