1
0
mirror of https://github.com/rcore-os/rCore.git synced 2024-11-23 00:16:17 +04:00

Fork (not finished). Not depend on boot_info after remap_kernel.

This commit is contained in:
WangRunji 2018-05-13 21:13:57 +08:00
parent 678d1d2b54
commit 4d6925a562
9 changed files with 122 additions and 33 deletions

View File

@ -24,6 +24,7 @@ once = "0.3.3"
linked_list_allocator = "0.5.0"
redox_syscall = "0.1.37"
xmas-elf = "0.6"
arrayvec = { version = "0.4.7", default-features = false }
[build-dependencies]
cc = "1.0"

View File

@ -26,7 +26,7 @@ pub const MAX_CPU_NUM: usize = 8;
pub const KERNEL_HEAP_OFFSET: usize = KERNEL_OFFSET - PML4_SIZE;
pub const KERNEL_HEAP_PML4: usize = (KERNEL_HEAP_OFFSET & PML4_MASK)/PML4_SIZE;
/// Size of kernel heap
pub const KERNEL_HEAP_SIZE: usize = 1 * 1024 * 1024; // 1 MB
pub const KERNEL_HEAP_SIZE: usize = 2 * 1024 * 1024; // 1 MB
/// Offset to kernel percpu variables
//TODO: Use 64-bit fs offset to enable this pub const KERNEL_PERCPU_OFFSET: usize = KERNEL_HEAP_OFFSET - PML4_SIZE;

View File

@ -33,6 +33,7 @@ extern crate lazy_static;
extern crate bit_field;
extern crate syscall as redox_syscall;
extern crate xmas_elf;
extern crate arrayvec;
#[macro_use] // print!
mod io;
@ -76,7 +77,7 @@ pub extern "C" fn rust_main(multiboot_information_address: usize) -> ! {
// FIXME: 开启SMP后导致switch_to_user中设置rsp无效
// arch::smp::start_other_cores(&acpi, &mut memory_controller);
process::init(&mut memory_controller);
process::init(memory_controller);
unsafe{ arch::interrupt::enable(); }

View File

@ -1,10 +1,11 @@
use memory::{Frame, FrameAllocator, PhysAddr};
use multiboot2::{MemoryAreaIter, MemoryArea};
use arrayvec::ArrayVec;
pub struct AreaFrameAllocator {
next_free_frame: Frame,
current_area: Option<&'static MemoryArea>,
areas: MemoryAreaIter,
current_area: Option<Area>,
areas: ArrayVec<[Area; 4]>,
kernel_start: Frame,
kernel_end: Frame,
multiboot_start: Frame,
@ -62,10 +63,12 @@ impl AreaFrameAllocator {
multiboot_start: PhysAddr, multiboot_end: PhysAddr,
memory_areas: MemoryAreaIter) -> AreaFrameAllocator
{
let areas: ArrayVec<[Area; 4]> = memory_areas.map(|a| Area::from(a)).collect();
let mut allocator = AreaFrameAllocator {
next_free_frame: Frame::of_addr(0),
current_area: None,
areas: memory_areas,
areas,
kernel_start: Frame::of_addr(kernel_start.0 as usize),
kernel_end: Frame::of_addr(kernel_end.0 as usize),
multiboot_start: Frame::of_addr(multiboot_start.0 as usize),
@ -76,10 +79,11 @@ impl AreaFrameAllocator {
}
fn choose_next_area(&mut self) {
self.current_area = self.areas.clone().filter(|area| {
self.current_area = self.areas.iter().filter(|area| {
let address = area.end_address() - 1;
Frame::of_addr(address as usize) >= self.next_free_frame
}).min_by_key(|area| area.start_address());
}).min_by_key(|area| area.start_address())
.map(|area| area.clone());
if let Some(area) = self.current_area {
let start_frame = Frame::of_addr(area.start_address());
@ -89,3 +93,30 @@ impl AreaFrameAllocator {
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct Area {
start: usize,
end: usize,
}
impl Area {
pub fn start_address(&self) -> usize {
self.start
}
pub fn end_address(&self) -> usize {
self.end
}
pub fn size(&self) -> usize {
self.end - self.start
}
}
impl<'a> From<&'a MemoryArea> for Area {
fn from(a: &'a MemoryArea) -> Self {
Area {
start: a.start_address(),
end: a.end_address(),
}
}
}

View File

@ -44,6 +44,14 @@ impl MemoryArea {
name,
}
}
pub unsafe fn as_slice(&self) -> &[u8] {
use core::slice;
slice::from_raw_parts(self.start_addr as *const u8, self.end_addr - self.start_addr)
}
pub unsafe fn as_slice_mut(&self) -> &mut [u8] {
use core::slice;
slice::from_raw_parts_mut(self.start_addr as *mut u8, self.end_addr - self.start_addr)
}
pub fn contains(&self, addr: VirtAddr) -> bool {
addr >= self.start_addr && addr < self.end_addr
}
@ -58,16 +66,17 @@ impl MemoryArea {
/// 内存空间集合,包含若干段连续空间
/// 对应ucore中 `mm_struct`
#[derive(Clone)]
pub struct MemorySet {
areas: Vec<MemoryArea>,
page_table: Option<InactivePageTable>,
// page_table: Option<InactivePageTable>,
}
impl MemorySet {
pub fn new() -> Self {
MemorySet {
areas: Vec::<MemoryArea>::new(),
page_table: None,
// page_table: None,
}
}
/// Used for remap_kernel() where heap alloc is unavailable
@ -76,7 +85,7 @@ impl MemorySet {
let cap = slice.len() / size_of::<MemoryArea>();
MemorySet {
areas: Vec::<MemoryArea>::from_raw_parts(slice.as_ptr() as *mut MemoryArea, 0, cap),
page_table: None,
// page_table: None,
}
}
pub fn find_area(&self, addr: VirtAddr) -> Option<&MemoryArea> {
@ -88,8 +97,8 @@ impl MemorySet {
.is_none(), "memory area overlap");
self.areas.push(area);
}
pub fn map(&mut self, pt: &mut Mapper) {
for area in self.areas.iter_mut() {
pub fn map(&self, pt: &mut Mapper) {
for area in self.areas.iter() {
match area.phys_start_addr {
Some(phys_start) => {
for page in Page::range_of(area.start_addr, area.end_addr) {
@ -105,13 +114,16 @@ impl MemorySet {
}
}
}
pub fn unmap(&mut self, pt: &mut Mapper) {
for area in self.areas.iter_mut() {
pub fn unmap(&self, pt: &mut Mapper) {
for area in self.areas.iter() {
for page in Page::range_of(area.start_addr, area.end_addr) {
pt.unmap(page);
}
}
}
pub fn iter(&self) -> impl Iterator<Item=&MemoryArea> {
self.areas.iter()
}
}
impl Debug for MemorySet {

View File

@ -18,8 +18,6 @@ mod stack_allocator;
mod address;
mod frame;
pub static ACITVE_PAGETABLE: Mutex<ActivePageTable> = Mutex::new(unsafe { ActivePageTable::new() });
pub static FRAME_ALLOCATOR: Mutex<Option<AreaFrameAllocator>> = Mutex::new(None);
pub fn alloc_frame() -> Frame {
@ -31,6 +29,8 @@ pub fn alloc_frame() -> Frame {
pub fn init(boot_info: BootInformation) -> MemoryController {
assert_has_not_been_called!("memory::init must be called only once");
debug!("{:?}", boot_info);
let memory_map_tag = boot_info.memory_map_tag().expect(
"Memory map tag required");
let elf_sections_tag = boot_info.elf_sections_tag().expect(
@ -70,14 +70,12 @@ pub fn init(boot_info: BootInformation) -> MemoryController {
}
}
pub fn remap_the_kernel(boot_info: BootInformation) -> Stack
{
let mut active_table = ACITVE_PAGETABLE.lock();
pub fn remap_the_kernel(boot_info: BootInformation) -> Stack {
let mut active_table = unsafe { ActivePageTable::new() };
let mut memory_set = MemorySet::from(boot_info.elf_sections_tag().unwrap());
use consts::{KERNEL_HEAP_OFFSET, KERNEL_HEAP_SIZE};
memory_set.push(MemoryArea::new_identity(0xb8000, 0xb9000, EntryFlags::WRITABLE, "VGA"));
memory_set.push(MemoryArea::new_identity(boot_info.start_address(), boot_info.end_address(), EntryFlags::PRESENT, "multiboot"));
memory_set.push(MemoryArea::new(KERNEL_HEAP_OFFSET, KERNEL_HEAP_OFFSET + KERNEL_HEAP_SIZE, EntryFlags::WRITABLE, "kernel_heap"));
let mut page_table = InactivePageTable::new(alloc_frame(), &mut active_table);
@ -179,7 +177,7 @@ impl MemoryController {
let flags = EntryFlags::WRITABLE;
self.active_table.map_to(page, frame, flags);
}
pub fn make_page_table(&mut self, set: &mut MemorySet) -> InactivePageTable {
pub fn make_page_table(&mut self, set: &MemorySet) -> InactivePageTable {
let mut page_table = InactivePageTable::new(alloc_frame(), &mut self.active_table);
use consts::{KERNEL_HEAP_PML4, KERNEL_PML4};

View File

@ -37,14 +37,14 @@ extern {
}
pub fn init(mc: &mut MemoryController) {
pub fn init(mut mc: MemoryController) {
PROCESSOR.call_once(|| {Mutex::new({
let mut processor = Processor::new();
let initproc = Process::new_init(mc);
let idleproc = Process::new("idle", idle_thread, mc);
let initproc = Process::new_init(&mut mc);
let idleproc = Process::new("idle", idle_thread, &mut mc);
#[cfg(feature = "link_user_program")]
let forktest = Process::new_user(_binary_user_forktest_start as usize,
_binary_user_forktest_end as usize, mc);
_binary_user_forktest_end as usize, &mut mc);
let mut processor = Processor::new(mc);
processor.add(initproc);
processor.add(idleproc);
processor.add(forktest);
@ -71,6 +71,7 @@ extern fn idle_thread() {
}
}
/// Fork the current process
pub fn fork(tf: &TrapFrame) {
unimplemented!()
PROCESSOR.try().unwrap().lock().fork(tf);
}

View File

@ -1,5 +1,5 @@
use super::*;
use memory::{Stack, InactivePageTable};
use memory::{self, Stack, InactivePageTable};
use xmas_elf::{ElfFile, program::{Flags, ProgramHeader}, header::HeaderPt2};
use core::slice;
use alloc::rc::Rc;
@ -71,7 +71,7 @@ impl Process {
let mut memory_set = MemorySet::from(&elf);
memory_set.push(MemoryArea::new(USER_STACK_OFFSET, USER_STACK_OFFSET + USER_STACK_SIZE,
EntryFlags::WRITABLE | EntryFlags::NO_EXECUTE | EntryFlags::USER_ACCESSIBLE, "user_stack"));
let page_table = mc.make_page_table(&mut memory_set);
let page_table = mc.make_page_table(&memory_set);
debug!("{:#x?}", memory_set);
// Temporary switch to it, in order to copy data
@ -108,9 +108,42 @@ impl Process {
}
/// Fork
pub fn fork(&mut self) -> Self {
pub fn fork(&self, tf: &TrapFrame, mc: &mut MemoryController) -> Self {
assert!(self.is_user);
unimplemented!()
// Clone memory set, make a new page table
let memory_set = self.memory_set.as_ref().unwrap().clone();
let page_table = mc.make_page_table(&memory_set);
// Copy data to temp space
use alloc::Vec;
let datas: Vec<Vec<u8>> = memory_set.iter().map(|area| {
Vec::from(unsafe { area.as_slice() })
}).collect();
// Temporary switch to it, in order to copy data
let page_table = mc.with(page_table, || {
for (area, data) in memory_set.iter().zip(datas.iter()) {
unsafe { area.as_slice_mut() }.copy_from_slice(data.as_slice())
}
});
// Allocate kernel stack and push trap frame
let kstack = mc.alloc_stack(7).unwrap();
let mut tf = tf.clone();
tf.scratch.rax = 1;
let rsp = kstack.push_at_top(tf);
Process {
pid: 0,
name: "fork",
kstack,
memory_set: Some(memory_set),
page_table: Some(page_table),
status: Status::Ready,
rsp,
is_user: true,
}
}
}

View File

@ -1,16 +1,18 @@
use alloc::BTreeMap;
use memory::{ActivePageTable, InactivePageTable};
use super::*;
use core::cell::RefCell;
#[derive(Debug)]
pub struct Processor {
mc: RefCell<MemoryController>,
procs: BTreeMap<Pid, Process>,
current_pid: Pid,
}
impl Processor {
pub fn new() -> Self {
pub fn new(mc: MemoryController) -> Self {
Processor {
mc: RefCell::new(mc),
procs: BTreeMap::<Pid, Process>::new(),
current_pid: 0,
}
@ -73,4 +75,14 @@ impl Processor {
self.current_pid = pid;
debug!("Processor: switch from {} to {}\n rsp: {:#x} -> {:#x}", pid0, pid, rsp0, rsp);
}
pub fn current(&self) -> &Process {
self.procs.get(&self.current_pid).unwrap()
}
/// Fork the current process
pub fn fork(&mut self, tf: &TrapFrame) {
let new = self.current().fork(tf, &mut self.mc.borrow_mut());
self.add(new);
}
}