huangchunzhen / Tcore

Tcore是我在暑假参与清华陈渝教授带领的summer school时和同来参与研修的东南大学李可然同学决定一起做的在一个基于Rcore衍生项目,终极目标是一起做出一个基于Riscv的Cpu并且开发一个可以移植到该Cpu上完整的操作系统,将操作系统继续钻研下去
13 stars 3 forks source link

Rcore开发期间的Rust #3

Open huangchunzhen opened 5 years ago

huangchunzhen commented 5 years ago

该issue主要记录在Rcore实现上遇到的一些Rust问题,但主要以Rcore的代码实现为基础。在Rcore实现的途中会对 https://github.com/huangchunzhen/Tcore/issues/5 与该issue进行整理:该issue以代码实现与解读为主,https://github.com/huangchunzhen/Tcore/issues/5 以算法分析与优化(如果可能的话)为主。 Rcore参考资料: Rcore_step_by_step : https://github.com/LearningOS/rcore_step_by_step tutorial : https://github.com/rcore-os/rCore/wiki/tutorial

huangchunzhen commented 5 years ago

Lab2:物理内存管理的buddy-allocator代码

#![feature(alloc)]
#![no_std]
#![feature(lang_items)]

extern crate alloc;
use alloc::vec::Vec;
use core::alloc::Layout;

pub struct BuddyAllocator {
    nodes : Vec<i8>,
    level : u8,
}

impl BuddyAllocator {
    pub fn new() -> Self {
        let ret = BuddyAllocator{
            nodes : Vec::new(),
            level : 0,
        };
        ret
    }

    pub fn init(&mut self, level : u8) {
        self.level = level;
        let mut idx = 0;
        for s in 0..level {
            for _t in 0..(1 << s) {
                self.nodes.push(0_i8);
                self.nodes[idx] = ( level - s - 1 ) as i8;
                idx = idx + 1;
            }
        }
    }

    pub fn alloc(&mut self, alloc_size : usize) -> Option<usize> {
        let size = log2_up(alloc_size) as i8;
        let mut location = 0;
        let mut height = self.level - 1;
        let ret;
        while height != 0 {
            if size > self.nodes[location] {
                panic!("memory is not enough ");
            }
            if self.nodes[(location << 1) + 1] >= size {
                location = (location << 1) + 1;
            }else if self.nodes[(location + 1) << 1] >= size{
                location = (location + 1) << 1;
            }else{
                break;
            }
            height = height - 1;
        }
        ret = (location + 1) * (1 << height) - (1 << (self.level - 1));
        self.nodes[location] = -1;
        while location > 0 {    // 回溯,更新父辈节点
            if location & 0x1 > 0 { // 当前节点的下标为奇数
                if self.nodes[location] > self.nodes[location + 1] {    // 当前节点的值大于兄弟节点的值
                    self.nodes[location >> 1] = self.nodes[location];
                }else{ // 兄弟节点的值不小于当前节点的值
                    self.nodes[location >> 1] = self.nodes[location + 1];
                }
                location = location >> 1;
            }else{  //当前节点的下标为偶数
                if self.nodes[location] > self.nodes[location - 1] {
                    self.nodes[(location - 1) >> 1] = self.nodes[location];
                }else{
                    self.nodes[(location - 1) >> 1] = self.nodes[location - 1];
                }
                location = (location - 1) >> 1;
            }
        }
        Some(ret)
    }

    pub fn dealloc(&mut self, address : usize, dealloc_size : usize){
        let size = log2_down(dealloc_size) as i8;
        let mut location = address + (1 << (self.level - 1)) - 1;
        let mut height = 0_i8;
        while size > height {
            height += 1;
            location = if location & 0x1 == 0 {
                (location - 1) >> 1
            }else{
                location >> 1
            };
        }
        self.nodes[location] = size as i8;
        while location > 0 {
            if location & 0x1 > 0 { // 奇数下标
                if self.nodes[location] == self.nodes[location + 1] && self.nodes[location] == height{
                    self.nodes[location >> 1] = self.nodes[location] + 1;
                }else if self.nodes[location] > self.nodes[location >> 1] {
                    self.nodes[location >> 1] = self.nodes[location];
                }
                location = location >> 1;
            }else{ // 偶数下标
                if self.nodes[location] == self.nodes[location - 1] && self.nodes[location] == height{
                    self.nodes[(location - 1) >> 1] = self.nodes[location] + 1;
                }else if self.nodes[location] > self.nodes[(location - 1) >> 1]{
                    self.nodes[(location - 1) >> 1] = self.nodes[location];
                }
                location = (location - 1) >> 1;
            }
            height = height + 1;
        }
    }
}

#[inline(always)]
fn log2_up(x: usize) -> usize {    // 以2为底的对数向上取整的值,主要考虑分配内存时应该向上取整
    assert_ne!(x, 0);
    let mut temp_x = x;
    let mut pos = -1;
    while temp_x != 0 {
        pos += 1;
        temp_x >>= 1;
    }
    if x - (1 << pos) != 0 {
        pos = pos + 1;
    }
    pos as usize
}

#[inline(always)]
pub fn log2_down(x: usize) -> usize {    // 以2为底的对数向下取整的值,释放内存时向下取整
    assert_ne!(x, 0);
    let mut temp_x = x;
    let mut pos = -1;
    while temp_x != 0 {
        pos += 1;
        temp_x >>= 1;
    }
    pos as usize
}

#[lang = "oom"]
fn oom(_: Layout) -> ! {
    panic!("out of memory");
} 
huangchunzhen commented 5 years ago

lab2代码是对于buddy-allocator的一个简单实现,使用的是Rust编程语言。在对buddy-allocator进行阐述之前,我们先对buddy-allocator有个大概了解,wiki上是这么解释的:

The buddy memory allocation technique is a memory allocation algorithm that divides memory into partitions to try to satisfy a memory request as suitably as possible. This system makes use of splitting memory into halves to try to give a best fit. According to Donald Knuth, the buddy system was invented in 1963 by Harry Markowitz, and was first described by Kenneth C. Knowlton (published 1965). The Buddy memory allocation is relatively easy to implement. It supports limited but efficient splitting and coalescing of memory blocks.

注意其中这么几句话: The Buddy memory allocation is relatively easy to implement. It supports limited but efficient splitting and coalescing of memory blocks.

它说的是 limited & efficient,那么它的 limited 和 efficient 又体现在哪儿呢?

首先我们从代码入手来查看buddy-allocator的思路:

huangchunzhen commented 5 years ago

由于准备引入slab allocation算法,但是一直被卡,一是Rust的指针问题,二是感觉没有理解slab allocation,于是决定先放弃代码,沉住气来看看《计算机程序设计艺术(第一卷)》的2.5 动态存储分配和slab allocation https://people.eecs.berkeley.edu/~kubitron/courses/cs194-24-S14/hand-outs/bonwick_slab.pdf 的论文,随后再更新best fitfirst fitlast fit的实现代码 与 buddy-allocatorslab allocation的代码理解和原理解读。

huangchunzhen commented 5 years ago

The slab allocator has three principle aims: