|
|
|
@ -1,4 +1,4 @@
|
|
|
|
|
//! 系统调用解析执行模块
|
|
|
|
|
//! System call
|
|
|
|
|
|
|
|
|
|
#![allow(unused)]
|
|
|
|
|
|
|
|
|
@ -6,25 +6,45 @@ use arch::interrupt::TrapFrame;
|
|
|
|
|
use process::*;
|
|
|
|
|
use thread;
|
|
|
|
|
use util;
|
|
|
|
|
use simple_filesystem::{INode, file::File};
|
|
|
|
|
use core::{slice, str};
|
|
|
|
|
use alloc::boxed::Box;
|
|
|
|
|
|
|
|
|
|
/// 系统调用入口点
|
|
|
|
|
///
|
|
|
|
|
/// 当发生系统调用中断时,中断服务例程将控制权转移到这里。
|
|
|
|
|
/// System call dispatcher
|
|
|
|
|
pub fn syscall(id: usize, args: [usize; 6], tf: &TrapFrame) -> i32 {
|
|
|
|
|
match id {
|
|
|
|
|
SYS_WRITE => sys_write(args[0], args[1] as *const u8, args[2]),
|
|
|
|
|
SYS_OPEN => sys_open(args[0] as *const u8, args[1]),
|
|
|
|
|
SYS_CLOSE => sys_close(args[0]),
|
|
|
|
|
SYS_WAIT => sys_wait(args[0], args[1] as *mut i32),
|
|
|
|
|
SYS_FORK => sys_fork(tf),
|
|
|
|
|
SYS_KILL => sys_kill(args[0]),
|
|
|
|
|
SYS_EXIT => sys_exit(args[0]),
|
|
|
|
|
SYS_YIELD => sys_yield(),
|
|
|
|
|
SYS_GETPID => sys_getpid(),
|
|
|
|
|
SYS_SLEEP => sys_sleep(args[0]),
|
|
|
|
|
SYS_GETTIME => sys_get_time(),
|
|
|
|
|
SYS_LAB6_SET_PRIORITY => sys_lab6_set_priority(args[0]),
|
|
|
|
|
SYS_PUTC => sys_putc(args[0] as u8 as char),
|
|
|
|
|
// file
|
|
|
|
|
100 => sys_open(args[0] as *const u8, args[1]),
|
|
|
|
|
101 => sys_close(args[0]),
|
|
|
|
|
102 => sys_read(args[0], args[1] as *mut u8, args[2]),
|
|
|
|
|
103 => sys_write(args[0], args[1] as *const u8, args[2]),
|
|
|
|
|
030 => sys_putc(args[0] as u8 as char),
|
|
|
|
|
// 104 => sys_seek(),
|
|
|
|
|
// 110 => sys_fstat(),
|
|
|
|
|
// 111 => sys_fsync(),
|
|
|
|
|
// 121 => sys_getcwd(),
|
|
|
|
|
// 128 => sys_getdirentry(),
|
|
|
|
|
// 128 => sys_dup(),
|
|
|
|
|
|
|
|
|
|
// process
|
|
|
|
|
001 => sys_exit(args[0]),
|
|
|
|
|
002 => sys_fork(tf),
|
|
|
|
|
003 => sys_wait(args[0], args[1] as *mut i32),
|
|
|
|
|
// 004 => sys_exec(),
|
|
|
|
|
// 005 => sys_clone(),
|
|
|
|
|
010 => sys_yield(),
|
|
|
|
|
011 => sys_sleep(args[0]),
|
|
|
|
|
012 => sys_kill(args[0]),
|
|
|
|
|
017 => sys_get_time(),
|
|
|
|
|
018 => sys_getpid(),
|
|
|
|
|
255 => sys_lab6_set_priority(args[0]),
|
|
|
|
|
|
|
|
|
|
// memory
|
|
|
|
|
// 020 => sys_mmap(),
|
|
|
|
|
// 021 => sys_munmap(),
|
|
|
|
|
// 022 => sys_shmem(),
|
|
|
|
|
// 031 => sys_pgdir(),
|
|
|
|
|
|
|
|
|
|
_ => {
|
|
|
|
|
error!("unknown syscall id: {:#x?}, args: {:x?}", id, args);
|
|
|
|
|
::trap::error(tf);
|
|
|
|
@ -32,28 +52,73 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &TrapFrame) -> i32 {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn sys_read(fd: usize, base: *mut u8, len: usize) -> i32 {
|
|
|
|
|
info!("read: fd: {}, base: {:?}, len: {:#x}", fd, base, len);
|
|
|
|
|
let slice = unsafe { slice::from_raw_parts_mut(base, len) };
|
|
|
|
|
match fd {
|
|
|
|
|
0 => unimplemented!(),
|
|
|
|
|
1 | 2 => return -1,
|
|
|
|
|
_ => {
|
|
|
|
|
let mut file = process().files.get_mut(&fd);
|
|
|
|
|
if file.is_none() {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
let file = file.as_mut().unwrap();
|
|
|
|
|
file.read(slice).unwrap();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn sys_write(fd: usize, base: *const u8, len: usize) -> i32 {
|
|
|
|
|
info!("write: fd: {}, base: {:?}, len: {:#x}", fd, base, len);
|
|
|
|
|
use core::slice;
|
|
|
|
|
use core::str;
|
|
|
|
|
let slice = unsafe { slice::from_raw_parts(base, len) };
|
|
|
|
|
print!("{}", str::from_utf8(slice).unwrap());
|
|
|
|
|
match fd {
|
|
|
|
|
0 => return -1,
|
|
|
|
|
1 | 2 => print!("{}", str::from_utf8(slice).unwrap()),
|
|
|
|
|
_ => {
|
|
|
|
|
let mut file = process().files.get_mut(&fd);
|
|
|
|
|
if file.is_none() {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
let file = file.as_mut().unwrap();
|
|
|
|
|
file.write(slice).unwrap();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn sys_open(path: *const u8, flags: usize) -> i32 {
|
|
|
|
|
let path = unsafe { util::from_cstr(path) };
|
|
|
|
|
let flags = VfsFlags::from_ucore_flags(flags);
|
|
|
|
|
info!("open: path: {:?}, flags: {:?}", path, flags);
|
|
|
|
|
match path {
|
|
|
|
|
"stdin:" => 0,
|
|
|
|
|
"stdout:" => 1,
|
|
|
|
|
_ => -1,
|
|
|
|
|
"stdin:" => return 0,
|
|
|
|
|
"stdout:" => return 1,
|
|
|
|
|
"stderr:" => return 2,
|
|
|
|
|
_ => {}
|
|
|
|
|
}
|
|
|
|
|
let inode = ::fs::ROOT_INODE.lookup(path);
|
|
|
|
|
if inode.is_err() {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
let inode = inode.unwrap();
|
|
|
|
|
let files = &mut process().files;
|
|
|
|
|
let fd = (3..).find(|i| !files.contains_key(i)).unwrap();
|
|
|
|
|
let file = File::new(inode, flags.contains(VfsFlags::READABLE), flags.contains(VfsFlags::WRITABLE));
|
|
|
|
|
files.insert(fd, Box::new(file));
|
|
|
|
|
fd as i32
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn sys_close(fd: usize) -> i32 {
|
|
|
|
|
info!("close: fd: {:?}", fd);
|
|
|
|
|
0
|
|
|
|
|
if fd < 3 {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
match process().files.remove(&fd) {
|
|
|
|
|
Some(_) => 0,
|
|
|
|
|
None => -1,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Fork the current process. Return the child's PID.
|
|
|
|
@ -151,29 +216,25 @@ fn sys_putc(c: char) -> i32 {
|
|
|
|
|
0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const SYS_EXIT: usize = 1;
|
|
|
|
|
const SYS_FORK: usize = 2;
|
|
|
|
|
const SYS_WAIT: usize = 3;
|
|
|
|
|
const SYS_EXEC: usize = 4;
|
|
|
|
|
const SYS_CLONE: usize = 5;
|
|
|
|
|
const SYS_YIELD: usize = 10;
|
|
|
|
|
const SYS_SLEEP: usize = 11;
|
|
|
|
|
const SYS_KILL: usize = 12;
|
|
|
|
|
const SYS_GETTIME: usize = 17;
|
|
|
|
|
const SYS_GETPID: usize = 18;
|
|
|
|
|
const SYS_MMAP: usize = 20;
|
|
|
|
|
const SYS_MUNMAP: usize = 21;
|
|
|
|
|
const SYS_SHMEM: usize = 22;
|
|
|
|
|
const SYS_PUTC: usize = 30;
|
|
|
|
|
const SYS_PGDIR: usize = 31;
|
|
|
|
|
const SYS_OPEN: usize = 100;
|
|
|
|
|
const SYS_CLOSE: usize = 101;
|
|
|
|
|
const SYS_READ: usize = 102;
|
|
|
|
|
const SYS_WRITE: usize = 103;
|
|
|
|
|
const SYS_SEEK: usize = 104;
|
|
|
|
|
const SYS_FSTAT: usize = 110;
|
|
|
|
|
const SYS_FSYNC: usize = 111;
|
|
|
|
|
const SYS_GETCWD: usize = 121;
|
|
|
|
|
const SYS_GETDIRENTRY: usize = 128;
|
|
|
|
|
const SYS_DUP: usize = 130;
|
|
|
|
|
const SYS_LAB6_SET_PRIORITY: usize = 255;
|
|
|
|
|
bitflags! {
|
|
|
|
|
struct VfsFlags: usize {
|
|
|
|
|
// WARNING: different from origin uCore
|
|
|
|
|
const READABLE = 1 << 0;
|
|
|
|
|
const WRITABLE = 1 << 1;
|
|
|
|
|
/// create file if it does not exist
|
|
|
|
|
const CREATE = 1 << 2;
|
|
|
|
|
/// error if O_CREAT and the file exists
|
|
|
|
|
const EXCLUSIVE = 1 << 3;
|
|
|
|
|
/// truncate file upon open
|
|
|
|
|
const TRUNCATE = 1 << 4;
|
|
|
|
|
/// append on each write
|
|
|
|
|
const APPEND = 1 << 5;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl VfsFlags {
|
|
|
|
|
fn from_ucore_flags(f: usize) -> Self {
|
|
|
|
|
assert_ne!(f & 0b11, 0b11);
|
|
|
|
|
Self::from_bits_truncate(f + 1)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|