JavaScript实现linux内存分配的buddy算法

操作系统课程设计中,使用JavaScript模拟Linux内存分配的伙伴(Buddy)算法。通过键盘输入进行内存申请和释放操作,并实时显示内存分配对比图。算法基于Linux的空闲页块管理,分配时寻找最小的2^n个页块,释放时合并相邻空闲块。使用JavaScript对象和数组数据结构存储内存状态,维护free_area、ram和free_ram三个变量来同步前端和后端的内存信息。

操作系统课程设计

要求

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)
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值