操作系统之动态分区分配

简介

本程序利用java编程语言对其进行了实现。
源代码移步:http://download.csdn.net/download/chengshijian2015/10215534

原理

可变分区调度算法有:最先适应分配算法,最优适应分配算法,最坏适应算法。
用户提出内存空间的申请;系统根据申请者的要求,按照一定的分配策略分析内存空间的使用情况,找出能满足请求的空闲区,分给申请者;当程序执行完毕或主动归还内存资源时,系统要收回它所占用的内存空间或它归还的部分内存空间。
每当一个进程被创建时,内存分配程序首先要查找空闲内存分区表(链),从中寻找一个合适的空闲块进行划分,并修改空闲内存分区表(链)。当进程运行完毕释放内存时,系统根据回收区的首址,从空闲区表(链)中找到相应的插入点,此时出现如下四种情况:
1) 回收区与插入点的前一个空闲分区F1相邻接,此时可将回收区直接与F1合并,并修改F1的大小;
2) 回收区与插入点的后一个空闲分区F2相邻接,此时可将回收区直接与F2合并,并用回收区的首址最为新空闲区的首址,大小为二者之和;
3) 回收区同时与插入点的前、后两个空闲分区邻接,此时需将三者合并;
4) 回收区不与任何一个空闲区邻接,此时应建一新的表项。
源代码:
DynamicPartAllocate.java:

package com.csi.operatesystem;

import java.util.Scanner;

/**
 * Created by ChengShiJian on 2017/11/08.
 * 
 */

public class DynamicPartAllocate {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println("软件1503  程世健 1511030304");
        final Scanner scanner = new Scanner(System.in);
        new DynamicPartAllocatePresenter().setOnExcuteLisenter(new OnExcuteLisenter() {
            @Override
            public Job getJob() {
                // TODO Auto-generated method stub
                while (true) {
                    System.out.print("请输入作业(作业号   所用空间大小)>");
                    Job job = new Job();
                    int id = scanner.nextInt();
                    if (id < 1) {
                        System.out.println("作业号必须大于0!");
                        continue;
                    }
                    int length = scanner.nextInt();
                    job.setJobId(id);
                    job.setLength(length);
                    return job;
                }
            }

            @Override
            public void onOutOfMemory() {
                // TODO Auto-generated method stub
                System.out.println("磁盘空间不足!");
            }

            @Override
            public void onAllocateSuccess(Partition partition) {
                // TODO Auto-generated method stub
                System.out.println("----------------------------当前内存情况------------------------------");
                System.out.println(
                        "起始地址                       终点地址                               内存大小                                  状态                        作业号");

                for (PartBlock block : partition.getBlocks()) {
                    System.out.printf("%-15d%-15d%-15d%-30s%-15s\n", block.getStartAddress(), block.getEndAddress(),
                            block.getLength(), block.getState(), block.getJobId()==0?"":String.valueOf(block.getJobId()));
                }
                System.out.println("------------------------------------------------------------------");
            }

            @Override
            public int getJobId() {
                // TODO Auto-generated method stub
                System.out.print("请输入作业id>");
                return scanner.nextInt();
            }

            @Override
            public void onSearchError(int id) {
                // TODO Auto-generated method stub
                System.out.println("作业" + id + "不存在!回收内存失败!");
            }

            @Override
            public void onRetrieveSuccess(Partition partition) {
                // TODO Auto-generated method stub
                System.out.println("----------------------------当前内存情况------------------------------");
                System.out.println(
                        "起始地址                       终点地址                               内存大小                                  状态                        作业号");

                for (PartBlock block : partition.getBlocks()) {
                    System.out.printf("%-15d%-15d%-15d%-30s%-15s\n", block.getStartAddress(), block.getEndAddress(),
                            block.getLength(), block.getState(), block.getJobId()==0?"":String.valueOf(block.getJobId()));
                }
                System.out.println("------------------------------------------------------------------");
            }

            @Override
            public int onGetMethod() {
                // TODO Auto-generated method stub
                System.out.println("0.最先适应分配算法         1.最优适应分配算法        2.最坏适应分配算法");
                System.out.print("请选择分配算法>");
                switch (scanner.nextInt()) {
                case 0:
                    return DynamicPartAllocatePresenter.FIRST_FIT;
                case 1:
                    return DynamicPartAllocatePresenter.BEST_FIT;
                case 2:
                    return DynamicPartAllocatePresenter.BAD_FIT;

                default:
                    return -1;
                }
            }

            @Override
            public int onGetOperate() {
                // TODO Auto-generated method stub

                System.out.println("0.分配         1.回收         2.退出");
                System.out.print("请选择>");
                switch (scanner.nextInt()) {
                case 0:
                    return DynamicPartAllocatePresenter.ALLOCATE;
                case 1:
                    return DynamicPartAllocatePresenter.RETRIVE;
                case 2:
                    System.exit(0);
                    break;
                }
                return -1;

            }
        }).excute();
    }
}

DynamicPartAllocatePresenter.java:

package com.chengshijian.operatesystem;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * Created by ChengShiJian on 2017/11/08.
 * 
 * 任命者类,动态内存分配的全部逻辑操作全部在这个类中
 */
public class DynamicPartAllocatePresenter {

    public static final int FIRST_FIT = 0;//最先适应算法
    public static final int BEST_FIT = 1;//最优适应算法
    public static final int BAD_FIT = 2;//最坏适应算法
    public static final int ALLOCATE = 3;//分配
    public static final int RETRIVE = 4;//回收

    private Partition partition = new Partition();//内存
    private int method;//算法
    private int operate;//操作,指分配还是回收
    private boolean isAllocateSuccess = false;//是否分配成功
    private boolean isSearchSuccess = false;//是否查找成功

    private OnExecuteLisenter lisenter;//执行事件监听器

    // 一.实验目的
    // 用高级语言编写和调试一个内存分配模拟程序,以加深对动态分区的概念及内存分配原理的理解。
    // 二.实验原理
    // 可变分区调度算法有:最先适应分配算法,最优适应分配算法,最坏适应算法。
    // 用户提出内存空间的申请;系统根据申请者的要求,按照一定的分配策略分析内存空间的使用情况,
    // 找出能满足请求的空闲区,分给申请者;当程序执行完毕或主动归还内存资源时,系统要收回它所占用的内存空间或它归还的部分内存空间。
    // 每当一个进程被创建时,内存分配程序首先要查找空闲内存分区表(链),从中寻找一个合适的空闲块进行划分,
    // 并修改空闲内存分区表(链)。当进程运行完毕释放内存时,系统根据回收区的首址,从空闲区表(链)中找到相应的插入点,此时出现如下四种情况:
    // 1) 回收区与插入点的前一个空闲分区F1相邻接,此时可将回收区直接与F1合并,并修改F1的大小;
    // 2) 回收区与插入点的后一个空闲分区F2相邻接,此时可将回收区直接与F2合并,并用回收区的首址最为新空闲区的首址,大小为二者之和;
    // 3) 回收区同时与插入点的前、后两个空闲分区邻接,此时需将三者合并;
    // 4) 回收区不与任何一个空闲区邻接,此时应建一新的表项。
    // 三.实验内容
    // 编写并调试一个模拟的内存分配程序。具体做法为:使用一个循环,根据提示,由用户选择随时创建一个新的进程,并为其分配存储空间,
    // 也随时可以撤销一个进程,可以根据需要随时打印空闲分区表(链)以及打印系统中内存使用情况。

    public DynamicPartAllocatePresenter setOnExcuteLisenter(OnExecuteLisenter lisenter) {
        this.lisenter = lisenter;
        return this;
    }

    public DynamicPartAllocatePresenter setOperate(int operate) {
        this.operate = operate;
        return this;
    }

    public int getMethod() {
        return method;
    }

    public void setMethod(int method) {
        this.method = method;
    }

    //回收
    private void retrieve() {
        int id = lisenter.getJobId();//获取作业号
        int index = 0;//先将目的查找Block 置为0
        for (int i = 0; i < partition.getBlocks().size(); i++) {
            PartBlock block = partition.getBlocks().get(i);
            if (block.getJobId() == id) {
                index = i;
                isSearchSuccess = true;
                break;
            }
        }
        if (isSearchSuccess) {//如果查找成功
            List blocks = partition.getBlocks();
            sortByAddress(blocks);//将内存中的内存块按起始地址由小到大排序
            PartBlock block = partition.getBlocks().get(index);
            block.setState(Partition.NOT_ALLOCATE);
            block.setJobId(0);
            PartBlock afterBlock = null;
            PartBlock beforeBlock = null;
            int originalBlockSize=blocks.size()-1;//先记录未合并之前内存中内存块的数量

            if (index != 0) {
                beforeBlock = blocks.get(index - 1);//得到前一个块
            }
            if (index != blocks.size() - 1) {
                afterBlock = partition.getBlocks().get(index + 1);//得到后一个块
            }
            //向前合并
            if (index != 0) {
                sortByAddress(partition.getBlocks());
                if (beforeBlock.getState().equals(Partition.NOT_ALLOCATE)) {
                    block.setStartAddress(beforeBlock.getStartAddress());
                    block.setLength(beforeBlock.getLength() + block.getLength());
                    block.setEndAddress(block.getStartAddress() + block.getLength());
                    blocks.remove(beforeBlock);
                }
            }
            //向后合并
            if (index != originalBlockSize) {
                if (afterBlock.getState().equals(Partition.NOT_ALLOCATE)) {
                    block.setLength(afterBlock.getLength() + block.getLength());
                    block.setEndAddress(block.getStartAddress() + block.getLength());
                    blocks.remove(afterBlock);
                }
            }
            lisenter.onAllocateSuccess(partition);//作事件监听
            isSearchSuccess=false;
        } else {
            lisenter.onSearchError(id);//作事件监听
        }
    }

    //分配
    private void allocate() {
        Job job = lisenter.getJob();//得到作业对象
        for (PartBlock block : partition.getBlocks()) {
            if (block.getLength() >= job.getLength() && block.getState().equals(Partition.NOT_ALLOCATE)) {//如果存在未分配并且比作业申请的内存大小大的内存块
                PartBlock newBlock = new PartBlock();
                newBlock.setJobId(job.getJobId());
                newBlock.setLength(job.getLength());
                newBlock.setStartAddress(block.getStartAddress());
                newBlock.setState(Partition.HAVE_ALLOCATE);
                newBlock.setEndAddress(newBlock.getStartAddress() + newBlock.getLength());
                block.setStartAddress(block.getStartAddress() + job.getLength());
                block.setLength(block.getLength() - job.getLength());
                partition.getBlocks().add(newBlock);
                isAllocateSuccess = true;
                break;
            }
        }

        if (!isAllocateSuccess) {
            lisenter.onOutOfMemory();//作事件监听
        } else {
            sortByAddress(partition.getBlocks());//按起始地址牌下序
            lisenter.onAllocateSuccess(partition);//作事件监听
            isAllocateSuccess = false;
        }
    }

    //最先适应算法
    public void allocteByFirstFit() {
        while (true) {
            operate = lisenter.onGetOperate();
            switch (operate) {
            case ALLOCATE:
                sortByAddress(partition.getBlocks());
                allocate();
                break;
            case RETRIVE:
                retrieve();
                break;
            default:
                break;
            }
        }

    }

    //最优适应算法
    public void allocteByBestFit() {
        while (true) {
            operate = lisenter.onGetOperate();
            switch (operate) {
            case ALLOCATE:
                sortByLengthDown(partition.getBlocks());
                allocate();
                break;
            case RETRIVE:
                retrieve();
                break;
            default:
                break;
            }
        }
    }

    //最坏适应算法
    public void allocteByBadestFit() {
        while (true) {
            operate = lisenter.onGetOperate();
            switch (operate) {
            case ALLOCATE:
                sortByLengthUp(partition.getBlocks());
                allocate();
                break;
            case RETRIVE:
                retrieve();
                break;
            default:
                break;
            }
        }
    }

    //按地址由小到大排序
    private void sortByAddress(List blocks) {
        Collections.sort(partition.getBlocks(), new Comparator() {
            @Override
            public int compare(PartBlock o1, PartBlock o2) {
                // TODO Auto-generated method stub
                if (o1.getStartAddress() > o2.getStartAddress()) {
                    return 1;
                } else if (o1.getStartAddress() < o2.getStartAddress()) {
                    return -1;
                }
                return 0;
            }
        });
    }

    //按内存大小由小到大排序
    private void sortByLengthDown(List blocks) {
        Collections.sort(partition.getBlocks(), new Comparator() {
            @Override
            public int compare(PartBlock o1, PartBlock o2) {
                // TODO Auto-generated method stub
                if (o1.getLength() > o2.getLength()) {
                    return 1;
                } else if (o1.getLength() < o2.getLength()) {
                    return -1;
                }
                return 0;
            }
        });
    }

    //按内存大小由大到小排序
    private void sortByLengthUp(List blocks) {
        Collections.sort(partition.getBlocks(), new Comparator() {
            @Override
            public int compare(PartBlock o1, PartBlock o2) {
                // TODO Auto-generated method stub
                if (o1.getLength() < o2.getLength()) {
                    return 1;
                } else if (o1.getLength() > o2.getLength()) {
                    return -1;
                }
                return 0;
            }
        });
    }

    //执行,也是起点
    public void excute() {
        method=lisenter.onGetMethod();
        switch (method) {
        case FIRST_FIT:
            allocteByFirstFit();
            break;
        case BEST_FIT:
            allocteByBestFit();
            break;
        case BAD_FIT:
            allocteByBadestFit();
            break;
        default:
            break;
        }
    }
}

Job.java:

package com.chengshijian.operatesystem;

/**
 * Created by ChengShiJian on 2017/11/08.
 * 
 * 作业类,对作业的一个封装
 */
public class Job {
    private int jobId;//作业id
    private int length;//作业长度
    public int getJobId() {
        return jobId;
    }
    public void setJobId(int jobId) {
        this.jobId = jobId;
    }
    public int getLength() {
        return length;
    }
    public void setLength(int length) {
        this.length = length;
    }
}

OnExcuteLisenter.java:

package com.chengshijian.operatesystem;

/**
 * Created by ChengShiJian on 2017/11/08.
 * 
 * 执行事件监听器接口
 * 
 */
public interface OnExecuteLisenter {
    Job getJob();//获取作业
    int getJobId();//获取作业id
    int onGetMethod();//获取算法
    int onGetOperate();//获取操作,指分配还是回收
    void onSearchError(int id);//当查找失败时,指在回收内存没有找到指定id的内存块时
    void onOutOfMemory();//当内存不足,指作业请求的内存大小太大,剩余内存不足以分配时
    void onAllocateSuccess(Partition partition);//当分配内存成功时
    void onRetrieveSuccess(Partition partition);//当回收内存成功时
}

PartBlock.java:

package com.chengshijian.operatesystem;

/**
 * Created by ChengShiJian on 2017/11/08.
 * 
 * 内存块类
 */
public class PartBlock {
    private int startAddress;//起始地址
    private int endAddress;//终点地址
    private int length;//内存块大小
    private String state;//内存块状态,已分配还是未分配
    private int jobId;//作业id

    public int getEndAddress() {
        return this.endAddress;
    }

    public void setEndAddress(int endAddress) {
        this.endAddress = endAddress;
    }

    public PartBlock() {
        super();
        // TODO Auto-generated constructor stub
    }

    public PartBlock(int startAddress, int length, String state) {
        super();
        this.startAddress = startAddress;
        this.length = length;
        this.state = state;
        this.endAddress=this.startAddress+this.length;
    }

    public int getStartAddress() {
        return startAddress;
    }

    public void setStartAddress(int startAddress) {
        this.startAddress = startAddress;
    }

    public int getLength() {
        return length;
    }

    public void setLength(int length) {
        this.length = length;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public int getJobId() {
        return jobId;
    }

    public void setJobId(int jobId) {
        this.jobId = jobId;
    }

    @Override
    public String toString() {
        return "PartBlock [startAddress=" + startAddress + ", endAddress=" + endAddress + ", length=" + length
                + ", state=" + state + ", jobId=" + jobId + "]";
    }
}

Partition.java:

package com.chengshijian.operatesystem;

/**
 * Created by ChengShiJian on 2017/11/08.
 * 
 * 内存类,核心实质上用来存内存块
 */
import java.util.ArrayList;
import java.util.List;

public class Partition {
    public static final String HAVE_ALLOCATE="已分配";
    public static final String NOT_ALLOCATE="未分配";

    private List blocks=new ArrayList<>();
    public int length=1000;

    public List getBlocks() {
        return blocks;
    }

    public void setBlocks(List blocks) {
        this.blocks = blocks;
    }

    public int getLength() {
        return length;
    }

    public void setLength(int length) {
        this.length = length;
    }

    public Partition() {
        super();
        // TODO Auto-generated constructor stub
        blocks.add(new PartBlock(0,length,NOT_ALLOCATE));
    }

    public Partition(int length) {
        super();
        blocks.add(new PartBlock(0,length,NOT_ALLOCATE));
    }
}

你可能感兴趣的:(大三上(操作系统))