模拟动态分区分配(友好用户界面显示、图形化交互界面、可视化、操作系统作业)

您所在的位置:网站首页 操作系统动态分区分配算法课程设计 模拟动态分区分配(友好用户界面显示、图形化交互界面、可视化、操作系统作业)

模拟动态分区分配(友好用户界面显示、图形化交互界面、可视化、操作系统作业)

2024-02-07 00:56| 来源: 网络整理| 查看: 265

模拟动态分区分配算法(友好用户界面显示、图形化交互界面、可视化、操作系统作业) 一、 前言二、实验结果1、首次适应算法-程序执行结果演示2、循环首次算法-程序执行结果演示3、最佳适应算法-程序执行结果演示 三、算法:1、采用的数据结构2、首次适应算法3、循环首次适应算法4、最佳适应算法5、点击开始按钮-进行界面和数据的初始化6、执行确定按钮-检测数据合法并启动相应算法7、更新picturebox8、更新listview9、内存回收10、 完整代码

一、 前言

编写一个内存动态分区分配模拟程序,分别实现:首次适应、循环首次适应、最佳适应算法,对内存的分配和回收过程,此程序没有实现“紧凑”。 每次分配和回收后把空闲分区的变化情况以及进程的申请、释放情况最好以图形方式显示,尽可能设计一个友好的用户界面,直观显示内存区域经分配、回收的动态变化情况。

二、实验结果 1、首次适应算法-程序执行结果演示

进行分配算法测试数据:(进程-1表示此内存块是空闲区,没有进程占用) 申请空间的进程顺序及大小: 在这里插入图片描述程序执行结果 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 【进行内存回收的测试:】

进行内存回收的测试数据:(因为回收内存时,不需要内存空间大小数据,当点击确定按钮后,会检测数据是否合法,即内存中是否有此进程的id,若合法则进行回收算法,并置内存空间大小的textbox为空) 释放的(内存块/进程)序号的顺序为:1、0、2、4、3 进程1: 前后没有空闲区 ,没有合并空闲区操作 进程0: 后有空闲区——>所以0、1空闲区合并一个空闲区 进程2: 前有(0、1合并后的)空闲区——>所以(0、1)与4和并一个空闲区 进程4: 前后没有空闲区 进程3: 前(有0、1、2合并后的空闲区)后(有空闲区4)都有空闲区 ,合并成一个大空闲区(0、1、2、3、4)

程序执行结果 在这里插入图片描述 【注:释放已经释放的进程空间会提示错误,如,下图,进程1已经释成功了,再点击确定按钮,想要释放就提示错误】 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 【释放内存后再申请空间去测试,首次适应算法是从内存开始位置进行申请。如,在上图测试之后,进程6 申请内存 20 M,存在两个空闲区,如下图】 在这里插入图片描述 【 但首次适应算法,会选择另一个内存块,结果如下,所以首次适应算法演示成功】 在这里插入图片描述 在这里插入图片描述

2、循环首次算法-程序执行结果演示 建议循环首次算法测试数据为: 在这里插入图片描述在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 【 回收过程:回收进程4的内存“】 在这里插入图片描述 【回收进程2的内存:】 在这里插入图片描述 【此时空闲区有:25MB(4原来的释放区) 、28MB(2原来的释放区)、18MB(以及剩余的从未用过的空闲区)】 在这里插入图片描述【分配:进程6 24MB 按空闲区递增排序,选择起始地址为33MB的内存块】 在这里插入图片描述 【回收6进程,分配:7进程 23MB】 在这里插入图片描述 【此时,3个空闲区如表,但起始地址为33MB大小的空闲区已经分配过了,所以会在之后的量的空闲区选择,如图,得以说明,循环首次适应算法模拟成功】 在这里插入图片描述 在这里插入图片描述 3、最佳适应算法-程序执行结果演示

与上类似,且可以各算法切换测试。

三、算法: 1、采用的数据结构

采用的数据结构:链表而非分区表表示内存使用情况。自定义Nodespace类用于记录每个内存块的使用情况包括空闲块和占用块。因为C#里没有指针,所以为实现链表的功能,采用C#的list类实现,Removeat():进行空闲块的合并(即为空闲块的删除)、Insert():进程申请内存空间成功把新内存块信息加入到链表,等等方法、、、、

public class Nodespace { public int taskid; // 任务号 public int begin; // 开始地址 public int size; // 大小 public int status; // 状态 0代表占用,1代表空闲 public Nodespace(int taskid, int begin, int size, int status) { this.taskid = taskid; this.begin = begin; this.size = size; this.status = status; } 2、首次适应算法 注: public static List ls = new List(); c#中Listfind的使用参考链接如下,总结的很简单,截图如下 c#中List < T > find使用示例 在这里插入图片描述函数完整代码: #region 首次适应算法 public bool FirstPartition(int taskid,int size) { int index = ls.FindIndex(param => param.size >= size && param.status == 1); if (index != -1) { if (ls[index].size > size) { //int teskid, int begin, int size, int status Nodespace t = new Nodespace(taskid, ls[index].begin, size, 0); ls[index].begin += size; ls[index].size -= size; ls.Insert(index, t); } else { ls[index].status = 0; ls[index].size = size; ls[index].taskid = taskid; } } else { return false; } return true; } #endregion 3、循环首次适应算法 注:查找在list中从startIndex(全局变量,初始值0)到list.ount大于申请的size的空闲内存块,若没找到,再从0~startIndex找每一次切换到循环首次算法后,都要把startIndex = 0;(我认为各内存分配算法,只是在分配时分配方法不一样,free内存释放过程一样,所以此程序中途是可以切换使用分配算法的) private void rb_cyclepart_CheckedChanged(object sender, EventArgs e) { startIndex = 0; } 函数完整代码: #region 循环首次适应算法 public bool CyclyFirstPartition(int taskid, int size) { int index = ls.FindIndex(startIndex,param => param.size >= size && param.status == 1); if (index == -1) index = ls.FindIndex(0, startIndex, param => param.size >= size && param.status == 1); if (index != -1) { if (ls[index].size == size) { ls[index].status = 0; ls[index].taskid = taskid; } else { Nodespace t = new Nodespace(taskid, ls[index].begin, size, 0); ls[index].begin += size; ls[index].size -= size; ls.Insert(index, t); startIndex = (index+1)%ls.Count; } return true; } else { return false; } } #endregion 4、最佳适应算法 C#中List.Sort()–集合排序方法有四种,我选用方法一、对Nodespace类继承IComparable接口,实现CompareTo()方法,参考文章链接及截图如下, C#中List.Sort()–集合排序方法分析 在这里插入图片描述之所以设置两个排序类,因为分配时,空闲区按size大小从小到大排序从而找到最适宜的大小的空闲内存块;回收时,空闲区按开始地址排序,查找释放区的前后有无空闲区从而对应着释放空间时的4种情况(如图1),从而有空闲区进行合并的不同方式。但用NodespaceCompare_partition类进行size从小到大的排序后,后续的释放会打乱原有内存块地址递增的顺序。我在写的时候没想到这么做,出现图2所示的出现画不出内存块从而变白色,以及超过绘图范围0~200MB的情况、各种小问题。 图1: 图1图2: 图2 //分配时,空闲区按size大小从小到大排序 public class NodespaceCompare_partition : IComparer { public int Compare(Nodespace x, Nodespace y) { return (x.size.CompareTo(y.size)); } } //回收时,空闲区按开始地址排序 public class NodespaceCompare_free : IComparer { public int Compare(Nodespace x, Nodespace y) { return (x.begin.CompareTo(y.begin)); } 函数完整代码: #region 最佳适应 public bool BestPartiton(int taskid, int size) { //因为这三个算法目的只是选择合适的内存空间,所以中间可以切换执行算法,从而不能确保执行最佳算法之前也执行的是执行最佳算法。从而无法确保他是有序的 ls.Sort(new NodespaceCompare_partition()); int index = ls.FindIndex(param => param.size >= size && param.status == 1); if (index!= -1) { if (ls[index].size == size) { ls[index].status = 0; ls[index].taskid = taskid; } else { Nodespace t = new Nodespace(taskid, ls[index].begin, size, 0); ls[index].begin += size; ls[index].size -= size; ls.Insert(index,t); } return true; } return false; } #endregion 5、点击开始按钮-进行界面和数据的初始化

初始界面:程序默认选择分配内存,首次适应算法 如图 在这里插入图片描述

数据初始化后界面,即点击开始按钮进行数据初始化,清空内存块的进程。(点击开始按钮如下界面,左、右侧表示的内存块是(0~200MB大小的内存),左侧表示进行分配或回收的算法之前的内存状况,右侧是进行分配或回收的算法之后的内存状况) 如图在这里插入图片描述

使用4个piicturebox,一个listview,分别对应着程序中的画图部分的图一、图二、图三、图四,图四,以及右边的表格。图四初始后固定,图1、2、3每次执行(点击确定按钮,并检测输入数据合法后执行)都会重绘

开始画图的时候,我不知道原来在bitmap中画,只要考虑相对位置就好了(因为bitmap放到picturebox,picturebox本身就带有坐标位置),就产生了四个画板什么都没有的情况,而且相对位置画这构图时简单了好多

清空并初始化数据:

ls.Clear(); //加入进程名-1,起始位置0,size=200,状态1的内存块 Nodespace nodespace = new Nodespace(-1, 0, 200, 1); ls.Add(nodespace); 绘图中,我觉得我的表示内存块的矩形太丑了,出现了只有右、下有边情况 简单的更改方法: 先fill再draw.后来我觉得是画笔对齐 PenAlignment方式问题,没空就不测试了。这个参考链接的作者在写GDI学习记录系列的文章特别简单、扼要、易懂,值得学习:GDI+学习记录(4)-画笔对齐 PenAlignment g3.FillRectangle(sbs[0], r1); g3.DrawRectangle(penBlack, r1);

如图 在这里插入图片描述

在这里插入图片描述

函数完整代码: #region 开始按钮 private void bt_start_Click(object sender, EventArgs e) { ls.Clear(); Nodespace nodespace = new Nodespace(-1, 0, 200, 1); ls.Add(nodespace); Graphics g12 = pb_mem1.CreateGraphics(); g12.Clear(Color.White); Graphics g22 = pb_mem2.CreateGraphics(); g22.Clear(Color.White); Graphics g32 = pb_mem3.CreateGraphics(); g32.Clear(Color.White); Bitmap b1 = new Bitmap(200, 480); Graphics g1 = Graphics.FromImage(b1); Rectangle r1 = new Rectangle(30,40,90,ls[0].size); g1.FillRectangle(sbs[0], r1); g1.DrawRectangle(penBlack, r1); g1.DrawString("0MB", myfont, sbs[3], new Point(0, 30)); g1.DrawString("200MB", myfont, sbs[3], new Point(0, 240)); g12.DrawImage(b1, 0, 0); Bitmap b3 = new Bitmap(200, 480); Graphics g3 = Graphics.FromImage(b3); g3.FillRectangle(sbs[0], r1); g3.DrawRectangle(penBlack, r1); g3.DrawString("0MB", myfont, sbs[3], new Point(0, 30)); g3.DrawString("200MB", myfont, sbs[3], new Point(0, 240)); g32.DrawImage(b3, 0, 0); //free 图1 b1.Dispose(); b1 = null; g1.Dispose(); g1 = null; g12.Dispose(); g12 = null; //free 图3 b3.Dispose(); b3 = null; g3.Dispose(); g3 = null; g32.Dispose(); g32 = null; //画图4------------------------------------------------------------ Bitmap b_example = new Bitmap(600, 50); Graphics gb_emp = Graphics.FromImage(b_example); //黄 Rectangle r_emp1 = new Rectangle(10, 0, 60, 20); gb_emp.FillRectangle(sbs[0], r_emp1); gb_emp.DrawRectangle(penBlack, r_emp1); gb_emp.DrawString("空闲区", myfont, sbs[0], new Point(75, 5)); //粉 Rectangle r_emp2 = new Rectangle(130, 0, 60, 20); gb_emp.FillRectangle(sbs[1], r_emp2); gb_emp.DrawRectangle(penBlack, r_emp2); gb_emp.DrawString("申请或释放区", myfont, sbs[1], new Point(190, 5)); //蓝 Rectangle r_emp3 = new Rectangle(290, 0, 60, 20); gb_emp.FillRectangle(sbs[2], r_emp3); gb_emp.DrawRectangle(penBlack, r_emp3); gb_emp.DrawString("占用区", myfont, sbs[2], new Point(360, 5)); Graphics gp_emp = pb_example.CreateGraphics(); gp_emp.DrawImage(b_example, 0, 0); b_example.Dispose(); b_example = null; gb_emp.Dispose(); gb_emp = null; gp_emp.Dispose(); gp_emp = null; } #endregion 6、执行确定按钮-检测数据合法并启动相应算法 #region 执行确定按钮 private void bt_certain_Click(object sender, EventArgs e) { //确保回收操作执行合法 if (rb_free.Checked && (rb_bestpart.Checked || rb_cyclepart.Checked || rb_firstpart.Checked) && tb_name.Text != "") { int taskid = Convert.ToInt32(tb_name.Text); pointer = taskid; int index = ls.FindIndex(param => param.taskid == taskid); if (index == -1) { MessageBox.Show("没有该进程!,不予执行"); return; } else { tb_size.Text = ""; /*//当free可执行时,使其他按钮无法再变化,直到显示执行完后 rb_free.Enabled = false; rb_part.Enabled = false; rb_firstpart.Enabled = false; rb_cyclepart.Enabled = false; rb_bestpart.Enabled = false;*/ ShowMem1(); FreeMem(taskid, index); ShowMem23(); DrawTable(); MessageBox.Show("内存回收成功!"); /*rb_free.Enabled = true; rb_part.Enabled = true; rb_firstpart.Enabled = true; rb_cyclepart.Enabled = true; rb_bestpart.Enabled = true;*/ } } else if (rb_part.Checked && (rb_bestpart.Checked || rb_cyclepart.Checked || rb_firstpart.Checked) && tb_name.Text != "" && tb_size.Text != "") { int taskid = Convert.ToInt32(tb_name.Text); int index = ls.FindIndex(param => param.taskid == taskid); if (index != -1) { MessageBox.Show("该进程已存在!"); tb_name.Text = ""; return; } int size = Convert.ToInt32(tb_size.Text); pointer = -1;//不在图1中画绿色内存块 ShowMem1(); pointer = taskid;//在图3中画绿色内存块 bool flag = false; if (rb_firstpart.Checked) flag = FirstPartition(taskid, size); else if (rb_bestpart.Checked) flag = BestPartiton(taskid, size); else if (rb_cyclepart.Checked) { flag = CyclyFirstPartition(taskid, size); } if (flag) { ShowMem23(); DrawTable(); } else MessageBox.Show("没有合适的内存空间,内存分配失败"); } } #endregion 7、更新picturebox

1.图2、3的更新放在一个函数,数据同时变化,在执行算法前或者说更新链表数据后执行, 图1的更新单独放在一个函数,在执行算法前或者说更新链表数据前执行

#region 画图1 public void ShowMem1() { //清空绘图 Graphics g12 = pb_mem1.CreateGraphics(); g12.Clear(Color.White); //画图1---------------------------------------------- Bitmap b1 = new Bitmap(200,480); Graphics g1 = Graphics.FromImage(b1); //内存块据滑板 左:30 上:40 长:90 高:200 Rectangle r1 = new Rectangle(30, 40, 90, 200); g1.DrawString("200MB", myfont, sbs[3], new Point(0, 240)); g1.DrawRectangle(penBlack, r1); //画内存使用情况 foreach (Nodespace nodespace in ls) { int begin = nodespace.begin; int size = nodespace.size; int taskid = nodespace.taskid; int state = nodespace.status; //size 输入的内存空间大小就为内存块的高,在10-80都可 //begin 从0开始,按size大小增加 Rectangle t = new Rectangle(30, begin + 40, 90, size); if (state == 1) g1.FillRectangle(sbs[0], t); else { if (rb_free.Checked&&pointer == nodespace.taskid) g1.FillRectangle(sbs[1], t); else g1.FillRectangle(sbs[2], t); g1.DrawRectangle(penBlack, t); g1.DrawString("进程" + Convert.ToString(taskid)+"大小"+size+"MB", myfont, sbs[3], t); //比矩形的左上角高10,左30 g1.DrawString(Convert.ToString(begin) + "MB", myfont, sbs[3], new Point(0, begin + 30)); g1.DrawString(Convert.ToString(begin + size + "MB"), myfont, sbs[3], new Point(0, begin + size + 30)); } } g12.DrawImage(b1, 0, 0); //结束画图1 //free 图1 b1.Dispose(); b1 = null; g1.Dispose(); g1 = null; g12.Dispose(); g12 = null; } #endregion #region 画图2和3 public void ShowMem23() { //清空绘图--------------------------------------------- Graphics g22 = pb_mem2.CreateGraphics(); g22.Clear(Color.White); //画图2 Bitmap b2 = new Bitmap(200, 480); Graphics g2 = Graphics.FromImage(b2); //分配还是回收 string s1 = ""; if (rb_part.Checked) s1 = "申请空间"; else if (rb_free.Checked) s1 = "释放空间"; g2.DrawString(s1, myfont, sbs[3], new Point(40, 90)); //内存块 Rectangle r2 = new Rectangle(30, 110, 80, 30); g2.FillRectangle(sbs[1], r2); g2.DrawRectangle(penBlack, r2); g2.DrawString("进程"+tb_name.Text+":大小 "+tb_size.Text+" MB", myfont, sbs[3],r2); //箭头 Pen p = new Pen(sbs[0], 5); p.StartCap = System.Drawing.Drawing2D.LineCap.Round; p.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor; g2.DrawLine(p, 10, 180, 130, 180); //算法名 string s2 = ""; if (rb_firstpart.Checked) s2 = "首次适应算法"; else if (rb_bestpart.Checked) s2 = "最佳适应算法"; else if (rb_cyclepart.Checked) s2 = "循环适应算法"; g2.DrawString(s2, myfont, sbs[3], new Point(30, 150)); g22.DrawImage(b2, 0, 0); //画图2结束 //清空绘图3-------------------------- Graphics g32 = pb_mem3.CreateGraphics(); g32.Clear(Color.White); //画图3 //画黑框 Rectangle r1 = new Rectangle(30, 40, 90, 200); Bitmap b3 = new Bitmap(200, 480); Graphics g3 = Graphics.FromImage(b3); g3.DrawRectangle(penBlack, r1); //g3.DrawString("0MB", myfont, sbs[3], new Point(0, 30)); g3.DrawString("200MB", myfont, sbs[3], new Point(0, 240)); //画内存使用情况 foreach (Nodespace nodespace in ls) { int begin = nodespace.begin; int size = nodespace.size; int taskid = nodespace.taskid; int state = nodespace.status; Rectangle t = new Rectangle(30, begin + 40, 90, size); if (state == 1) { g3.FillRectangle(sbs[0], t); g3.DrawRectangle(penBlack, t); } else { if (rb_part.Checked && pointer == nodespace.taskid) g3.FillRectangle(sbs[1], t); else g3.FillRectangle(sbs[2], t); g3.DrawRectangle(penBlack, t); g3.DrawString("进程" + Convert.ToString(nodespace.taskid) + ":大小" + size + "MB", myfont, sbs[3], t); g3.DrawString(Convert.ToString(begin) + "MB", myfont, sbs[3], new Point(0, begin + 30)); g3.DrawString(Convert.ToString(begin + size + "MB"), myfont, sbs[3], new Point(0, begin + size + 30)); } } g32.DrawImage(b3, 0, 0); //结束画图3 //free 图3------------------------------------------------------------- b3.Dispose(); b3 = null; g3.Dispose(); g3 = null; g32.Dispose(); g32 = null; //free 图2 b2.Dispose(); b2 = null; g2.Dispose(); g2 = null; g22.Dispose(); g22 = null; } #endregion 8、更新listview 这个部分超简单,就不过赘述了 #region 画表格 public void DrawTable() { lv_mem.BeginUpdate();//数据更新,UI暂时挂起,直到EndUpdate绘制控件,可以有效避免闪烁并大大提高加载速度 lv_mem.Items.Clear();//只移除所有的项。 foreach (Nodespace nodespace in ls) { ListViewItem lvi = new ListViewItem(); lvi.Text = nodespace.begin+"MB"; lvi.SubItems.Add(nodespace.begin + nodespace.size + "MB"); lvi.SubItems.Add(nodespace.size + "MB"); lvi.SubItems.Add(nodespace.status == 1 ? "空闲" : "占用"); lvi.SubItems.Add("进程"+nodespace.taskid); lv_mem.Items.Add(lvi); } lv_mem.EndUpdate();//结束数据处理,UI界面一次性绘制。 } #endregion 9、内存回收 #region 回收 public bool FreeMem(int taskid,int index) { if (rb_bestpart.Checked) ls.Sort(new NodespaceCompare_free()); //如果前后都没有空闲区,并不需要从list中移除,更改变量即可 ls[index].status = 1; ls[index].taskid = -1; int size = ls[index].size; //前面空闲区,移出自己 if (index - 1 >=0 && ls[index - 1].status == 1) { ls[index-1].size += size ; ls.RemoveAt(index); index -= 1; } //后面有空闲区,更改自己空闲区的大小,并移出后面的空闲区 if (index+1 public partial class MainForm : Form { int pointer=-1; Pen penBlack = new Pen(Color.Black); Pen penRed = new Pen(Color.Red); Pen penGreen = new Pen(Color.Green); Pen penBlue = new Pen(Color.Blue); Font myfont = new Font("宋体", 10); StringFormat format= new StringFormat(); public static List ls; int startIndex=0; //红色 空闲;绿色:释放 ;蓝色:占用 SolidBrush [] sbs= { new SolidBrush(Color.Red), new SolidBrush(Color.Orange), new SolidBrush(Color.LightPink),new SolidBrush(Color.Black) }; public MainForm() { InitializeComponent(); ls = new List(); } #region 首次适应算法 public bool FirstPartition(int taskid,int size) { int index = ls.FindIndex(param => param.size >= size && param.status == 1); if (index != -1) { if (ls[index].size > size) { //int teskid, int begin, int size, int status Nodespace t = new Nodespace(taskid, ls[index].begin, size, 0); ls[index].begin += size; ls[index].size -= size; ls.Insert(index, t); } else { ls[index].status = 0; ls[index].size = size; ls[index].taskid = taskid; } } else { return false; } return true; } #endregion #region 最佳适应 public bool BestPartiton(int taskid, int size) { //因为这三个算法目的只是选择合适的内存空间,所以中间可以切换执行算法,从而不能确保执行最佳算法之前也执行的是执行最佳算法。从而无法确保他是有序的 ls.Sort(new NodespaceCompare_partition()); int index = ls.FindIndex(param => param.size >= size && param.status == 1); if (index!= -1) { if (ls[index].size == size) { ls[index].status = 0; ls[index].taskid = taskid; } else { Nodespace t = new Nodespace(taskid, ls[index].begin, size, 0); ls[index].begin += size; ls[index].size -= size; ls.Insert(index,t); } return true; } return false; } #endregion #region 循环首次适应算法 public bool CyclyFirstPartition(int taskid, int size) { int index = ls.FindIndex(startIndex,param => param.size >= size && param.status == 1); if (index == -1) index = ls.FindIndex(0, startIndex, param => param.size >= size && param.status == 1); if (index != -1) { if (ls[index].size == size) { ls[index].status = 0; ls[index].taskid = taskid; } else { Nodespace t = new Nodespace(taskid, ls[index].begin, size, 0); ls[index].begin += size; ls[index].size -= size; ls.Insert(index, t); startIndex = (index+1)%ls.Count; } return true; } else { return false; } } #endregion #region 回收 public bool FreeMem(int taskid,int index) { if (rb_bestpart.Checked) ls.Sort(new NodespaceCompare_free()); //如果前后都没有空闲区,并不需要从list中移除,更改变量即可 ls[index].status = 1; ls[index].taskid = -1; int size = ls[index].size; //前面空闲区,移出自己 if (index - 1 >=0 && ls[index - 1].status == 1) { ls[index-1].size += size ; ls.RemoveAt(index); index -= 1; } //后面有空闲区,更改自己空闲区的大小,并移出后面的空闲区 if (index+1 //清空绘图 Graphics g12 = pb_mem1.CreateGraphics(); g12.Clear(Color.White); //画图1---------------------------------------------- Bitmap b1 = new Bitmap(200,480); Graphics g1 = Graphics.FromImage(b1); //内存块据滑板 左:30 上:40 长:90 高:200 Rectangle r1 = new Rectangle(30, 40, 90, 200); g1.DrawString("200MB", myfont, sbs[3], new Point(0, 240)); g1.DrawRectangle(penBlack, r1); //画内存使用情况 foreach (Nodespace nodespace in ls) { int begin = nodespace.begin; int size = nodespace.size; int taskid = nodespace.taskid; int state = nodespace.status; //size 输入的内存空间大小就为内存块的高,在10-80都可 //begin 从0开始,按size大小增加 Rectangle t = new Rectangle(30, begin + 40, 90, size); if (state == 1) g1.FillRectangle(sbs[0], t); else { if (rb_free.Checked&&pointer == nodespace.taskid) g1.FillRectangle(sbs[1], t); else g1.FillRectangle(sbs[2], t); g1.DrawRectangle(penBlack, t); g1.DrawString("进程" + Convert.ToString(taskid)+"大小"+size+"MB", myfont, sbs[3], t); //比矩形的左上角高10,左30 g1.DrawString(Convert.ToString(begin) + "MB", myfont, sbs[3], new Point(0, begin + 30)); g1.DrawString(Convert.ToString(begin + size + "MB"), myfont, sbs[3], new Point(0, begin + size + 30)); } } g12.DrawImage(b1, 0, 0); //结束画图1 //free 图1 b1.Dispose(); b1 = null; g1.Dispose(); g1 = null; g12.Dispose(); g12 = null; } #endregion #region 画图2和3 public void ShowMem23() { //清空绘图--------------------------------------------- Graphics g22 = pb_mem2.CreateGraphics(); g22.Clear(Color.White); //画图2 Bitmap b2 = new Bitmap(200, 480); Graphics g2 = Graphics.FromImage(b2); //分配还是回收 string s1 = ""; if (rb_part.Checked) s1 = "申请空间"; else if (rb_free.Checked) s1 = "释放空间"; g2.DrawString(s1, myfont, sbs[3], new Point(40, 90)); //内存块 Rectangle r2 = new Rectangle(30, 110, 80, 30); g2.FillRectangle(sbs[1], r2); g2.DrawRectangle(penBlack, r2); g2.DrawString("进程"+tb_name.Text+":大小 "+tb_size.Text+" MB", myfont, sbs[3],r2); //箭头 Pen p = new Pen(sbs[0], 5); p.StartCap = System.Drawing.Drawing2D.LineCap.Round; p.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor; g2.DrawLine(p, 10, 180, 130, 180); //算法名 string s2 = ""; if (rb_firstpart.Checked) s2 = "首次适应算法"; else if (rb_bestpart.Checked) s2 = "最佳适应算法"; else if (rb_cyclepart.Checked) s2 = "循环适应算法"; g2.DrawString(s2, myfont, sbs[3], new Point(30, 150)); g22.DrawImage(b2, 0, 0); //画图2结束 //清空绘图3-------------------------- Graphics g32 = pb_mem3.CreateGraphics(); g32.Clear(Color.White); //画图3 //画黑框 Rectangle r1 = new Rectangle(30, 40, 90, 200); Bitmap b3 = new Bitmap(200, 480); Graphics g3 = Graphics.FromImage(b3); g3.DrawRectangle(penBlack, r1); //g3.DrawString("0MB", myfont, sbs[3], new Point(0, 30)); g3.DrawString("200MB", myfont, sbs[3], new Point(0, 240)); //画内存使用情况 foreach (Nodespace nodespace in ls) { int begin = nodespace.begin; int size = nodespace.size; int taskid = nodespace.taskid; int state = nodespace.status; Rectangle t = new Rectangle(30, begin + 40, 90, size); if (state == 1) { g3.FillRectangle(sbs[0], t); g3.DrawRectangle(penBlack, t); } else { if (rb_part.Checked && pointer == nodespace.taskid) g3.FillRectangle(sbs[1], t); else g3.FillRectangle(sbs[2], t); g3.DrawRectangle(penBlack, t); g3.DrawString("进程" + Convert.ToString(nodespace.taskid) + ":大小" + size + "MB", myfont, sbs[3], t); g3.DrawString(Convert.ToString(begin) + "MB", myfont, sbs[3], new Point(0, begin + 30)); g3.DrawString(Convert.ToString(begin + size + "MB"), myfont, sbs[3], new Point(0, begin + size + 30)); } } g32.DrawImage(b3, 0, 0); //结束画图3 //free 图3------------------------------------------------------------- b3.Dispose(); b3 = null; g3.Dispose(); g3 = null; g32.Dispose(); g32 = null; //free 图2 b2.Dispose(); b2 = null; g2.Dispose(); g2 = null; g22.Dispose(); g22 = null; } #endregion #region 画表格 public void DrawTable() { lv_mem.BeginUpdate();//数据更新,UI暂时挂起,直到EndUpdate绘制控件,可以有效避免闪烁并大大提高加载速度 lv_mem.Items.Clear();//只移除所有的项。 foreach (Nodespace nodespace in ls) { ListViewItem lvi = new ListViewItem(); lvi.Text = nodespace.begin+"MB"; lvi.SubItems.Add(nodespace.begin + nodespace.size + "MB"); lvi.SubItems.Add(nodespace.size + "MB"); lvi.SubItems.Add(nodespace.status == 1 ? "空闲" : "占用"); lvi.SubItems.Add("进程"+nodespace.taskid); lv_mem.Items.Add(lvi); } lv_mem.EndUpdate();//结束数据处理,UI界面一次性绘制。 } #endregion #region 执行确定按钮 private void bt_certain_Click(object sender, EventArgs e) { //确保回收操作执行合法 if (rb_free.Checked && (rb_bestpart.Checked || rb_cyclepart.Checked || rb_firstpart.Checked) && tb_name.Text != "") { int taskid = Convert.ToInt32(tb_name.Text); pointer = taskid; int index = ls.FindIndex(param => param.taskid == taskid); if (index == -1) { MessageBox.Show("没有该进程!,不予执行"); return; } else { tb_size.Text = ""; /*//当free可执行时,使其他按钮无法再变化,直到显示执行完后 rb_free.Enabled = false; rb_part.Enabled = false; rb_firstpart.Enabled = false; rb_cyclepart.Enabled = false; rb_bestpart.Enabled = false;*/ ShowMem1(); FreeMem(taskid, index); ShowMem23(); DrawTable(); MessageBox.Show("内存回收成功!"); /*rb_free.Enabled = true; rb_part.Enabled = true; rb_firstpart.Enabled = true; rb_cyclepart.Enabled = true; rb_bestpart.Enabled = true;*/ } } else if (rb_part.Checked && (rb_bestpart.Checked || rb_cyclepart.Checked || rb_firstpart.Checked) && tb_name.Text != "" && tb_size.Text != "") { int taskid = Convert.ToInt32(tb_name.Text); int index = ls.FindIndex(param => param.taskid == taskid); if (index != -1) { MessageBox.Show("该进程已存在!"); tb_name.Text = ""; return; } int size = Convert.ToInt32(tb_size.Text); pointer = -1;//不在图1中画绿色内存块 ShowMem1(); pointer = taskid;//在图3中画绿色内存块 bool flag = false; if (rb_firstpart.Checked) flag = FirstPartition(taskid, size); else if (rb_bestpart.Checked) flag = BestPartiton(taskid, size); else if (rb_cyclepart.Checked) { flag = CyclyFirstPartition(taskid, size); } if (flag) { ShowMem23(); DrawTable(); } else MessageBox.Show("没有合适的内存空间,内存分配失败"); } } #endregion #region 开始按钮 private void bt_start_Click(object sender, EventArgs e) { ls.Clear(); Nodespace nodespace = new Nodespace(-1, 0, 200, 1); ls.Add(nodespace); Graphics g12 = pb_mem1.CreateGraphics(); g12.Clear(Color.White); Graphics g22 = pb_mem2.CreateGraphics(); g22.Clear(Color.White); Graphics g32 = pb_mem3.CreateGraphics(); g32.Clear(Color.White); Bitmap b1 = new Bitmap(200, 480); Graphics g1 = Graphics.FromImage(b1); Rectangle r1 = new Rectangle(30,40,90,ls[0].size); g1.FillRectangle(sbs[0], r1); g1.DrawRectangle(penBlack, r1); g1.DrawString("0MB", myfont, sbs[3], new Point(0, 30)); g1.DrawString("200MB", myfont, sbs[3], new Point(0, 240)); g12.DrawImage(b1, 0, 0); Bitmap b3 = new Bitmap(200, 480); Graphics g3 = Graphics.FromImage(b3); g3.FillRectangle(sbs[0], r1); g3.DrawRectangle(penBlack, r1); g3.DrawString("0MB", myfont, sbs[3], new Point(0, 30)); g3.DrawString("200MB", myfont, sbs[3], new Point(0, 240)); g32.DrawImage(b3, 0, 0); //free 图1 b1.Dispose(); b1 = null; g1.Dispose(); g1 = null; g12.Dispose(); g12 = null; //free 图3 b3.Dispose(); b3 = null; g3.Dispose(); g3 = null; g32.Dispose(); g32 = null; //画图4------------------------------------------------------------ Bitmap b_example = new Bitmap(600, 50); Graphics gb_emp = Graphics.FromImage(b_example); //红 Rectangle r_emp1 = new Rectangle(10, 0, 60, 20); gb_emp.FillRectangle(sbs[0], r_emp1); gb_emp.DrawRectangle(penBlack, r_emp1); gb_emp.DrawString("空闲区", myfont, sbs[0], new Point(75, 5)); //黄 Rectangle r_emp2 = new Rectangle(130, 0, 60, 20); gb_emp.FillRectangle(sbs[1], r_emp2); gb_emp.DrawRectangle(penBlack, r_emp2); gb_emp.DrawString("申请或释放区", myfont, sbs[1], new Point(190, 5)); //粉 Rectangle r_emp3 = new Rectangle(290, 0, 60, 20); gb_emp.FillRectangle(sbs[2], r_emp3); gb_emp.DrawRectangle(penBlack, r_emp3); gb_emp.DrawString("占用区", myfont, sbs[2], new Point(360, 5)); Graphics gp_emp = pb_example.CreateGraphics(); gp_emp.DrawImage(b_example, 0, 0); b_example.Dispose(); b_example = null; gb_emp.Dispose(); gb_emp = null; gp_emp.Dispose(); gp_emp = null; } #endregion private void MainForm_Load(object sender, EventArgs e) { } //如果重新点击循环算法,开始位置置0 private void rb_cyclepart_CheckedChanged(object sender, EventArgs e) { startIndex = 0; } } public class Nodespace { public int taskid; // 任务号 public int begin; // 开始地址 public int size; // 大小 public int status; // 状态 0代表占用,1代表空闲 public Nodespace(int taskid, int begin, int size, int status) { this.taskid = taskid; this.begin = begin; this.size = size; this.status = status; } } //分配时,空闲区按size大小从小到大排序 public class NodespaceCompare_partition : IComparer { public int Compare(Nodespace x, Nodespace y) { return (x.size.CompareTo(y.size)); } } //回收时,空闲区按开始地址排序 public class NodespaceCompare_free : IComparer { public int Compare(Nodespace x, Nodespace y) { return (x.begin.CompareTo(y.begin)); } } }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3