From e27aea47e1ff103336582875689f5d79ddd957f4 Mon Sep 17 00:00:00 2001 From: WangRunji Date: Wed, 7 Nov 2018 13:34:31 +0800 Subject: [PATCH] impl file syscalls, without test --- kernel/Cargo.lock | 2 +- kernel/src/fs.rs | 8 +- kernel/src/process/context.rs | 8 +- kernel/src/syscall.rs | 161 +++++++++++++++++++++++----------- 4 files changed, 123 insertions(+), 56 deletions(-) diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index 439601e..0654983 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -209,7 +209,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "simple-filesystem" version = "0.0.1" -source = "git+https://github.com/wangrunji0408/SimpleFileSystem-Rust?branch=multi-thread#d75aab77d685791d6d919f901cc8ec8f29075ff6" +source = "git+https://github.com/wangrunji0408/SimpleFileSystem-Rust?branch=multi-thread#80d72a9853aa8d64c3dc5f8117fc78a50b6f6ca3" dependencies = [ "bit-vec 0.5.0 (git+https://github.com/AltSysrq/bit-vec.git)", "spin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/kernel/src/fs.rs b/kernel/src/fs.rs index 3a946a5..63ca9e6 100644 --- a/kernel/src/fs.rs +++ b/kernel/src/fs.rs @@ -1,7 +1,7 @@ use simple_filesystem::*; use alloc::{boxed::Box, sync::Arc}; #[cfg(target_arch = "x86_64")] -use arch::driver::ide::IDE; +use arch::driver::ide; use spin::Mutex; // Hard link user program @@ -17,7 +17,7 @@ _user_img_end: "#); lazy_static! { - static ref ROOT_INODE: Arc = { + pub static ref ROOT_INODE: Arc = { #[cfg(target_arch = "riscv32")] let device = { extern { @@ -27,7 +27,7 @@ lazy_static! { Box::new(unsafe { MemBuf::new(_user_img_start, _user_img_end) }) }; #[cfg(target_arch = "x86_64")] - let device = Box::new(IDE::new(1)); + let device = Box::new(ide::IDE::new(1)); let sfs = SimpleFileSystem::open(device).expect("failed to open SFS"); sfs.root_inode() @@ -88,7 +88,7 @@ impl Device for MemBuf { use core::slice; #[cfg(target_arch = "x86_64")] -impl BlockedDevice for IDE { +impl BlockedDevice for ide::IDE { const BLOCK_SIZE_LOG2: u8 = 9; fn read_at(&mut self, block_id: usize, buf: &mut [u8]) -> bool { assert!(buf.len() >= ide::BLOCK_SIZE); diff --git a/kernel/src/process/context.rs b/kernel/src/process/context.rs index 95da842..da29ffb 100644 --- a/kernel/src/process/context.rs +++ b/kernel/src/process/context.rs @@ -3,12 +3,14 @@ use memory::{MemoryArea, MemoryAttr, MemorySet, KernelStack}; use xmas_elf::{ElfFile, header, program::{Flags, ProgramHeader, Type}}; use core::fmt::{Debug, Error, Formatter}; use ucore_process::Context; -use alloc::boxed::Box; +use simple_filesystem::file::File; +use alloc::{boxed::Box, collections::BTreeMap}; pub struct ContextImpl { arch: ArchContext, memory_set: MemorySet, kstack: KernelStack, + pub files: BTreeMap>, } impl Context for ContextImpl { @@ -25,6 +27,7 @@ impl ContextImpl { arch: ArchContext::null(), memory_set: MemorySet::new(), kstack: KernelStack::new(), + files: BTreeMap::default(), }) } @@ -35,6 +38,7 @@ impl ContextImpl { arch: unsafe { ArchContext::new_kernel_thread(entry, arg, kstack.top(), memory_set.token()) }, memory_set, kstack, + files: BTreeMap::default(), }) } @@ -95,6 +99,7 @@ impl ContextImpl { }, memory_set, kstack, + files: BTreeMap::default(), }) } @@ -124,6 +129,7 @@ impl ContextImpl { arch: unsafe { ArchContext::new_fork(tf, kstack.top(), memory_set.token()) }, memory_set, kstack, + files: BTreeMap::default(), }) } } diff --git a/kernel/src/syscall.rs b/kernel/src/syscall.rs index 80037c8..b5b8100 100644 --- a/kernel/src/syscall.rs +++ b/kernel/src/syscall.rs @@ -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) + } +}