操作系统课程设计
要求
Linux中内存分配的伙伴堆算法模拟。
(1)模拟内存实始情况。
(2)实现Buddy heap算法。
(3)通过键盘输入随机产生的申请和释放操作。
(4)每次申请或释放都显示实时的内存分配的对比图。
实现结果:





伙伴算法:
Linux把空闲的页面按照页块大小分组进行管理。用数组管理各个空闲页块组。当进程提出存储请求时。系统按照Buddy算法。根据请求的 页面数在free_area口对应的空闲页块组中搜索。linux并不是按 照要求的页块的数目去进行分配.而是将大于、等于这个数目的 最小2n个页块分配出去。比如,要求3个页块。就分配2-2=4块;要求16个页块,就分配24=16块.如此等等。因此,系统总是按 照进程所需连续存储块的申请数量。到空闲区队列free 中 能够满足要求的最小空闲区队列里查找。当队列不空时,就把第一个空闲区分配出去。如果该队列为空.那么就继续查找下面的队列(其空闲区的尺寸为上一个队列的2倍)。当它里面有空闲区时,就把该空闲区一分为二:一个分配出去给进程使用;余下的一半.排到它上面的空闲区队列中去。
在内存页面释放时。系统将做为空闲页面看待。然后检查是否存在与这些页面相邻的其它空闲页块,若存在,则合为一 个连续的空闲区按Buddy算法重新分组。
利用JavaScript的对象数据类型和数组来存储相应的内容。
// 空闲块
let free_area = [
{
index: 0,
size: 1024
}
]
// 当前内存使用状况
let ram = [
{
state: false,
size: 1024
}
]
// 剩余空间总和
let free_ram = 1024;
其中free_area表示空闲块数组,数组中的每一个对象表示空闲块信息,index对应当前内存ram数组中空闲块的分块的下标,size表示该空闲块大小。
其中ram表示内存使用状态数组,数组中的每一个对象表示分块,state表示该块是否被使用,state为true表示已使用,反之为未使用。
其中free_ram表示当前未使用内存的大小。
后端到前端的渲染均依靠维护这三个变量。
主要算法代码
let free_area = [
{
index: 0,
size: 1024
}
]
// 当前内存使用状况
let ram = [
{
state: false,
size: 1024
}
]
// 剩余空间总和
let free_ram = 1024;
// 快速幂
var pow = function (x, n) {
let ans = 1;
for (let i = 0; i < n; i++) {
ans *= x;
}
return ans;
}
// console.log(pow(2, 10))
// 找到申请内存大小的二次幂
var findlistnum = function (size) {
for (var i = 0; i <= 10; i++) {
if (size > pow(2, i) && size < pow(2, i + 1)) {
return i + 1;
} else if (size == pow(2, i)) {
// console.log(i)
return i;
}
}
return false;
}
// 删除指定下标的数组元素并返回新数组
var deleteArrElement = function (index, arr) {
let newarr = {
deleteele: arr[index],
arr: arr
}
for (let i = index; i < arr.length; i++) {
arr[i] = arr[i + 1];
}
arr.length--;
newarr.arr = arr;
return newarr;
}
// 查找数组里面某对象的值是否是要找的值
var indexOfArrObj = function (value, arr) {
for (let i = 0; i < arr.length; i++) {
if (arr[i].size === value) {
return i;
}
}
return -1;
}
// 分配内存
// 参数为二次幂i,返回值为新的内存状态,空闲块状态,空闲内存大小;
var allocation = function (powi) {
// if(powi)
console.log(powi)
if (powi < 6) {
powi = 6;
}
let nowstate = {
ram: [],
free_area: [],
free_ram: 0
}
let blocksize = pow(2, powi)
// console.log(free_area)
if (free_area.length == 0) {
// 改成返回错误代码
return false;
} else if (free_area[0].size == 1024) {
let ramsize = 1024;
ram.pop()
free_area.pop()
for (let i = 10 - powi; i > 0; i--) {
ramsize = ramsize / 2;
let obj = {
index: i,
size: ramsize
}
// console.log(ramsize)
free_area.unshift(obj);
let tempusedobj = {
state: false,
size: ramsize
}
ram.unshift(tempusedobj)
}
let usedpbj = {
state: true,
size: ramsize
}
ram.unshift(usedpbj)
free_ram -= ramsize;
nowstate.ram = ram;
nowstate.free_area = free_area;
nowstate.free_ram = free_ram;
// console.log('allocation ans 1' + JSON.stringify(nowstate))
return nowstate;
} else {
if (indexOfArrObj(blocksize, free_area) != -1) {
let i = indexOfArrObj(blocksize, free_area);
// console.log(i)
// free_area.index不变
let newfreeare = deleteArrElement(i, free_area);
free_area = newfreeare.arr;
// console.log(free_area)
let ramindex = newfreeare.deleteele.index
ram[ramindex].state = true;
free_ram -= newfreeare.deleteele.size;
nowstate.ram = ram;
nowstate.free_area = free_area;
nowstate.free_ram = free_ram;
// console.log('allocation ans 2' + JSON.stringify(nowstate))
return nowstate;
} else {
let findupsize = blocksize;
for (let i = 0; pow(2, i) * blocksize <= free_area[free_area.length - 1].size; i++) {
findupsize *= 2;
// console.log(findupsize)
if (indexOfArrObj(findupsize, free_area) != -1) {
let nowindex = indexOfArrObj(findupsize, free_area);
console.log(nowindex)//0
let ramindex = free_area[nowindex].index;//4
//5
// let sliceindex=ram.length-1-ramindex;//0
// ram.pop();
ram.splice(ramindex, 1)
let times = 0;
console.log(free_area[nowindex])
for (let k = nowindex; free_area[nowindex].size > blocksize; k++) {
times++;
free_area[nowindex].size /= 2;
var obj = { ...free_area[nowindex] }
let usedobj = {
state: false,
size: free_area[nowindex].size
}
free_area.unshift(obj)
console.log(usedobj)
ram.splice(ramindex, 0, usedobj)
}
free_area.splice(0, 1);
let tempobj = {
state: true,
size: free_area[nowindex].size
}
ram.splice(ramindex, 0, tempobj)
// console.log(ramindex)
// ram[ramindex].state = true;
console.log(times)
if (times < 2) {
// console.log(222)
for (let k = nowindex; k < free_area.length; k++) {
free_area[k].index++;
}
} else if (times >= 2) {
// console.log(111)
let freenowindex = free_area[nowindex].index;
for (let k = nowindex; k < free_area.length; k++) {
if (free_area[k].index == freenowindex) {
free_area[k].index = freenowindex + (k - nowindex) + 1;
} else {
free_area[k].index += times;
}
}
}
console.log(free_area)
free_ram -= free_area[nowindex].size;
nowstate.ram = ram;
nowstate.free_area = free_area;
nowstate.free_ram = free_ram;
return nowstate;
}
}
return false;
}
}
}
// 找寻对应的空闲块,如果找到并分配成功返回true;分配失败返回false;
// 参数:申请内存大小
var findFreeBlock = function (size) {
let blockpow = findlistnum(size);
console.log(blockpow)
if (blockpow === false) {
return false;
}
let newstate = $.parseJSON(JSON.stringify(allocation(blockpow)));
// console.log(newstate)
console.log(newstate)
if (newstate == false) {
// console.log('findFreeBlock ans 1')
return false;
}
else {
// console.log(newstate.ram)
ram = newstate.ram;
free_area = newstate.free_area;
free_ram = newstate.free_ram;
// console.log('findFreeBlock ans 2')
return true;
}
}
// 渲染内存界面;
var renderAllocation = function () {
if (free_ram == 1024) {
ram = [{
size: 1024,
state: false
}]
free_area = [{
index: 0,
size: 1024
}]
}
let sum = 1024
// console.log(bcg.innerHTML)
let html = ''
for (let i = 0; i < ram.length; i++) {
if (ram[i].state == true) {
let width = ram[i].size / sum * 100 + '%';
var useddiv = `<div class="used block ` + `kb` + ram[i].size + `" style="width:` + width + ` ">` + ram[i].size + `KB</div>`
html += useddiv
} else {
let freewidth = ram[i].size / sum * 100 + '%';
var freediv = `<div class="free block" style="width: ` + freewidth + `">` + ram[i].size + `KB` + `</div>`;
html += freediv;
}
}
bcg.innerHTML = html;
// $('.bcg').append(useddiv);
// console.log('renderAllocation ans 1')
}
// 格式化时间
var formatDateTime = function (date) {
// var y = date.getFullYear();
// var m = date.getMonth() + 1;
// m = m < 10 ? ('0' + m) : m;
// var d = date.getDate();
// d = d < 10 ? ('0' + d) : d;
var h = date.getHours();
h = h < 10 ? ('0' + h) : h;
var minute = date.getMinutes();
minute = minute < 10 ? ('0' + minute) : minute;
var second = date.getSeconds();
second = second < 10 ? ('0' + second) : second;
return h + ':' + minute + ':' + second;
};
//申请内存 参数:申请内存大小
var applicationram = function (size) {
let isAllocationOk = findFreeBlock(size);
// console.log(isAllocationOk)
if (!isAllocationOk) {
// console.log('applicationram ans 1')
window.alert('分配失败');
let messagewrap = document.createElement('div');
let messagediv = document.createElement('span');
messagewrap.classList.add('message-wrap');
messagediv.classList.add('message-text');
messagediv.classList.add('fail');
messagediv.classList.add('applicationtext')
let date = new Date();
var datestr = formatDateTime(date);
messagediv.innerHTML = datestr + `分配内存` + size + `KB 失败!`;
messagewrap.appendChild(messagediv);
let leftwrap = document.getElementsByClassName('left-wrap')[0];
leftwrap.appendChild(messagewrap);
setTimeout(function (param) {
messagewrap.classList.add('active')
}, 1);
setTimeout(function () {
messagewrap.classList.add('disappear');
}, 5000);
setTimeout(function(){
messagewrap.style.display='none'
},10000);
renderAllocation()
} else {
// console.log('applicationram ans 2')
let messagewrap = document.createElement('div');
let messagediv = document.createElement('span');
messagewrap.classList.add('message-wrap');
messagediv.classList.add('message-text');
messagediv.classList.add('applicationtext')
let date = new Date();
var datestr = formatDateTime(date);
messagediv.innerHTML = datestr + ` 成功分配内存` + size + `KB !`;
messagewrap.appendChild(messagediv);
let leftwrap = document.getElementsByClassName('left-wrap')[0];
leftwrap.appendChild(messagewrap);
setTimeout(function (param) {
messagewrap.classList.add('active')
}, 1);
setTimeout(function () {
messagewrap.classList.add('disappear');
}, 5000);
setTimeout(function(){
messagewrap.style.display='none'
},10000);
renderAllocation()
}
}
//确定分配内存
var buddyheap = function (state) {
if (state == true) {
let applicationsize = document.getElementsByClassName('input')[0].value;
// 申请内存
applicationram(applicationsize)
}
}
// applicationram(70)
applicationbtn.addEventListener('click', function () {
state = true;
// console.log(state)
buddyheap(state);
})
// 给已申请成功的内存块加监听事件
var usedramaddevent = function () {
return new Promise(function (resolve, reject) {
for (let i = 0; i < blockram.length; i++) {
let index = i;
blockram[i].addEventListener('click', function () {
console.log(index)
var that = this
if (ram[index].state == true) {
if (confirm('release this block?')) {
resolve(index)
} else {
resolve(false)
}
}
})
}
});
}
// 释放内存 参数:释放内存大小,释放内存块在内存中的下标
var releasram = function (size, index) {
// console.log(ram)
let flag = true;
let k = 0;
let obj = {
index: index,
size: size
}
free_area.unshift(obj)
free_area.sort(function (a, b) {
return a.index - b.index
})
console.log(free_area)
if (free_area.length == 1) {
let ramindex = free_area[k].index;
ram[ramindex].state=false;
console.log(ramindex)
} else {
while (flag == true) {
console.log(size)
if (k == 0) {
flag = false;
}
// 当从头到尾没有伙伴内存的时候,flag=false
if (k >= free_area.length - 1) {
k = (k % free_area.length) - 1;
}
if ((free_area[k].index - free_area[k + 1].index == -1) && (free_area[k].size == free_area[k + 1].size)) {
console.log(444)
let ramindex = free_area[k].index;
ram[ramindex].size *= 2;
ram[ramindex].state = false;
ram.splice(ramindex + 1, 1);
free_area[k].size *= 2;
free_area.splice(k + 1, 1);
for (let i = k + 1; i < free_area.length; i++) {
free_area[i].index--;
}
flag = false;
} else {
flag = true;
k++;
}
if ((k == free_area.length - 1 && flag == true) || free_area.length == 1) {
console.log(999)
flag=false;
}else{
flag=true;
}
}
}
console.log(free_area)
let s = 0;
for (let i = 0; i < free_area.length; i++) {
s += free_area[i].size;
}
free_ram = s;
// console.log(ram)
}
操作系统课程设计中,使用JavaScript模拟Linux内存分配的伙伴(Buddy)算法。通过键盘输入进行内存申请和释放操作,并实时显示内存分配对比图。算法基于Linux的空闲页块管理,分配时寻找最小的2^n个页块,释放时合并相邻空闲块。使用JavaScript对象和数组数据结构存储内存状态,维护free_area、ram和free_ram三个变量来同步前端和后端的内存信息。

378

被折叠的 条评论
为什么被折叠?



