impl sys_exec

master
WangRunji 6 years ago
parent f97e8458b8
commit 44bf3fb07a

@ -180,4 +180,9 @@ impl Context {
},
}.push_at(kstack_top)
}
/// Called at a new user context
/// To get the init TrapFrame in sys_exec
pub unsafe fn get_init_tf(&self) -> TrapFrame {
(*(self.0 as *const InitStack)).tf.clone()
}
}

@ -183,4 +183,9 @@ impl Context {
},
}.push_at(kstack_top)
}
/// Called at a new user context
/// To get the init TrapFrame in sys_exec
pub unsafe fn get_init_tf(&self) -> TrapFrame {
(*(self.0 as *const InitStack)).tf.clone()
}
}

@ -40,12 +40,9 @@ pub fn shell() {
let files = ROOT_INODE.list().unwrap();
println!("Available programs: {:?}", files);
// Avoid stack overflow in release mode
// Equal to: `buf = Box::new([0; 64 << 12])`
use alloc::alloc::{alloc, dealloc, Layout};
const BUF_SIZE: usize = 0x40000;
let layout = Layout::from_size_align(BUF_SIZE, 0x1000).unwrap();
let buf = unsafe{ slice::from_raw_parts_mut(alloc(layout), BUF_SIZE) };
let mut buf = Vec::with_capacity(BUF_SIZE);
unsafe { buf.set_len(BUF_SIZE); }
loop {
print!(">> ");
use console::get_line;
@ -57,14 +54,13 @@ pub fn shell() {
if let Ok(file) = ROOT_INODE.lookup(name) {
use process::*;
let len = file.read_at(0, &mut *buf).unwrap();
let pid = processor().manager().add(ContextImpl::new_user(&buf[..len], cmd.as_str()));
let pid = processor().manager().add(ContextImpl::new_user(&buf[..len], cmd.split(' ')));
processor().manager().wait(thread::current().id(), pid);
processor().yield_now();
} else {
println!("Program not exist");
}
}
unsafe { dealloc(buf.as_mut_ptr(), layout) };
}
struct MemBuf(&'static [u8]);
@ -89,6 +85,7 @@ impl Device for MemBuf {
}
use core::slice;
use alloc::vec::Vec;
#[cfg(target_arch = "x86_64")]
impl BlockedDevice for ide::IDE {

@ -7,10 +7,11 @@ use simple_filesystem::file::File;
use alloc::{boxed::Box, collections::BTreeMap, vec::Vec, sync::Arc, string::String};
use spin::Mutex;
// TODO: avoid pub
pub struct ContextImpl {
arch: ArchContext,
memory_set: MemorySet,
kstack: KernelStack,
pub arch: ArchContext,
pub memory_set: MemorySet,
pub kstack: KernelStack,
pub files: BTreeMap<usize, Arc<Mutex<File>>>,
pub cwd: String,
}
@ -47,7 +48,9 @@ impl ContextImpl {
}
/// Make a new user thread from ELF data
pub fn new_user(data: &[u8], cmd: &str) -> Box<Context> {
pub fn new_user<'a, Iter>(data: &[u8], args: Iter) -> Box<ContextImpl>
where Iter: Iterator<Item=&'a str>
{
// Parse elf
let elf = ElfFile::new(data).expect("failed to read elf");
let is32 = match elf.header.pt2 {
@ -84,7 +87,7 @@ impl ContextImpl {
let target = unsafe { slice::from_raw_parts_mut(virt_addr as *mut u8, file_size) };
target.copy_from_slice(&data[offset..offset + file_size]);
}
ustack_top = push_args_at_stack(cmd, ustack_top);
ustack_top = push_args_at_stack(args, ustack_top);
});
}
@ -150,11 +153,13 @@ unsafe fn push_slice<T: Copy>(mut sp: usize, vs: &[T]) -> usize {
sp
}
unsafe fn push_args_at_stack(cmd: &str, stack_top: usize) -> usize {
unsafe fn push_args_at_stack<'a, Iter>(args: Iter, stack_top: usize) -> usize
where Iter: Iterator<Item=&'a str>
{
use core::{ptr, slice};
let mut sp = stack_top;
let mut argv = Vec::new();
for arg in cmd.split(' ') {
for arg in args {
sp = push_slice(sp, &[0u8]);
sp = push_slice(sp, arg.as_bytes());
argv.push(sp);

@ -8,9 +8,11 @@ use simple_filesystem::{INode, file::File, FileInfo, FileType};
use core::{slice, str};
use alloc::sync::Arc;
use spin::Mutex;
use alloc::vec::Vec;
use alloc::string::String;
/// System call dispatcher
pub fn syscall(id: usize, args: [usize; 6], tf: &TrapFrame) -> i32 {
pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> i32 {
let ret = match id {
// file
100 => sys_open(args[0] as *const u8, args[1]),
@ -29,7 +31,7 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &TrapFrame) -> i32 {
001 => sys_exit(args[0] as i32),
002 => sys_fork(tf),
003 => sys_wait(args[0], args[1] as *mut i32),
// 004 => sys_exec(),
004 => sys_exec(args[0] as *const u8, args[1] as usize, args[2] as *const *const u8, tf),
// 005 => sys_clone(),
010 => sys_yield(),
011 => sys_sleep(args[0]),
@ -183,6 +185,42 @@ fn sys_wait(pid: usize, code: *mut i32) -> SysResult {
}
}
fn sys_exec(name: *const u8, argc: usize, argv: *const *const u8, tf: &mut TrapFrame) -> SysResult {
// TODO: check ptr
let name = if name.is_null() { "" } else { unsafe { util::from_cstr(name) } };
info!("exec: {:?}, argc: {}, argv: {:?}", name, argc, argv);
// Copy args to kernel
let args: Vec<String> = unsafe {
slice::from_raw_parts(argv, argc).iter()
.map(|&arg| String::from(util::from_cstr(arg)))
.collect()
};
// Read program file
let path = args[0].as_str();
let inode = ::fs::ROOT_INODE.lookup(path)?;
let size = inode.info()?.size;
let mut buf = Vec::with_capacity(size);
unsafe { buf.set_len(size); }
inode.read_at(0, buf.as_mut_slice())?;
// Make new Context
let iter = args.iter().map(|s| s.as_str());
let mut context = ContextImpl::new_user(buf.as_slice(), iter);
// Activate new page table
unsafe { context.memory_set.activate(); }
// Modify the TrapFrame
*tf = unsafe { context.arch.get_init_tf() };
// Swap Context but keep KStack
::core::mem::swap(&mut process().kstack, &mut context.kstack);
::core::mem::swap(process(), &mut *context);
Ok(0)
}
fn sys_yield() -> SysResult {
thread::yield_now();
Ok(0)

Loading…
Cancel
Save