From 606abbe6a1c9888d0d7260fdd9d418f361f249fb Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Sun, 20 Dec 2020 13:52:38 +0800 Subject: [PATCH] Simple filetest passed on qemu/k210. --- easy-fs/build.rs | 6 +++ os/Makefile | 8 ++-- os/src/fs/inode.rs | 71 +++++++++++++++++++++++++++++---- os/src/main.rs | 10 ----- os/src/syscall/fs.rs | 26 +++++++++++- os/src/syscall/mod.rs | 2 + os/src/task/processor.rs | 1 - user/Cargo.toml | 3 +- user/src/bin/filetest_simple.rs | 38 ++++++++++++++++++ user/src/lib.rs | 13 ++++++ user/src/syscall.rs | 5 +++ 11 files changed, 159 insertions(+), 24 deletions(-) create mode 100644 easy-fs/build.rs create mode 100644 user/src/bin/filetest_simple.rs diff --git a/easy-fs/build.rs b/easy-fs/build.rs new file mode 100644 index 00000000..5529b4fe --- /dev/null +++ b/easy-fs/build.rs @@ -0,0 +1,6 @@ +static TARGET_PATH: &str = "../user/target/riscv64gc-unknown-none-elf/release/"; + +fn main() { + println!("cargo:rerun-if-changed=../user/src/"); + println!("cargo:rerun-if-changed={}", TARGET_PATH); +} diff --git a/os/Makefile b/os/Makefile index ee507f84..840de204 100644 --- a/os/Makefile +++ b/os/Makefile @@ -7,6 +7,7 @@ KERNEL_ENTRY_PA := 0x80020000 DISASM_TMP := target/$(TARGET)/$(MODE)/asm FS_IMG := ../user/target/$(TARGET)/$(MODE)/fs.img SDCARD := /dev/sdb +APPS := ../user/src/bin # BOARD BOARD ?= qemu @@ -33,12 +34,13 @@ sdcard: $(FS_IMG) $(KERNEL_BIN): kernel @$(OBJCOPY) $(KERNEL_ELF) --strip-all -O binary $@ -$(FS_IMG): - @echo "hello, world!" +$(FS_IMG): $(APPS) + @cd ../user && make build @cd ../easy-fs && cargo run --release +$(APPS): + kernel: - @cd ../user && make build @cargo build --release --features "board_$(BOARD)" clean: diff --git a/os/src/fs/inode.rs b/os/src/fs/inode.rs index 5b61ea49..172b6cc4 100644 --- a/os/src/fs/inode.rs +++ b/os/src/fs/inode.rs @@ -8,6 +8,9 @@ use lazy_static::*; use bitflags::*; use alloc::vec::Vec; use spin::Mutex; +use super::File; +use crate::mm::UserBuffer; +use core::any::Any; pub struct OSInode { readable: bool, @@ -92,13 +95,67 @@ impl OpenFlags { pub fn open_file(name: &str, flags: OpenFlags) -> Option> { let (readable, writable) = flags.read_write(); - // TODO: do not support CREATE or TRUNC flags now - ROOT_INODE.find(name) - .map(|inode| { - Arc::new(OSInode::new( + if flags.contains(OpenFlags::CREATE) { + if let Some(inode) = ROOT_INODE.find(name) { + // clear size + inode.clear(); + Some(Arc::new(OSInode::new( readable, writable, - inode - )) - }) + inode, + ))) + } else { + // create file + ROOT_INODE.create(name) + .map(|inode| { + Arc::new(OSInode::new( + readable, + writable, + inode, + )) + }) + } + } else { + ROOT_INODE.find(name) + .map(|inode| { + if flags.contains(OpenFlags::TRUNC) { + inode.clear(); + } + Arc::new(OSInode::new( + readable, + writable, + inode + )) + }) + } } + +impl File for OSInode { + fn readable(&self) -> bool { self.readable } + fn writable(&self) -> bool { self.writable } + fn read(&self, mut buf: UserBuffer) -> usize { + let mut inner = self.inner.lock(); + let mut total_read_size = 0usize; + for slice in buf.buffers.iter_mut() { + let read_size = inner.inode.read_at(inner.offset, *slice); + if read_size == 0 { + break; + } + inner.offset += read_size; + total_read_size += read_size; + } + total_read_size + } + fn write(&self, buf: UserBuffer) -> usize { + let mut inner = self.inner.lock(); + let mut total_write_size = 0usize; + for slice in buf.buffers.iter() { + let write_size = inner.inode.write_at(inner.offset, *slice); + assert_eq!(write_size, slice.len()); + inner.offset += write_size; + total_write_size += write_size; + } + total_write_size + } + fn as_any_ref(&self) -> &dyn Any { self } +} \ No newline at end of file diff --git a/os/src/main.rs b/os/src/main.rs index 464657b0..e9a34bb8 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -46,17 +46,7 @@ pub fn rust_main() -> ! { trap::enable_timer_interrupt(); timer::set_next_trigger(); fs::list_apps(); - //println!("after listing apps"); task::add_initproc(); - /* - println!("after adding initproc!"); - println!("list apps again!"); - fs::list_apps(); - println!("test user_shell now!"); - let user_shell = fs::open_file("user_shell", fs::OpenFlags::RDONLY).unwrap(); - println!("user_shell size = {}", user_shell.read_all().len()); - println!("before running tasks!"); - */ task::run_tasks(); panic!("Unreachable in rust_main!"); } \ No newline at end of file diff --git a/os/src/syscall/fs.rs b/os/src/syscall/fs.rs index cdaa3449..577e4a0a 100644 --- a/os/src/syscall/fs.rs +++ b/os/src/syscall/fs.rs @@ -1,6 +1,11 @@ -use crate::mm::{UserBuffer, translated_byte_buffer, translated_refmut}; +use crate::mm::{ + UserBuffer, + translated_byte_buffer, + translated_refmut, + translated_str, +}; use crate::task::{current_user_token, current_task}; -use crate::fs::{make_pipe}; +use crate::fs::{make_pipe, OpenFlags, open_file}; pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize { let token = current_user_token(); @@ -46,6 +51,23 @@ pub fn sys_read(fd: usize, buf: *const u8, len: usize) -> isize { } } +pub fn sys_open(path: *const u8, flags: u32) -> isize { + let task = current_task().unwrap(); + let token = current_user_token(); + let path = translated_str(token, path); + if let Some(inode) = open_file( + path.as_str(), + OpenFlags::from_bits(flags).unwrap() + ) { + let mut inner = task.acquire_inner_lock(); + let fd = inner.alloc_fd(); + inner.fd_table[fd] = Some(inode); + fd as isize + } else { + -1 + } +} + pub fn sys_close(fd: usize) -> isize { let task = current_task().unwrap(); let mut inner = task.acquire_inner_lock(); diff --git a/os/src/syscall/mod.rs b/os/src/syscall/mod.rs index 1699e8ca..f4a67538 100644 --- a/os/src/syscall/mod.rs +++ b/os/src/syscall/mod.rs @@ -1,3 +1,4 @@ +const SYSCALL_OPEN: usize = 56; const SYSCALL_CLOSE: usize = 57; const SYSCALL_PIPE: usize = 59; const SYSCALL_READ: usize = 63; @@ -18,6 +19,7 @@ use process::*; pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { match syscall_id { + SYSCALL_OPEN => sys_open(args[0] as *const u8, args[1] as u32), SYSCALL_CLOSE => sys_close(args[0]), SYSCALL_PIPE => sys_pipe(args[0] as *mut usize), SYSCALL_READ => sys_read(args[0], args[1] as *const u8, args[2]), diff --git a/os/src/task/processor.rs b/os/src/task/processor.rs index c53ea507..677d8792 100644 --- a/os/src/task/processor.rs +++ b/os/src/task/processor.rs @@ -61,7 +61,6 @@ lazy_static! { } pub fn run_tasks() { - println!("into Processor::run_tasks!"); PROCESSOR.run(); } diff --git a/user/Cargo.toml b/user/Cargo.toml index aa6e20fe..d50a0ba0 100644 --- a/user/Cargo.toml +++ b/user/Cargo.toml @@ -7,4 +7,5 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -buddy_system_allocator = "0.6" \ No newline at end of file +buddy_system_allocator = "0.6" +bitflags = "1.2.1" \ No newline at end of file diff --git a/user/src/bin/filetest_simple.rs b/user/src/bin/filetest_simple.rs new file mode 100644 index 00000000..60fda6aa --- /dev/null +++ b/user/src/bin/filetest_simple.rs @@ -0,0 +1,38 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; + +use user_lib::{ + open, + close, + read, + write, + OpenFlags, +}; + +#[no_mangle] +pub fn main() -> i32 { + let test_str = "Hello, world!"; + let filea = "filea\0"; + let fd = open(filea, OpenFlags::CREATE | OpenFlags::WRONLY); + assert!(fd > 0); + let fd = fd as usize; + write(fd, test_str.as_bytes()); + close(fd); + + let fd = open(filea, OpenFlags::RDONLY); + assert!(fd > 0); + let fd = fd as usize; + let mut buffer = [0u8; 100]; + let read_len = read(fd, &mut buffer) as usize; + close(fd); + + assert_eq!( + test_str, + core::str::from_utf8(&buffer[..read_len]).unwrap(), + ); + println!("file_test passed!"); + 0 +} \ No newline at end of file diff --git a/user/src/lib.rs b/user/src/lib.rs index 32482859..244baaea 100644 --- a/user/src/lib.rs +++ b/user/src/lib.rs @@ -10,6 +10,8 @@ mod syscall; mod lang_items; extern crate alloc; +#[macro_use] +extern crate bitflags; use syscall::*; use buddy_system_allocator::LockedHeap; @@ -42,6 +44,17 @@ fn main() -> i32 { panic!("Cannot find main!"); } +bitflags! { + pub struct OpenFlags: u32 { + const RDONLY = 0; + const WRONLY = 1 << 0; + const RDWR = 1 << 1; + const CREATE = 1 << 9; + const TRUNC = 1 << 10; + } +} + +pub fn open(path: &str, flags: OpenFlags) -> isize { sys_open(path, flags.bits) } pub fn close(fd: usize) -> isize { sys_close(fd) } pub fn pipe(pipe_fd: &mut [usize]) -> isize { sys_pipe(pipe_fd) } pub fn read(fd: usize, buf: &mut [u8]) -> isize { sys_read(fd, buf) } diff --git a/user/src/syscall.rs b/user/src/syscall.rs index 76683649..0130e127 100644 --- a/user/src/syscall.rs +++ b/user/src/syscall.rs @@ -1,3 +1,4 @@ +const SYSCALL_OPEN: usize = 56; const SYSCALL_CLOSE: usize = 57; const SYSCALL_PIPE: usize = 59; const SYSCALL_READ: usize = 63; @@ -23,6 +24,10 @@ fn syscall(id: usize, args: [usize; 3]) -> isize { ret } +pub fn sys_open(path: &str, flags: u32) -> isize { + syscall(SYSCALL_OPEN, [path.as_ptr() as usize, flags as usize, 0]) +} + pub fn sys_close(fd: usize) -> isize { syscall(SYSCALL_CLOSE, [fd, 0, 0]) }