小组实现伙伴堆,我个人实现了内存的分配和释放部分
代码如下:
//Buddy类,伙伴堆算法类
package buddy;
import javax.swing.JOptionPane;
public class Buddy {
Order [] orders;
int frameAmount;//总页框数
int storage;//内存物理空间大小
int frameSize;//每一个页框的大小
RandomNumFactory rnf;
Buddy(int storage,int frameSize){
orders = new Order[10];
for(int i = 0; i < 10; i++) {
orders[i] = new Order(i);
}
this.storage = storage;
this.frameSize = frameSize;
frameAmount = this.storage*1024/this.frameSize;
rnf = new RandomNumFactory();
initialize();
}
/**
* 用于为指定的页框数(num)分配内存。分配成功返回true,分配失败返回false。
* 该方法本身不分配内存,而是遍历orders内的对象,并选择合适的Order对象调用其方法allocate()。
* 根据order对象allocate()的返回时进行判断,分配成功则判断返回的Block对象是否应进行拆分
* 拆分方法Buddy类中实现,直至大小适合,拆分过程中注意对orders中Order的freelist和bitmap做相应的改动
*
* @param num 指定的页框数
* @return 分配结果,成功返回true,不成功返回false
*/
boolean allocate(int num) {
boolean flag=false;
if(num>512) {
JOptionPane.showMessageDialog(null, "所要申请的页框数多于一个块所容纳的最大页框数", "错误",JOptionPane.WARNING_MESSAGE);
}else {
int index=(int) Math.ceil(Math.log(num)/Math.log(2));//获得这个所需页框数对应的order数组的索引
while(orders[index].freeList.isNull()&&index<=9) {
index+=1;
}
Block block=orders[index].allocate(num);// index=9
if(block!=null) {//block不为空,查找到相应的块
flag=true;
int number=(int) Math.ceil(Math.log(num)/Math.log(2));//要求7个页框,结果number为3
while(block.getBlockSize()!=Math.pow(2, number)) {
Block b1=new Block(block.getBlockStart()+(int)Math.pow(2, index-1), (int)Math.pow(2, index-1));//从取出的块中分出一个块,这个块在取出的块的“右侧”
Block b2=new Block(block.getBlockStart(), (int)Math.pow(2, index-1));//从取出的块中分出一个块,这个块在取出的块的“左侧”
orders[index-1].freeList.addBlock(b2);//index=9 第8个块组
orders[index-1].bitMap.exlusiveOR(b1.getBlockStart()>>(index));//index=9 第8个块组的map操作
block=b1;
index--;//index=8
}
orders[index].usingFrames.add(block);
JOptionPane.showMessageDialog(null, "大小为"+String.valueOf(Math.log((int)block.getBlockSize())/Math.log(2))+"起始地址为"+String.valueOf(block.getBlockStart()), "错误",JOptionPane.WARNING_MESSAGE);
}else {//block为空,没有查到块
flag=false;
}
}
return flag;
}
/**********
* 释放内存。在该方法中实现了根据对bitmap
* 进行判断而决定是否对伙伴块进行合成。
* 若需要合成,则返回合成的对象,若不需要合成则返回null
* @param o 块组号
* @param n 制定块(页框号为标志)
* 释放
*/
void retrieve(int o,int n) {//retrive(3,504)
Block b=orders[o].retrieve(n);//返回一个大块, O4中的
Block flag = null;
while(b!=null) {//o4中这个块存在,合并
flag = b;
b=orders[o+1].retrieve(b.getBlockStart());
o++;
if(o==9) {
break;
}
}
if(o!=9 && b!=null) {
orders[o+1].freeList.addBlock(b);
}
if(flag!=null) {
orders[o].freeList.addBlock(flag);
}
}
void initialize() {
int amount = frameAmount;
int num = 0;
while(amount!=0) {
double a =Math.log((double)amount)/Math.log((double)2);
int i = (int)a;
if(i > 9) {
i = 9;
}
i =(int)((i+1)*Math.random());
i = 9;
Block block = new Block(num,(int)Math.pow(2, i));
num = (int)(num + Math.pow(2, i));
amount = amount - (int)Math.pow(2, i);
orders[i].freeList.addBlock(block);
orders[i].bitMap.map.put(block.getBlockStart()>>(1+i), 0);
}
for(int i = 0; i < 10;i++) {
amount = frameAmount;
num = 0;
while(amount!=0) {
int i1 = i;
Block block = new Block(num,(int)Math.pow(2, i1));
num = (int)(num + Math.pow(2, i1));
amount = amount - (int)Math.pow(2, i1);
orders[i1].bitMap.map.put(block.getBlockStart()>>(1+i1), 0);
}
}
}
}
//Order是块组类
package buddy;
import java.util.Vector;
import javax.swing.JOptionPane;
public class Order {
BitMap bitMap;
FreeList freeList;
int mic;//表示该块组的2的幂次的数值
int size;//表示该块组的的块的数目的多少
Vector<Block> usingFrames;
Order(int num){
this.mic=num;
bitMap=new BitMap();//新建一个位图对象
freeList=new FreeList();//新建一个链表
size=0;//初始化时里面应该什么都没有
usingFrames=new Vector<Block>();
}//有问题????????????
public Order() {
// TODO 自动生成的构造函数存根
}
/**********
*
* @param num 申请的页框数
* @return 如果满足分配条件则返回被分配出去的Block对象,若不能成功分配则返回null
*/
Block allocate(int num) { //int num没有用吧?
if(freeList.isNull()==true)
{
return null;
}
else
{
Block re=freeList.useFirst();
int bian=re.getBlockStart()>>(1+mic);//得到该伙伴的编号,方便取非运算
bitMap.exlusiveOR(bian);
return re;
}
}//进行完成分配操作
/***********
* n为要被释放的页框号
* 对位图进行判断,决定是否有伙伴块需要合并,若合并成功则返回合并成功后的Block对象,若不需要合并则返回null
*/
Block retrieve(int n) {
int flag = 0;
for(int i=0;i<usingFrames.size();i++)
{
Block temp=usingFrames.get(i);
int bian=temp.getBlockStart();
if(bian==n)
{
flag= 1;
usingFrames.remove(i);
int op=bitMap.exlusiveOR(n>>(1+mic));
if(mic!=9&&op==0)
{
//进行合并
//首先要找到他的伙伴块,因为当分配之后链表中相邻的块不一定是伙伴块因此要遍历并找到编号进行筛选
int huo = 0;
if(n+(int)Math.pow(2, mic)>>(1+mic) == n>>(1+mic)) {
huo = n+(int)Math.pow(2, mic);
}
else if(n-(int)Math.pow(2, mic)>>(1+mic) == n>>(1+mic)) {
huo = n-(int)Math.pow(2, mic);
}
Block huoban=freeList.query(huo);
if(huoban!=null)
{
Block ne=Block.together(huoban, temp);//将两个块进行合并
freeList.remove(huoban);
JOptionPane.showMessageDialog(null, String.valueOf(huoban.getBlockStart())+"和"+String.valueOf(temp.getBlockStart())+"合并", "提示", JOptionPane.INFORMATION_MESSAGE);
return ne;//将合并后的Block返回,在Buddy中进行下一步的释放
}
else {
freeList.addBlock(temp);//如果释放到该块组对象的时候无法继续合并那么会将Block加入到这里
return null;
}
}
else
{
freeList.addBlock(temp);//如果释放到该块组对象的时候无法继续合并那么会将Block加入到这里
return null;
}
}
}//找到了要释放的那个块并从vector中移除
if(mic!=9&&flag == 0) {
int op=bitMap.exlusiveOR(n>>(1+mic));
if(op==0)
{
//进行合并
//首先要找到他的伙伴块,因为当分配之后链表中相邻的块不一定是伙伴块因此要遍历并找到编号进行筛选
int huo = 0;
if(n+(int)Math.pow(2, mic)>>(1+mic) == n>>(1+mic)) {
huo = n+(int)Math.pow(2, mic);
}
else if(n-(int)Math.pow(2, mic)>>(1+mic) == n>>(1+mic)) {
huo = n-(int)Math.pow(2, mic);
}
Block huoban=freeList.query(huo);
if(huoban!=null)
{
Block temp = new Block(n,(int)Math.pow(2,mic-1));
Block ne=Block.together(huoban, temp);//将两个块进行合并
freeList.remove(huoban);
JOptionPane.showMessageDialog(null, String.valueOf(huoban)+"和"+String.valueOf(temp)+"合并", "提示", JOptionPane.INFORMATION_MESSAGE);
return ne;//将合并后的Block返回,在Buddy中进行下一步的释放
}
}
}
return null;//没有找到释放的块
}
void useBlock(Block block)
{
int bianhao=block.getBlockStart()>>(1+mic);
freeList.query(bianhao);//相当于在List中查找然后删除并返回
}
}
RandomNum...是随机数类
package buddy;
import java.math.*;
public class RandomNumFactory {
/*******
*
* 用于分配页框时调用
* 随机产生小于n且>0的整数并返回
*/
int getFrameNum(int n) {
int m=0;
do{
m=(int)(n*Math.random());
}while(m==0);
return m;
}
/*************
*
* 遍历orders中所有Order对象的bitmap,获取所有处于忙状态的块,然后随机选择一个块进行返回
* @return
*/
Block getFrameAndBlockNum(Order[] orders) {
Block block=null;
int []a=new int[10];
for(int i=0;i<10;i++){
a[i]=orders[i].usingFrames.size();
}
if(a[0]==0&&a[1]==0&&a[2]==0&&a[3]==0&&a[4]==0&&a[5]==0&&a[6]==0&&a[7]==0&&a[8]==0&&a[9]==0)
{
return null;
}
else{
int m=0,n=0;
m=(int)(10*Math.random());
while(orders[m].usingFrames.size()==0){
m=(int)(10*Math.random());
}
n=(int)(orders[m].usingFrames.size()*Math.random());
block=orders[m].usingFrames.get(n);
return block;
}
}
}
//Block是具体块
package buddy;
/*********
*
* 块类,双向链表,实现双向链表的操作
*
*/
public class Block implements Comparable<Block>{
private int blockStart;//块起始地址(用页框号表示)
private int blockSize;//块大小
public Block(int num, int i) {
// TODO 自动生成的构造函数存根
blockStart = num;
blockSize = i;
}
/**
* @return blockStart
*/
public int getBlockStart() {
return blockStart;
}
/**
* @param blockStart 要设置的 blockStart
*/
public void setBlockStart(int blockStart) {
this.blockStart = blockStart;
}
/**
* @return blockSize
*/
public int getBlockSize() {
return blockSize;
}
/**
* @param blockSize 要设置的 blockSize
*/
public void setBlockSize(int blockSize) {
this.blockSize = blockSize;
}
public static Block together(Block a,Block b)
{
if(a.getBlockStart()>b.getBlockStart())
{
return new Block(b.blockStart,b.blockSize*2);
}
else
{
return new Block(a.blockStart,a.blockSize*2);
}
}
@Override
public int compareTo(Block arg0) {
// TODO 自动生成的方法存根
return (this.blockStart-arg0.blockStart);
}
}
位图类
package buddy;
import java.util.HashMap;
import java.util.Map;
/**********
*
* 位图类,用于标记伙伴块是否处于忙状态
*
*/
public class BitMap {
Map<Integer,Integer> map;//第一个int表示页框号(实际为页框号对应的块组),第二个int是该页框号对应的状态的标志位
BitMap(){
map = new HashMap<Integer,Integer>();
}
/*****************
*
* 对页框n的标志位执行异或操作!!!!!!!!!!!!!!!!!
*/
int exlusiveOR(int n){
int c=map.get(n);
if(c == 0) {
c = 1;
}
else {
c= 0;
}
map.put(n, c);
return c;
}
}
//画图Draw,用来显示分配的结果
package buddy;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics2D;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import java.awt.Graphics;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class Draw {
private JFrame frame = null;
private JTextField textField;
private JTextField textField_1;
private MyPanel panel=null;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Draw(Order[] orders) {
initialize(orders);
}
/**
* Initialize the contents of the frame.
*/
private void initialize(Order[] orders) {
frame = new JFrame();
frame.setBounds(0, 0, 1763, 972);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().setLayout(null);
frame.setVisible(true);
textField = new JTextField();
textField.setEditable(false);
textField.setText("\u8BF7\u8F93\u5165\u8981\u663E\u793A\u7684\u5757\u7EC4\u53F7\uFF1A");
textField.setBounds(14, 13, 172, 24);
frame.getContentPane().add(textField);
textField.setColumns(10);
textField_1 = new JTextField();
textField_1.setBounds(186, 13, 58, 24);
frame.getContentPane().add(textField_1);
textField_1.setColumns(10);
JButton btnNewButton = new JButton("\u786E\u5B9A");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String num = textField_1.getText();
int n = Integer.parseInt(num);
draw(n,orders);
}
});
btnNewButton.setBounds(256, 13, 79, 24);
frame.getContentPane().add(btnNewButton);
}
void draw(int n,Order[] orders) {// draw(Order[] orders)
// MyPanel[] panels = new MyPanel[10];
// for (int i = 0; i < 10; i++) {
// panels[i] = new MyPanel(orders[i].freeList,i); // new MyPanel(i,orders[i].freeList);
// panels[i].setBounds(0, 60 * i + 20, 923, 50);
// frame.getContentPane().add(panels[i]);
// }
if(panel!=null) {
frame.remove(panel);
}
panel = new MyPanel(n,orders[n].freeList);
panel.setBounds(0, 50, 1763, 900);
frame.getContentPane().add(panel);
frame.repaint();
}
class MyPanel extends JPanel {
private static final long serialVersionUID = 1L;
FreeList freelist;
int num;
MyPanel(int i,FreeList freelist) {
this.freelist = freelist;
num = i;
}
public void paint(Graphics graphics) {
super.paint(graphics);
Graphics g2d = (Graphics2D) graphics;
g2d.setColor(Color.black);
g2d.drawOval(60-40, 0, 30, 30);
JTextField fieldd = new JTextField();
fieldd.setBounds(25, 5, 20, 20);
Font ff=new Font("宋体",Font.PLAIN,9);
fieldd.setFont(ff);
fieldd.setText(String.valueOf(num));
fieldd.setBackground(Color.GRAY);
fieldd.setEditable(false);
this.add(fieldd);
int j = 0;
int flag = 28;
for(int i = 0; i < freelist.freelist.size();i++) {
g2d.drawLine(60 * (29-flag) + 30-40, 15+40*j, 60 * (29-flag) + 30 + 30-40, 15+40*j);// g2d.drawLine(60+30*i, 15,60+30+30, 15);
//g2d.drawRect(60 * ((29-flag) + 1)-40, 0+40*j, 30, 30);
JTextField field = new JTextField();
field.setBounds(60 * ((29-flag) + 1)-40, 0+40*j, 30, 30);
Font f=new Font("宋体",Font.PLAIN,9);
field.setFont(f);
field.setText(String.valueOf(freelist.freelist.get(i).getBlockStart()));
field.setEditable(false);
this.add(field);
flag--;
if(flag==0) {
j++;
flag = 28;
}
}
}
}
}
//用来存储Block对象的链表
package buddy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.math.*;
public class FreeList {
List<Block> freelist;//空闲块链表
/**********
* 构造函数
*/
FreeList(){
freelist = new ArrayList<Block>();
}
/*********
* 判断freelist是否为空
*/
boolean isNull() {
if(freelist.isEmpty())
{
return (Boolean) true;
}
else
{
return false;
}
}
/**************
*
* 使用freelist中页框号最小的块(Block),从freelist中去除并作为返回值
*/
Block useFirst() {
if(isNull())
{
return null;
}
else
{
return freelist.remove(0);
}
}
/**************
*
* 添加空闲块,应保持freelist中的Block是按页框号从小到大排序的,以保证useFirst方法的正确
*/
void addBlock(Block b) {
freelist.add(b);
if(freelist!=null) {
Collections.sort(freelist);
}
}//表示的是
Block query(int bian)
{
for(int i=0;i<freelist.size();i++) {
if(freelist.get(i).getBlockStart()==bian) {
return freelist.get(i);
}
}
return null;
}
void remove(Block b) {
for(int i=0;i<freelist.size();i++)
{
if(freelist.get(i).getBlockStart() == b.getBlockStart()) {
freelist.remove(i);
}
}
}
}
//主框架
package buddy;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JRadioButtonMenuItem;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JButton;
import java.awt.Button;
import java.awt.BorderLayout;
public class MainFrame {
private JFrame frmBuddy;
private String physicalSpace;
private String frameSize;
private SetFrame setFrame;
private Buddy buddy;
private RandomNumFactory rnf;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainFrame window = new MainFrame();
window.frmBuddy.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public MainFrame() {
physicalSpace = null;
frameSize = null;
rnf = new RandomNumFactory();
setFrame = new SetFrame();
setFrame.addListener(this);
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frmBuddy = new JFrame();
frmBuddy.setTitle("\u4F19\u4F34\u5806");
frmBuddy.setBounds(100, 100, 438, 193);
frmBuddy.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frmBuddy.getContentPane().setLayout(null);
Button button = new Button("\u8BBE\u7F6E\u5185\u5B58\u6570\u636E");
button.setBounds(6, 10, 98, 125);
frmBuddy.getContentPane().add(button);
Button button_2 = new Button("\u5206\u914D\u9875\u6846");
button_2.setActionCommand("\u5206\u914D\u5185\u5B58");
button_2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
int num = rnf.getFrameNum(128);
String s = "是否分配"+num+"个页框?";
int flag = JOptionPane.showConfirmDialog(null, s,"请确认信息!",JOptionPane.YES_NO_OPTION);
if(flag == 0) {
buddy.allocate(num);
}
else {
JOptionPane.showMessageDialog(null, "已取消操作!", "提示", JOptionPane.INFORMATION_MESSAGE);
}
}
});
button_2.setBounds(110, 10, 98, 125);
frmBuddy.getContentPane().add(button_2);
Button button_3 = new Button("\u91CA\u653E\u9875\u6846");
button_3.setActionCommand("\u91CA\u653E\u5185\u5B58");
button_3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
Block b = rnf.getFrameAndBlockNum(buddy.orders);
if(b==null) {
JOptionPane.showMessageDialog(null, "没有需要释放的内存", "提示", JOptionPane.INFORMATION_MESSAGE);
}
else {
int n = b.getBlockStart();
int o = (int)(Math.log(b.getBlockSize())/Math.log(2));
String s = "是否释放块组"+o+"中起始地址为"+n+"的块?";
int flag = JOptionPane.showConfirmDialog(null, s,"请确认信息!",JOptionPane.YES_NO_OPTION);
if(flag == 0) {
buddy.retrieve(o,n);
JOptionPane.showMessageDialog(null, "释放成功!", "提示", JOptionPane.INFORMATION_MESSAGE);
}
else {
JOptionPane.showMessageDialog(null, "已取消操作!", "提示", JOptionPane.INFORMATION_MESSAGE);
}
}
}
});
button_3.setBounds(214, 10, 98, 125);
frmBuddy.getContentPane().add(button_3);
Button button_1 = new Button("\u663E\u793A");
button_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
Draw d = new Draw(buddy.orders);
}
});
button_1.setBounds(318, 10, 96, 125);
frmBuddy.getContentPane().add(button_1);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
setFrame.getSetFrame().setVisible(true);
}
});
}
public String getPhysicalSpace() {
return physicalSpace;
}
public void setPhysicalSpace(String physicalSpace) {
this.physicalSpace = physicalSpace;
}
/**
* @return frameSize
*/
public String getFrameSize() {
return frameSize;
}
/**
* @param frameSize 要设置的 frameSize
*/
public void setFrameSize(String frameSize) {
this.frameSize = frameSize;
}
public void respond() {
physicalSpace = setFrame.getPhySpace();
frameSize = setFrame.getFrSize();
buddy = new Buddy(Integer.parseInt(physicalSpace.substring(0, 3)),Integer.parseInt(frameSize.substring(0, 1)));
}
}
//设置框架
package buddy;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.JComboBox;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.Window.Type;
public class SetFrame {
private JFrame SetFrame;
private JTextField textField;
private JTextField textField_1;
private String phySpace;
private String frSize;
private MainFrame mainFrame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
SetFrame window = new SetFrame();
window.SetFrame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public SetFrame() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
SetFrame = new JFrame();
SetFrame.setType(Type.UTILITY);
SetFrame.setTitle("\u5185\u5B58\u7A7A\u95F4\u53CA\u5176\u5212\u5206");
SetFrame.setBounds(100, 100, 332, 179);
SetFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
SetFrame.getContentPane().setLayout(null);
textField = new JTextField();
textField.setEditable(false);
textField.setText("\u8BF7\u9009\u62E9\u7269\u7406\u7A7A\u95F4\u5927\u5C0F\uFF1A");
textField.setBounds(14, 13, 186, 30);
SetFrame.getContentPane().add(textField);
textField.setColumns(10);
textField_1 = new JTextField();
textField_1.setText("\u8BF7\u9009\u62E9\u6BCF\u4E2A\u9875\u6846\u7684\u5927\u5C0F\uFF1A");
textField_1.setEditable(false);
textField_1.setBounds(14, 56, 186, 30);
SetFrame.getContentPane().add(textField_1);
textField_1.setColumns(10);
JComboBox physicalSpace = new JComboBox();
physicalSpace.setModel(new DefaultComboBoxModel(new String[] {"256M bytes", "512M bytes"}));
physicalSpace.setBounds(200, 13, 109, 30);
SetFrame.getContentPane().add(physicalSpace);
JComboBox frameSize = new JComboBox();
frameSize.setModel(new DefaultComboBoxModel(new String[] {"1K bytes", "2K bytes", "4K bytes"}));
frameSize.setBounds(200, 56, 109, 30);
SetFrame.getContentPane().add(frameSize);
JButton confirm = new JButton("\u786E\u5B9A");
confirm.setToolTipText("l");
confirm.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
setPhySpace(physicalSpace.getSelectedItem().toString());
setFrSize(frameSize.getSelectedItem().toString());
thisNotify();
SetFrame.setVisible(false);
}
});
confirm.setBounds(170, 99, 70, 30);
SetFrame.getContentPane().add(confirm);
JButton cancel = new JButton("\u53D6\u6D88");
cancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
SetFrame.setVisible(false);
}
});
cancel.setBounds(239, 99, 70, 30);
SetFrame.getContentPane().add(cancel);
}
public String getPhySpace() {
return phySpace;
}
public void setPhySpace(String phySpace) {
this.phySpace = phySpace;
}
public String getFrSize() {
return frSize;
}
public void setFrSize(String frSize) {
this.frSize = frSize;
}
public JFrame getSetFrame() {
initialize();
return SetFrame;
}
public void addListener(MainFrame mainFrame) {
this.mainFrame = mainFrame;
}
public void thisNotify() {
mainFrame.respond();
}
}
//以下是我的组长写的类的设计
一、系统总体功能
根据用户的选择内存物理空间的大小和每个页框的大小对系统进行初始化,完成内存空间的随机分配、随机分配页块、随机释放页块并显示各块组链表的内容的功能。
二、功能模块划分
l 内存初始化模块:根据用户选择的内存物理空间的大小和每个页框的大小将内存空间进行划分。初始化时将内存空间分配到最大的块组,即每个块占用2^9个页框。系统进行内存初始化,初始化完成后调用显示模块显示块组空闲区链表的内容。
l 分配页框模块:基于内存当前情况,随机产生申请的页框数,系统进行内存分配,分配完成后调用显示模块显示块组空闲区链表的内容
l 回收页框模块:基于内存当前情况,随机产生被占用的页框号释放,系统进行内存释放,释放完成后调用显示模块显示块组空闲区链表的内容
l 显示模块:显示块组空闲区链表的内容
三、功能处理流程
1. 内存初始化模块
2. 内存分配模块:
3. 内存回收模块:
4. 显示模块:
四、详细设计
1. Buddy类
伙伴堆类,用于分配和回收内存
属性说明:
属性名称 |
属性说明 |
orders[10] Order[] |
Order类的一个数组,用于存储块组,分别为orders[0]、orders[1]......orders[9] |
frameAmount int |
用于存储总页框数 |
storage int |
用于存储内存物理空间大小 |
frameSize int |
用来存储每一个页框的大小 |
方法说明:
方法名称 |
方法说明 |
Buddy(int storage,int frameSize); |
Buddy类构造函数,对系统进行初始化,并完成对Order类数组orders的初始化 |
boolean allocate(int num); |
用于为指定的页框数(num)分配内存。分配成功返回true,分配失败返回false。(该方法本身不分配内存,而是遍历orders内的对象,并选择合适的Order对象调用其方法allocate()。 根据order对象allocate()的返回时进行判断,分配成功则判断返回的Block对象是否应进行拆分(拆分方法Buddy类中实现,直至大小适合,拆分过程中注意对orders中Order的freelist和bitmap做相应的改动) |
void retrieve(int o,int n) |
用于在指定块组(o即块组号)回收指定块(n即页框号)。该方法本身不分配内存,遍历orders内的对象,并选择合适的Order对象调用其方法retrieve()。 |
2. Order类
块组类,用于维护位图和空闲链表还有被占用的页框号(标志页块唯一性的是页块的起始地址)
属性说明:
属性名称 |
属性说明 |
bitmap BitMap |
BitMap类的一个实例 |
freeList FreeList |
FreeList类的一个实例 |
usingFrames Vector<Block> |
用于存储被占用的页块Vector<Block> |
方法说明:
方法名称 |
方法说明 |
Order(int num) |
构造函数,根据num的值进行初始化,num表示块组内空闲链表内块的数目。完成bitmap和freeList以及usingFrames的初始化 |
Block allocate(int num) |
分配内存。首先调用freelist的isNULL()方法判断空闲链表是否为空。若为空则返回null,否则返回useFirst的返回值block对象并将该block对象从freelist中移除,并对bitmap做相应的处理。 |
Block retrieve(int n) |
释放内存。在该方法中实现了根据对bitmap进行判断而决定是否对伙伴块进行合成。若需要合成,则返回合成的对象,若不需要合成则返回null |
void useBlock(Block block) |
将参数中的块从freeList中移除,添加到usingFrames中 |
3. Bitmap类
位图类,用于标记伙伴块是否处于忙的状态,在回收合并时使用
属性说明:
属性名称 |
属性说明 |
map Bitmap |
Map<int,int>的实例对象,用于存储页框号(实际为页框号对应的块组)和标记的映射,标记位为1时表示忙,为0时表示空 |
方法说明:
方法名称 |
方法说明 |
Bitmap() |
初始化map |
void exclusiveOR(int n) |
异或操作,对页框n(实际为页框号对应的块组)的伙伴的标志执行异或操作 |
4. FreeList类
空闲链表类,用于存储所属块组中的空闲块。
属性说明:
属性名称 |
属性说明 |
freelist |
List<Block>类的实例对象,用来存储空闲块 |
方法说明:
方法名称 |
方法说明 |
FreeList() |
构造函数 |
Boolean isNull(); |
用于判断链表freelist是否为空,为空则返回true,否则返回false。 |
Block useFirst(); |
使用链表freelist头部块,返回头部Block对象并完成从链表中去除头部的操作。 |
void addBlock(Block b); |
在链表freelist中添加空闲块。 |
5. Block类
块类,链表中的元素
属性说明:
属性名称 |
属性说明 |
blockStart int |
块起始地址(用页框号表示) |
blockSize int |
块组大小,用来得到终止地址 |
next Block |
Block类实例,用来表示在链表中的下一个元素 |
prior Block |
Block类实例,用来表示在链表中的上一个元素 |
方法说明:
方法名称 |
方法说明 |
Block(int start,int size); |
构造函数 |
int getBlockStart() |
|
void setBlockStart(int blockStart) |
|
int getBlockSize() |
|
void setBlockSize(int blockSize) |
6. RandomFactory类
随机数工厂类,用来产生各种需要的随机数
属性说明:
方法说明:
方法名称 |
方法说明 |
int getFrameNum(int n) |
在随机产生页框数用于分配时调用,返回任意小于总页框数(n)的正整数。 |
Block getFrameAndBlockNum(Vector<Block>) |
随机产生被占用的页框号和块组号时调用 |
五、各模块处理流程图
1. 内存初始化模块
2. 内存分配模块
3. 内存回收模块
4. 显示模块