你的位置:首页 > Java教程

[Java教程]使用动态分区分配方式的模拟


1实验目的

(1)了解动态分区分配方式中使用的数据结构和分配算法

(2)加深对动态分区存储管理方式及其实现过程的理解。

2实验内容

(1)分别实现采用首次适应算法和最佳适应算法的动态分区分配过程alloc()和回收过程free()。其中,空闲分区通过空闲分区链来管理:在进行内存分配时,系统优先使用空闲区低端的空间。

(2)假设初始状态下,可用的内存空间为640KB,并有下列的请求序列:

•作业1申请130KB。

•作业2申请60KB。

•作业3申请100KB。

•作业2释放60KB。

•作业4申请200KB。

•作业3释放100KB。

•作业1释放130KB。

•作业5申请140KB。

•作业6申请60KB。

•作业7申请50KB。

•作业6释放60KB。

分别采用首次适应算法和最佳适应算法,对内存块进行分配和回收,要求每次分配和回收后显示出空闲分区链的情况。

3实验结果(给出编写的程序源代码和运行结果的截图)

 这是操作系统实验老师出的一个题目,要求模拟动态分区的内存分配,上面是题目的要求。对于这道题,我自己并没有独立实现,在网上找了源码,终于弄懂了,然后自己写了最佳适应算法,这里我就说一下怎么来解这道题

1.首先,需要声明占用内存的进程的各个属性。你需要name来表示该进程的名字、startAddress表示进程所占内存的起始地址、length表示进程所占大小、flag表示用于标记该内存是否释放。

2.然后需要分配算法和回收的算法。对于分配,因为存储的方式是链式存储的,对于一个将要分配进来的进程,系统会将第一个适合该进程的内存分出足够的大小分配给该进程,这就是首次适应算法。而我写的最佳适应算法的思路是这样的:每次分配前,就对内存中的所有片空间进行排序,这样每次分配进来的内存都会是最适合的内存空间。

3.有分配就会有回收,回收分为几种情况,需要注意的就是在回收过程中,当相邻的有空闲分区时,需要进行合并

下面是源代码:

进程类Date.class

package memory;public class Date {  String name;    //进程名称  int startAddress;  //起始地址  int length;      //占用大小长度  int flag;      //是否已使用  public Date(String name, int startAddress, int length, int flag) {    super();    this.name = name;    this.startAddress = startAddress;    this.length = length;    this.flag = flag;  }  public Date() {    super();  }  @Override  public String toString() {    return "Date [name=" + name + ", startAddress=" + startAddress        + ", length=" + length + ", flag=" + flag + "]";  }}

 

Main.class

package memory;import java.util.ArrayList;import java.util.Collection;import java.util.Scanner;public class Main {  static ArrayList list = new ArrayList();  //建立一个链表,来表示内存的使用情况  static Scanner sc = new Scanner(System.in);    //首次适应算法  static void fenPei(){    Date date = new Date();    System.out.println("输入请求分配进程的名称:");    date.name = sc.next();    System.out.println("输入分配的内存大小:");    date.length = sc.nextInt();    int i;    for ( i = 0; i < list.size(); i++) {      if (date.length <= ((Date)list.get(i)).length && ((Date)list.get(i)).flag == 0) {        //当有适合的内存,且未被使用        break;      }    }    if (i == list.size()) {      System.out.println("没有足够的内存进行分配");    }    if (((Date)list.get(i)).length - date.length <= 4 && i != list.size() - 1 ) {//当内存比进程所占的内存在4kB以内的话,就不进行分片      ((Date)list.get(i)).name = date.name;      ((Date)list.get(i)).flag = 1;    }else {      //分片分配内存      date.flag = 1;      ((Date)list.get(i)).length -= date.length;      date.startAddress = ((Date)list.get(i)).startAddress;      ((Date)list.get(i)).startAddress += date.length;      list.add(i, date);    }  }  //最佳适应算法  static void fenPei1(){    Date date = new Date();    System.out.println("输入请求分配进程的名称:");    date.name = sc.next();    System.out.println("输入分配的内存大小:");    date.length = sc.nextInt();    int m, j;    Date target = new Date();      for (m = 1; m < list.size()-1; m++){        j = m;        target.name = ((Date)list.get(m)).name;        target.flag = ((Date)list.get(m)).flag;        target.length = ((Date)list.get(m)).length;        target.startAddress = ((Date)list.get(m)).startAddress;        while(j>0 && ((Date)list.get(j-1)).length>target.length){                    ((Date)list.get(j)).name = ((Date)list.get(j-1)).name;          ((Date)list.get(j)).flag = ((Date)list.get(j-1)).flag;          ((Date)list.get(j)).length = ((Date)list.get(j-1)).length;          ((Date)list.get(j)).startAddress = ((Date)list.get(j-1)).startAddress + ((Date)list.get(j)).length;          j--;        }        ((Date)list.get(j)).name = target.name;        ((Date)list.get(j)).length = target.length;        ((Date)list.get(j)).flag = target.flag;        ((Date)list.get(j)).startAddress = target.startAddress-((Date)list.get(j+1)).length;              }      int i;      for ( i = 0; i < list.size(); i++) {        if (date.length <= ((Date)list.get(i)).length && ((Date)list.get(i)).flag == 0) {          //当有适合的内存,且未被使用          break;        }      }      if (i == list.size()) {        System.out.println("没有足够的内存进行分配");      }      if (((Date)list.get(i)).length - date.length <= 4 && i != list.size() - 1 ) {        ((Date)list.get(i)).name = date.name;        ((Date)list.get(i)).flag = 1;      }else {        //分片分配内存        date.flag = 1;        ((Date)list.get(i)).length -= date.length;        date.startAddress = ((Date)list.get(i)).startAddress;        ((Date)list.get(i)).startAddress += date.length;        list.add(i, date);      }  }  //回收部分  static void huiShou(){    System.out.println("请输入要回收的进程:");    String name = sc.next();    int i;    for ( i = 0; i < list.size(); i++) {      if (name.equals(((Date)list.get(i)).name)) {        break;      }    }    if (i == list.size()) {      System.out.println("没有找到该进程。");      return;    }    System.out.println("找到的是====>"+ i);    int hui = ((Date)list.get(i)).length;    if (i == 0 && ((Date)list.get(i+1)).flag == 0) {    //回收第一个进程,且第二个内存位置空闲,合并这两者      ((Date)list.get(i)).flag = 0;      ((Date)list.get(i)).length += ((Date)list.get(i+1)).length;      ((Date)list.get(i)).name = "";      list.remove(1);    }else if (i == 0 && ((Date)list.get(i+1)).flag == 1) {  //回收第一个进程,但第二个内存位置被占用      ((Date)list.get(i)).name = "";      ((Date)list.get(i)).flag = 0;    }else if (((Date)list.get(i-1)).flag == 0 && ((Date)list.get(i+1)).flag == 0) {//回收位置的进程左右两边的内存空间都空闲      ((Date)list.get(i)).name = "";      ((Date)list.get(i)).flag = 0;      ((Date)list.get(i-1)).length += ((Date)list.get(i)).length + ((Date)list.get(i+1)).length;       list.remove(i);      list.remove(i+1);    }else if (((Date)list.get(i-1)).flag == 0 && ((Date)list.get(i+1)).flag == 1) {//回收位置左边的内存空闲,而右边的内存被占用      ((Date)list.get(i)).name = "";      ((Date)list.get(i)).flag = 0;      ((Date)list.get(i-1)).length += ((Date)list.get(i)).length;      list.remove(i);    }else if (((Date)list.get(i-1)).flag == 1 && ((Date)list.get(i+1)).flag == 0) {//回收位置右边的内存空闲,而左边的内存被占用      ((Date)list.get(i)).name = "";      ((Date)list.get(i)).flag = 0;      ((Date)list.get(i)).length += ((Date)list.get(i+1)).length;      list.remove(i+1);    }else {//左右两边的内存都被占用      ((Date)list.get(i)).name = "";      ((Date)list.get(i)).flag = 0;    }    System.out.println("成功回收进程"+i+"的"+hui+"kb的空间");  }    static void disPlay(){    System.out.println("=============================================");    for (int i = 0; i < list.size(); i++) {      System.out.println(list.get(i));    }    System.out.println("=============================================");  }    public static void main(String[] args){    Date date = new Date("", 0, 640, 0);    list.add(date);    int choice0;    int choice1;    while(true){      System.out.println("请选择:内存分配方式");      System.out.println("1.首次适应算法");      System.out.println("2.最佳适应算法");      System.out.println("3.退出");      choice0 = sc.nextInt();      switch (choice0) {      case 1:        while(true){        System.out.println("请选择:");        System.out.println("1.分配内存");        System.out.println("2.回收内存");        System.out.println("3.查看内存");        System.out.println("4.退出");        choice1 = sc.nextInt();        switch (choice1) {        case 1:          fenPei();          break;        case 2:          huiShou();          break;        case 3:          disPlay();          break;        case 4:          System.exit(0);          break;        default:          System.out.println("请正确输入");          break;        }        }      case 2:        while(true){          System.out.println("请选择:");          System.out.println("1.分配内存");          System.out.println("2.回收内存");          System.out.println("3.查看内存");          System.out.println("4.退出");          choice1 = sc.nextInt();          switch (choice1) {          case 1:            fenPei1();            break;          case 2:            huiShou();            break;          case 3:            disPlay();            break;          case 4:            System.exit(0);            break;          default:            System.out.println("请正确输入");            break;          }          }      case 3:          System.exit(0);        break;      default:        System.out.println("请正确输入:");      }    }      }}