diff --git a/.gitignore b/.gitignore index 74b654547bb2e2e556c0f5178b2ce84486503e86..ec0d4718f5d0f1731c09f119ffb761a6b0441345 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ .idea/* os/target/* os/.idea/* +os/Cargo.lock os/src/link_app.S os/Cargo.lock user/target/* diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..bbc25b5319f5ef5bdca5544287915fb27f47b79f --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,11 @@ +default: + image: wangrunji0408/rcore-lab + +stages: + - test + +test-code-job: + stage: test + script: + - git clone https://gitlab-ci-token:i9tQiwpeUjAtG9Unrx23@git.tsinghua.edu.cn/os-21/rcore_tutorial_tests.git + - cd rcore_tutorial_tests && make test CHAPTER=`echo $CI_COMMIT_REF_NAME | grep -oP 'ch\K[0-9]'` \ No newline at end of file diff --git a/bootloader/rustsbi-k210.bin b/bootloader/rustsbi-k210.bin index e696137ab183ea5129e14e86ba980af53ae025d2..58d1c1a7aab97a8253864fa22811a0c8334cb60d 100755 Binary files a/bootloader/rustsbi-k210.bin and b/bootloader/rustsbi-k210.bin differ diff --git a/bootloader/rustsbi-qemu.bin b/bootloader/rustsbi-qemu.bin index 5ccab433b2cac6c11e47ae827904839c4275dfa7..f293ced75934d33cb2585f729b62d019c954456f 100755 Binary files a/bootloader/rustsbi-qemu.bin and b/bootloader/rustsbi-qemu.bin differ diff --git a/easy-fs-fuse/src/main.rs b/easy-fs-fuse/src/main.rs index 498b61ec843d5c6d14bdf6063f36b775fe1e52c7..0ae7975e85884f967b4b35bbb57e9ed3abeb36a8 100644 --- a/easy-fs-fuse/src/main.rs +++ b/easy-fs-fuse/src/main.rs @@ -66,7 +66,7 @@ fn easy_fs_pack() -> std::io::Result<()> { 1, ); let root_inode = Arc::new(EasyFileSystem::root_inode(&efs)); - let apps: Vec<_> = read_dir(src_path) + let mut apps: Vec<_> = read_dir(src_path) .unwrap() .into_iter() .map(|dir_entry| { @@ -75,8 +75,11 @@ fn easy_fs_pack() -> std::io::Result<()> { name_with_ext }) .collect(); + apps.retain(|x| x!=""); + println!("efs...apps number = {}",apps.len()); for app in apps { // load app data from host file system + println!("[efs] loading app : {}{}",target_path, app); let mut host_file = File::open(format!("{}{}", target_path, app)).unwrap(); let mut all_data: Vec<u8> = Vec::new(); host_file.read_to_end(&mut all_data).unwrap(); diff --git a/easy-fs/src/block_cache.rs b/easy-fs/src/block_cache.rs index 572658122a66707306bc7430ba11f2fa77f42bee..fbc70ecba43d5ed28bc381c874b716c028197796 100644 --- a/easy-fs/src/block_cache.rs +++ b/easy-fs/src/block_cache.rs @@ -14,6 +14,7 @@ pub struct BlockCache { modified: bool, } +//一å—BlockCache对应的是一å—Blockçš„ç¼“å˜ impl BlockCache { /// Load a new BlockCache from disk. pub fn new( @@ -34,6 +35,8 @@ impl BlockCache { &self.cache[offset] as *const _ as usize } + //CPU需è¦è¯»å†™ç£ç›˜çš„æ—¶å€™ï¼Œå¤§æ¦‚是è¦è°ƒç”¨è¿™äº›å‡½æ•°çš„ + //至于内容怎么真的写进ç£ç›˜ï¼Œæ˜¯è¿™äº›å‡½æ•°å·²ç»å¸®å¿™å†™å¥½äº†ï¼Œä¼¼ä¹Žæˆ‘们ä¸ç”¨ç®¡ pub fn get_ref<T>(&self, offset: usize) -> &T where T: Sized { let type_size = core::mem::size_of::<T>(); assert!(offset + type_size <= BLOCK_SZ); @@ -73,6 +76,7 @@ impl Drop for BlockCache { const BLOCK_CACHE_SIZE: usize = 16; +//这个类型管ç†äº†ç”¨å“ªäº›ã€ä¸ç”¨å“ªäº› pub struct BlockCacheManager { queue: VecDeque<(usize, Arc<Mutex<BlockCache>>)>, } diff --git a/easy-fs/src/console.rs b/easy-fs/src/console.rs new file mode 100644 index 0000000000000000000000000000000000000000..d7f2f1b5141136e335d1ca6313557305569d2fa0 --- /dev/null +++ b/easy-fs/src/console.rs @@ -0,0 +1,141 @@ +use crate::sbi::console_putchar; +use core::fmt::{self, Write}; + +// use lazy_static::lazy_static; +use core::option_env; + +struct Stdout; + +impl Write for Stdout { + fn write_str(&mut self, s: &str) -> fmt::Result { + for c in s.chars() { + console_putchar(c as usize); + } + Ok(()) + } +} + +// /// Add escape sequence to print with color in Linux console +// macro_rules! with_color { +// ($fmt: literal, $color_code: ident) => { +// concat!("\x1b[",$color_code,"m",$fmt, "\x1b[0m") +// }; +// } +//================basics function=================== + +pub fn print(args: fmt::Arguments) { + Stdout.write_fmt(args).unwrap(); +} + +#[macro_export] +macro_rules! print { + ($fmt: literal $(, $($arg: tt)+)?) => { + $crate::console::print(format_args!($fmt $(, $($arg)+)?)); + } +} + +#[macro_export] +macro_rules! println { + ($fmt: literal $(, $($arg: tt)+)?) => { + $crate::console::print(format_args!(concat!($fmt, "\n") $(, $($arg)+)?)); + } +} + +#[macro_export] +macro_rules! fs_println{ + ($fmt: literal $(, $($arg: tt)+)?) => { + if let Some(_key) = option_env!("LOG"){ + $crate::console::print(format_args!(concat!("\x1b[96m[easy-fs] ",$fmt,"\n\x1b[0m") $(, $($arg)+)?)); + } + } +} + +#[allow(unused)] +pub fn my_log(){ + let key: Option<&'static str> = option_env!("LOG"); + println!("In test....."); + println!("the secret key might be: {:?}", key); +} + +//================more function=================== +#[macro_export] +macro_rules! kernel_println{ + ($fmt: literal $(, $($arg: tt)+)?) => { + // $crate::console::print(format_args!(concat!("\x1b[31m",$fmt, "\n","\x1b[0m") $(, $($arg)+)?)); + if let Some(_key) = option_env!("LOG"){ + $crate::console::print(format_args!(concat!("\x1b[35m[kernel] ",$fmt,"\n\x1b[0m") $(, $($arg)+)?)); + // _ => {}, + } + } +} + +#[macro_export] +macro_rules! error{ + ($fmt: literal $(, $($arg: tt)+)?) => { + // $crate::console::print(format_args!(concat!("\x1b[31m",$fmt, "\n","\x1b[0m") $(, $($arg)+)?)); + match option_env!("LOG"){ + Some("TRACE")|Some("trace") => $crate::console::print(format_args!(concat!("\x1b[31m[ERROR]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + Some("DEBUG")|Some("debug") => $crate::console::print(format_args!(concat!("\x1b[31m[ERROR]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + Some("INFO")|Some("info") => $crate::console::print(format_args!(concat!("\x1b[31m[ERROR]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + Some("WARN")|Some("warn") => $crate::console::print(format_args!(concat!("\x1b[31m[ERROR]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + Some("ERROR")|Some("error") => $crate::console::print(format_args!(concat!("\x1b[31m[ERROR]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + // None => $crate::console::print(format_args!(concat!("\x1b[31m[ERROR]",$fmt,"\n","\x1b[0m") $(, $($arg)+)?)), + _ => {}, + } + } +} + +#[macro_export] +macro_rules! warn{ + ($fmt: literal $(, $($arg: tt)+)?) => { + //$crate::console::print(format_args!(concat!("\x1b[93m",$fmt, "\n","\x1b[0m") $(, $($arg)+)?)); + match option_env!("LOG"){ + Some("INFO")|Some("info") => $crate::console::print(format_args!(concat!("\x1b[93m[WARN]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + Some("WARN")|Some("warn") => $crate::console::print(format_args!(concat!("\x1b[93m[WARN]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + Some("DEBUG")|Some("debug") => $crate::console::print(format_args!(concat!("\x1b[93m[WARN]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + Some("TRACE")|Some("trace") => $crate::console::print(format_args!(concat!("\x1b[93m[WARN]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + // None => $crate::console::print(format_args!(concat!("\x1b[93m[WARN]",$fmt,"\n","\x1b[0m") $(, $($arg)+)?)), + _ => {}, + } + } +} + +#[macro_export] +macro_rules! info{ + ($fmt: literal $(, $($arg: tt)+)?) => { + //如果LOGç‰çº§>=INFOæ‰§è¡Œä»¥ä¸‹è¿™ä¸€å¥ + // let key: Option<&'static str> = option_env!("LOG"); + // $crate::console::print(format_args!(concat!("\x1b[34m",$fmt, "\n","\x1b[0m") $(, $($arg)+)?)); + //å¦åˆ™ä»€ä¹ˆä¹Ÿä¸åš + match option_env!("LOG"){ + Some("TRACE")|Some("trace")|Some("Trace") => $crate::console::print(format_args!(concat!("\x1b[34m[INFO]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + Some("DEBUG")|Some("debug")|Some("Debug") => $crate::console::print(format_args!(concat!("\x1b[34m[INFO]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + Some("INFO")|Some("info")|Some("Info") => $crate::console::print(format_args!(concat!("\x1b[34m[INFO]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + // None => $crate::console::print(format_args!(concat!("\x1b[34m[INFO]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + _ => {}, + } + } +} + +#[macro_export] +macro_rules! debug{ + ($fmt: literal $(, $($arg: tt)+)?) => { + //$crate::console::print(format_args!(concat!("\x1b[32m",$fmt, "\n","\x1b[0m") $(, $($arg)+)?)); + match option_env!("LOG"){ + Some("DEBUG")|Some("debug") => $crate::console::print(format_args!(concat!("\x1b[32m[DEBUG]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + Some("TRACE")|Some("trace") => $crate::console::print(format_args!(concat!("\x1b[32m[DEBUG]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + _ => {}, + } + } +} + +#[macro_export] +macro_rules! trace{ + ($fmt: literal $(, $($arg: tt)+)?) => { + // $crate::console::print(format_args!(concat!("\x1b[90m",$fmt, "\n","\x1b[0m") $(, $($arg)+)?)); + match option_env!("LOG"){ + Some("TRACE")|Some("trace") => $crate::console::print(format_args!(concat!("\x1b[90m[TRACE]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + _ => {}, + } + } +} diff --git a/easy-fs/src/efs.rs b/easy-fs/src/efs.rs index 9e4445df5f7488eb4117934a19f6ab38c8771691..9db05eb4f31baced5c71ab9551418c6111f755d4 100644 --- a/easy-fs/src/efs.rs +++ b/easy-fs/src/efs.rs @@ -11,6 +11,8 @@ use super::{ }; use crate::BLOCK_SZ; +//从这一层开始,所有的数æ®ç»“构都放在内å˜ä¸Š +//问题:下é¢å‡ 层的数æ®ç»“构,怎么让它们放在ç£ç›˜ä¸Šï¼ŸOrz pub struct EasyFileSystem { pub block_device: Arc<dyn BlockDevice>, pub inode_bitmap: Bitmap, @@ -85,6 +87,7 @@ impl EasyFileSystem { Arc::new(Mutex::new(efs)) } + //åªè¦æŠŠç¼–å·ä¸º0的超级å—读入 pub fn open(block_device: Arc<dyn BlockDevice>) -> Arc<Mutex<Self>> { // read SuperBlock get_block_cache(0, Arc::clone(&block_device)) @@ -125,6 +128,8 @@ impl EasyFileSystem { } */ + //è¿™å°±çœŸçš„å¼€å§‹ç»™åˆ†é… + //inode从ç£ç›˜ä¸Šåˆ†é…出的编å·å¾—知它们在ç£ç›˜ä¸Šçš„实际ä½ç½® pub fn get_disk_inode_pos(&self, inode_id: u32) -> (u32, usize) { let inode_size = core::mem::size_of::<DiskInode>(); let inodes_per_block = (BLOCK_SZ / inode_size) as u32; diff --git a/easy-fs/src/layout.rs b/easy-fs/src/layout.rs index 7d14de467ced1f489aad53f599006bc1a6a4ee42..e66d4e2782552e5d08e2aa54a0a49ee5404c0811 100644 --- a/easy-fs/src/layout.rs +++ b/easy-fs/src/layout.rs @@ -71,8 +71,9 @@ pub enum DiskInodeType { type IndirectBlock = [u32; BLOCK_SZ / 4]; type DataBlock = [u8; BLOCK_SZ]; +//需è¦ä¿è¯æ€»å¤§å°æ˜¯128个å—节 +//åŽé¢éœ€è¦å¢žåŠ å…¶ä»–ç±»åž‹æ•°æ®çš„æ—¶å€™ï¼Œå‡å°‘直接索引的大å°å°±å¯ä»¥äº†å“¦ #[repr(C)] -/// Only support level-1 indirect now, **indirect2** field is always 0. pub struct DiskInode { pub size: u32, pub direct: [u32; INODE_DIRECT_COUNT], @@ -81,8 +82,13 @@ pub struct DiskInode { type_: DiskInodeType, } +//DiskInode的功能大概就类似一个目录(?) +//åæ£ä¼¼ä¹Žæ˜¯æŠŠinode-id输入,就å¯ä»¥ç»™å‡ºblockid的输出 +//ç„¶åŽæ‹¿ç€è¿™ä¸ªblockidæ“作ç£ç›˜å°±å¯ä»¥äº† +//è¿™ä¸ªæ–‡ä»¶çš„æ„æ€å°±æ˜¯ï¼Œæˆ‘å¯ä»¥ä¿å˜è¿™ä¹ˆå¤šä¸ªæ•°æ®å—哦 impl DiskInode { /// indirect1 and indirect2 block are allocated only when they are needed. + /// åˆå§‹åŒ–为文件或者目录 pub fn initialize(&mut self, type_: DiskInodeType) { self.size = 0; self.direct.iter_mut().for_each(|v| *v = 0); @@ -124,6 +130,12 @@ impl DiskInode { assert!(new_size >= self.size); Self::total_blocks(new_size) - Self::total_blocks(self.size) } + //æ¯ä¸€ä¸ªæ–‡ä»¶å¯¹åº”一个DiskInode。 + //inner-idçš„å«ä¹‰æ˜¯,我è¦å–出这个文件ä¸çš„ç¬¬å‡ ä¸ªæ•°æ®å— + //也就是说第inner-id个数æ®å—到底放在ç£ç›˜ä¸Šçš„哪个blockä¸ + //到底是ç£ç›˜ä¸Šçš„哪个数æ®å—,å˜å‚¨äº†æˆ‘这个inode的信æ¯ã€‚ + //我这个inode节点å˜å‚¨çš„ä¿¡æ¯å°±æ˜¯æ–‡ä»¶çš„索引, + //文件的索引ä¸å¯ä»¥æ‰¾åˆ°çœŸå®žå˜æ”¾æ–‡ä»¶çš„æ•°æ®çš„ç£ç›˜å—åœ°å€ pub fn get_block_id(&self, inner_id: u32, block_device: &Arc<dyn BlockDevice>) -> u32 { let inner_id = inner_id as usize; if inner_id < INODE_DIRECT_COUNT { @@ -237,13 +249,20 @@ impl DiskInode { } /* + + /// Clear size to zero and return blocks that should be deallocated. + /// + /// We will clear the block contents to zero later. pub fn clear_size(&mut self, block_device: &Arc<dyn BlockDevice>) -> Vec<u32> { let mut v: Vec<u32> = Vec::new(); - let blocks = self.blocks() as usize; + let mut data_blocks = self.data_blocks() as usize; self.size = 0; - for i in 0..blocks.min(INODE_DIRECT_COUNT) { - v.push(self.direct[i]); - self.direct[i] = 0; + let mut current_blocks = 0usize; + // direct + while current_blocks < data_blocks.min(INODE_DIRECT_COUNT) { + v.push(self.direct[current_blocks]); + self.direct[current_blocks] = 0; + current_blocks += 1; } if blocks > INODE_DIRECT_COUNT { get_block_cache( @@ -257,7 +276,79 @@ impl DiskInode { indirect_block[i] = 0; } }); + // indirect1 block + if data_blocks > INODE_DIRECT_COUNT { + v.push(self.indirect1); + data_blocks -= INODE_DIRECT_COUNT; + current_blocks = 0; + } else { + return v; + } + // indirect1 + get_block_cache( + self.indirect1 as usize, + Arc::clone(block_device), + ) + .lock() + .modify(0, |indirect1: &mut IndirectBlock| { + while current_blocks < data_blocks.min(INODE_INDIRECT1_COUNT) { + v.push(indirect1[current_blocks]); + //indirect1[current_blocks] = 0; + current_blocks += 1; + } + }); + self.indirect1 = 0; + // indirect2 block + if data_blocks > INODE_INDIRECT1_COUNT { + v.push(self.indirect2); + data_blocks -= INODE_INDIRECT1_COUNT; + } else { + return v; } + // indirect2 + assert!(data_blocks <= INODE_INDIRECT2_COUNT); + let a1 = data_blocks / INODE_INDIRECT1_COUNT; + let b1 = data_blocks % INODE_INDIRECT1_COUNT; + get_block_cache( + self.indirect2 as usize, + Arc::clone(block_device), + ) + .lock() + .modify(0, |indirect2: &mut IndirectBlock| { + // full indirect1 blocks + for i in 0..a1 { + v.push(indirect2[i]); + get_block_cache( + indirect2[i] as usize, + Arc::clone(block_device), + ) + .lock() + .modify(0, |indirect1: &mut IndirectBlock| { + for j in 0..INODE_INDIRECT1_COUNT { + v.push(indirect1[j]); + //indirect1[j] = 0; + } + }); + //indirect2[i] = 0; + } + // last indirect1 block + if b1 > 0 { + v.push(indirect2[a1]); + get_block_cache( + indirect2[a1] as usize, + Arc::clone(block_device), + ) + .lock() + .modify(0, |indirect1: &mut IndirectBlock| { + for j in 0..b1 { + v.push(indirect1[j]); + //indirect1[j] = 0; + } + }); + //indirect2[a1] = 0; + } + }); + self.indirect2 = 0; v } */ @@ -426,6 +517,14 @@ impl DiskInode { } } +//DirEntryçš„å«ä¹‰æ˜¯ï¼Œå¯¹äºŽç£ç›˜ä¸çš„æ¯ä¸€ä¸ªç›®å½•ï¼Œé‡Œé¢éƒ½æ”¾äº†è®¸å¤šçš„æ–‡ä»¶å“¦ +//一个目录项表示其ä¸ä¸€ä¸ªæ–‡ä»¶çš„ä¿¡æ¯ï¼šname+inode_number +//ä¸€ä¸ªç›®å½•å°±å®žçŽ°ä¸ºå¾ˆå¤šä¸ªç›®å½•é¡¹çš„ç»„åˆ +//目录项说的应该是这个 +//事实上åªè¦æŠŠç›®å½•项的inode-number修改过去就å¯ä»¥äº† +//对于目录项æ¥è¯´ï¼Œå®žé™…ä¸Šå°±æ˜¯åœ¨æ ¹ç›®å½•ä¸‹é¢æ–°å¢žåŠ äº†ä¸€ä¸ªDirEntry +//这个DirEntryçš„nameå¯èƒ½æ˜¯æ–°çš„,inode也是新分é…çš„inode +//但是block-id是和之å‰çš„一致的 #[repr(C)] pub struct DirEntry { name: [u8; NAME_LENGTH_LIMIT + 1], @@ -434,10 +533,13 @@ pub struct DirEntry { pub const DIRENT_SZ: usize = 32; -//pub type DirentBlock = [DirEntry; BLOCK_SZ / DIRENT_SZ]; -pub type DirentBytes = [u8; DIRENT_SZ]; - impl DirEntry { + pub fn empty() -> Self { + Self { + name: [0u8; NAME_LENGTH_LIMIT + 1], + inode_number: 0, + } + } pub fn new(name: &str, inode_number: u32) -> Self { let mut bytes = [0u8; NAME_LENGTH_LIMIT + 1]; &mut bytes[..name.len()].copy_from_slice(name.as_bytes()); @@ -446,18 +548,20 @@ impl DirEntry { inode_number, } } - pub fn into_bytes(&self) -> &DirentBytes { + pub fn as_bytes(&self) -> &[u8] { unsafe { - &*(self as *const Self as usize as *const DirentBytes) + core::slice::from_raw_parts( + self as *const _ as usize as *const u8, + DIRENT_SZ, + ) } } - pub fn from_bytes(bytes: &DirentBytes) -> &Self { - unsafe { &*(bytes.as_ptr() as usize as *const Self) } - } - #[allow(unused)] - pub fn from_bytes_mut(bytes: &mut DirentBytes) -> &mut Self { + pub fn as_bytes_mut(&mut self) -> &mut [u8] { unsafe { - &mut *(bytes.as_mut_ptr() as usize as *mut Self) + core::slice::from_raw_parts_mut( + self as *mut _ as usize as *mut u8, + DIRENT_SZ, + ) } } pub fn name(&self) -> &str { diff --git a/easy-fs/src/lib.rs b/easy-fs/src/lib.rs index 10a5af76ef287785b3627f7a1f0b6fabc5166c6e..3b444a2843a747143f6c5dd561b299ac5e043d87 100644 --- a/easy-fs/src/lib.rs +++ b/easy-fs/src/lib.rs @@ -1,7 +1,12 @@ #![no_std] +#![feature(global_asm)] +#![feature(llvm_asm)] extern crate alloc; +#[macro_use] +mod console; +mod sbi; mod block_dev; mod layout; mod efs; diff --git a/easy-fs/src/sbi.rs b/easy-fs/src/sbi.rs new file mode 100644 index 0000000000000000000000000000000000000000..abeeb7e1571645e00e375fb18ea0765320f5f24a --- /dev/null +++ b/easy-fs/src/sbi.rs @@ -0,0 +1,44 @@ +#![allow(unused)] +#![feature(global_asm)] +#![feature(llvm_asm)] + +const SBI_SET_TIMER: usize = 0; +const SBI_CONSOLE_PUTCHAR: usize = 1; +const SBI_CONSOLE_GETCHAR: usize = 2; +const SBI_CLEAR_IPI: usize = 3; +const SBI_SEND_IPI: usize = 4; +const SBI_REMOTE_FENCE_I: usize = 5; +const SBI_REMOTE_SFENCE_VMA: usize = 6; +const SBI_REMOTE_SFENCE_VMA_ASID: usize = 7; +const SBI_SHUTDOWN: usize = 8; + +#[inline(always)] +fn sbi_call(which: usize, arg0: usize, arg1: usize, arg2: usize) -> usize { + let mut ret=0; + // unsafe { + // llvm_asm!("ecall" + // : "={x10}" (ret) + // : "{x10}" (arg0), "{x11}" (arg1), "{x12}" (arg2), "{x17}" (which) + // : "memory" + // : "volatile" + // ); + // } + ret +} + +pub fn set_timer(timer: usize) { + sbi_call(SBI_SET_TIMER, timer, 0, 0); +} + +pub fn console_putchar(c: usize) { + sbi_call(SBI_CONSOLE_PUTCHAR, c, 0, 0); +} + +pub fn console_getchar() -> usize { + sbi_call(SBI_CONSOLE_GETCHAR, 0, 0, 0) +} + +pub fn shutdown() -> ! { + sbi_call(SBI_SHUTDOWN, 0, 0, 0); + panic!("It should shutdown!"); +} diff --git a/easy-fs/src/vfs.rs b/easy-fs/src/vfs.rs index f10a8c8a39415dfdf2d559b06a745c9fb356ebaa..4b2e44a80d4152d45575de1ec715480ad9c39e65 100644 --- a/easy-fs/src/vfs.rs +++ b/easy-fs/src/vfs.rs @@ -1,9 +1,9 @@ + use super::{ BlockDevice, DiskInode, DiskInodeType, DirEntry, - DirentBytes, EasyFileSystem, DIRENT_SZ, get_block_cache, @@ -12,15 +12,22 @@ use alloc::sync::Arc; use alloc::string::String; use alloc::vec::Vec; use spin::{Mutex, MutexGuard}; +// use super::lib::*; +//注æ„,这个数æ®ç»“构是放在内å˜é‡Œé¢çš„ +//æŸç§æ„义上说å¯ä»¥éšä¾¿ä¿®æ”¹Â·Â·Â·Â·Â·Â· pub struct Inode { - block_id: usize, + //新增.我就很想知é“为什么这个结构里é¢ä¸ç›´æŽ¥å˜ä¸€ä¸ªinode-id好了??? + //ä¸ºä»€ä¹ˆæ¯æ¬¡éƒ½è¦è¿™ä¹ˆéº»çƒ¦Â·Â·Â·å› 为访问硬盘很慢很慢ï¼ï¼ï¼çš„啊ï¼ï¼ï¼ï¼ + my_inode_id: u32,//还是éžå¸¸éœ€è¦çš„ + block_id: usize,//表明这个inodeå˜å‚¨åœ¨ç£ç›˜çš„哪个å—上s block_offset: usize, fs: Arc<Mutex<EasyFileSystem>>, block_device: Arc<dyn BlockDevice>, } impl Inode { + //============================================== pub fn new( inode_id: u32, fs: Arc<Mutex<EasyFileSystem>>, @@ -28,6 +35,7 @@ impl Inode { ) -> Self { let (block_id, block_offset) = fs.lock().get_disk_inode_pos(inode_id); Self { + my_inode_id: inode_id,//new block_id: block_id as usize, block_offset, fs, @@ -55,25 +63,35 @@ impl Inode { } */ + //这个返回的大概就是stat想è¦çš„inodeç¼–å·å§ + //这个函数调用的时候就disk_inodeä½¿ç”¨æ ¹ç›®å½•å°±å¯ä»¥äº† + //给定一个DiskInode,也就是一个文件,而且è¦å‡è®¾å®ƒæ˜¯ä¸€ä¸ªç›®å½• + //é历这个目录下é¢çš„æ‰€æœ‰æ–‡ä»¶ + //如果å‘çŽ°é‚£ä¸ªæ–‡ä»¶å’Œè‡ªå·±æƒ³è¦æ‰¾çš„æ–‡ä»¶åä¸€æ · + //那么就返回那个文件的inode_id + //看起æ¥è¿™å°±æ˜¯éœ€è¦è¿”回的ino了 + //å·²ç»å®Œå…¨æžæ‡‚这是在åšä»€ä¹ˆäº†ï¼Œå°±æ˜¯æŠŠä¸€ä¸ªæ–‡ä»¶å¤¹ä¸‹é¢çš„æ–‡ä»¶éƒ½é历一é + //有了inode-id,就å¯ä»¥ä»Žè¶…级å—里é¢è®¿é—®æ–‡ä»¶äº† fn find_inode_id( &self, name: &str, disk_inode: &DiskInode, ) -> Option<u32> { // assert it is a directory + fs_println!("find_inode_id::disk_node is dir...{}",disk_inode.is_dir()); assert!(disk_inode.is_dir()); let file_count = (disk_inode.size as usize) / DIRENT_SZ; - let mut dirent_space: DirentBytes = Default::default(); + let mut dirent = DirEntry::empty(); for i in 0..file_count { assert_eq!( disk_inode.read_at( DIRENT_SZ * i, - &mut dirent_space, + dirent.as_bytes_mut(), &self.block_device, ), DIRENT_SZ, ); - let dirent = DirEntry::from_bytes(&dirent_space); + fs_println!("find_inode_id::dirent name is {}, inode number is {}",dirent.name(),dirent.inode_number()); if dirent.name() == name { return Some(dirent.inode_number() as u32); } @@ -81,6 +99,48 @@ impl Inode { None } + //也é™åˆ¶åªæœ‰æ ¹ç›®å½•å¯ä»¥è°ƒç”¨å¥½äº† + pub fn get_inode_id(&self, name: &str) -> Option<u32>{ + let _ = self.fs.lock(); + self.read_disk_inode(|disk_inode| { + self.find_inode_id(name, disk_inode) + }) + } + + pub fn get_my_inode_id(&self) ->Option<u32>{ + return Some(self.my_inode_id) + } + + //已知有一个inode类型 + //å¸Œæœ›çŸ¥é“æˆ‘代表的文件的inodeæ˜¯å¤šå°‘å· + pub fn get_my_data(&self) ->Option<u32>{ + let _ = self.fs.lock(); + self.read_disk_inode(|disk_inode| { + fs_println!("Inode::get_my_data::disk_node is dir...{}",disk_inode.is_dir()); + let file_count = (disk_inode.size as usize) / DIRENT_SZ; + let mut dirent = DirEntry::empty(); + for i in 0..file_count { + assert_eq!( + disk_inode.read_at( + DIRENT_SZ * i, + dirent.as_bytes_mut(), + &self.block_device, + ), + DIRENT_SZ, + ); + //TODO这里è¦ä¿®æ”¹è¾“出,能够返回文件åé¸ + // fs_println!("get_my_data::dirent name is {}, inode number is {}",dirent.name(),dirent.inode_number()); + if dirent.inode_number() == self.my_inode_id { + // return Some((dirent.inode_number() as u32, dirent.name())); + fs_println!("get_my_data::dirent name is {}, inode number is {},but return None",dirent.name(),dirent.inode_number()); + return None; + } + } + return None; + }) + } + + //刚刚æ„识到哪里有问题ï¼å…¶å®žå˜inodeç¼–å·å°±å¯ä»¥äº†ï¼Ÿ pub fn find(&self, name: &str) -> Option<Arc<Inode>> { let _ = self.fs.lock(); self.read_disk_inode(|disk_inode| { @@ -144,7 +204,7 @@ impl Inode { let dirent = DirEntry::new(name, new_inode_id); root_inode.write_at( file_count * DIRENT_SZ, - dirent.into_bytes(), + dirent.as_bytes(), &self.block_device, ); }); @@ -158,22 +218,271 @@ impl Inode { ))) } + //这个函数åªå…许ROOT调用 + //一旦建立了linkerï¼Œæ ¹ç›®å½•ä¸‹é¢çš„两个DirEntry的地ä½å°±æ˜¯å·®ä¸å¤šçš„ + pub fn create_linker(&self, name: &str, old_name: &str) -> Option<Arc<Inode>> { + let mut fs = self.fs.lock(); + + //先检查原æ¥çš„æ–‡ä»¶æ˜¯å¦å˜åœ¨ + if self.modify_disk_inode(|root_inode| { + // assert it is a directory + assert!(root_inode.is_dir()); + // has the file been created? + self.find_inode_id(old_name, root_inode) + }).is_none() { + return None; + } + + //å°±ä¸ç”¨æ–°å»ºinode了 + //å…ˆèŽ·å–æ—§çš„æ–‡ä»¶åå’Œinode-id + //冿–°å»ºç›®å½•项就å¯ä»¥äº† + let mut inode_id = 0; + //新建一个目录项 + self.modify_disk_inode(|root_inode| { + // append file in the dirent + let file_count = (root_inode.size as usize) / DIRENT_SZ; + let new_size = (file_count + 1) * DIRENT_SZ; + // increase size + self.increase_size(new_size as u32, root_inode, &mut fs); + // write dirent + let inode_id = self.find_inode_id(old_name, root_inode).unwrap();//å› ä¸ºå‰é¢å·²ç»æ£€æŸ¥è¿‡åˆæ³•性了 + //所以这个inode-idä¸€å®šæ˜¯åˆæ³•çš„ + let dirent = DirEntry::new(name, inode_id); + root_inode.write_at( + file_count * DIRENT_SZ, + dirent.as_bytes(), + &self.block_device, + ); + }); + // release efs lock manually because we will acquire it again in Inode::new + drop(fs); + // return inode + Some(Arc::new(Self::new( + inode_id, + self.fs.clone(), + self.block_device.clone(), + ))) + } + + //这个函数也åªå…许ROOT调用 + //è¿™è¦æ€Žä¹ˆå†™Â·Â·Â·Â·Â·Â·ä¸å¦‚æˆ‘æ”¹ä¸€ä¸‹å¥½äº†ï¼Œæ¯”å¦‚è¯´å¢žåŠ ä¸€ä¸ªvalidä½ï¼Ÿ + //todo:fix return type, Option<bool> + pub fn delete_linker(&self, name: &str) -> bool{ + let fs = self.fs.lock(); + + //先检查想è¦unlink的文件是å¦å˜åœ¨ + if self.modify_disk_inode(|root_inode| { + // assert it is a directory + assert!(root_inode.is_dir()); + // has the file been created? + self.find_inode_id(name, root_inode) + }).is_none() { + return false; + } + + //就是ä¸ç”¨è€ƒè™‘åªå‰©ä¸‹è¿™ä¸€ä¸ªDirEntry到文件还有linkçš„æƒ…å†µï¼Œç›´æŽ¥åˆ é™¤å³å¯ + //把那个Entry设置æˆä¸åˆæ³•å³å¯ + let mut result = false; + //新建一个目录项 + self.modify_disk_inode(|root_inode| { + // append file in the dirent + let file_count = (root_inode.size as usize) / DIRENT_SZ; + let mut dirent = DirEntry::empty(); + for i in 0..file_count { + assert_eq!( + root_inode.read_at( + DIRENT_SZ * i, + dirent.as_bytes_mut(), + &self.block_device, + ), + DIRENT_SZ, + ); + //TODO这里è¦ä¿®æ”¹è¾“出,能够返回文件åé¸ + // fs_println!("get_my_data::dirent name is {}, inode number is {}",dirent.name(),dirent.inode_number()); + if dirent.name() == name { + fs_println!("get_my_data::dirent name is {}, inode number is {},but return None", + dirent.name(),dirent.inode_number()); + //如果找到了,那么就把空的写进去 + //就是用一个ä¸åˆæ³•的内容替æ¢çš„æ„æ€ + let mut dirent_unlink = DirEntry::empty(); + assert_eq!( + root_inode.write_at( + i * DIRENT_SZ, + dirent_unlink.as_bytes(), + &self.block_device, + ), + DIRENT_SZ, + ); + result = true; + } + } + }); + // release efs lock manually because we will acquire it again in Inode::new + drop(fs); + // return nothing + return result; + } + + //åªæœ‰æ ¹ç›®å½•å¯ä»¥è°ƒç”¨ + pub fn count_files(&self, name: &str) -> Option<usize>{ + let fs = self.fs.lock(); + + //先检查想è¦è®¡æ•°çš„æ–‡ä»¶æ˜¯å¦å˜åœ¨ + if self.modify_disk_inode(|root_inode| { + // assert it is a directory + assert!(root_inode.is_dir()); + // has the file been created? + self.find_inode_id(name, root_inode) + }).is_none() { + return None; + } + + // + let mut counter = 0 as usize; + + //就是ä¸ç”¨è€ƒè™‘åªå‰©ä¸‹è¿™ä¸€ä¸ªDirEntry到文件还有linkçš„æƒ…å†µï¼Œç›´æŽ¥åˆ é™¤å³å¯ + //把那个Entry设置æˆä¸åˆæ³•å³å¯ + let mut inode_id = 0; + //新建一个目录项 + self.modify_disk_inode(|root_inode| { + // append file in the dirent + let file_count = (root_inode.size as usize) / DIRENT_SZ; + let mut dirent = DirEntry::empty(); + for i in 0..file_count { + assert_eq!( + root_inode.read_at( + DIRENT_SZ * i, + dirent.as_bytes_mut(), + &self.block_device, + ), + DIRENT_SZ, + ); + //得到了自己的inode-number + if dirent.name() == name { + fs_println!("count_files::get_inode_id::dirent name is {}, inode number is {},but return None", + dirent.name(),dirent.inode_number()); + //如果找到了,那么就把空的写进去 + //就是用一个ä¸åˆæ³•的内容替æ¢çš„æ„æ€ + inode_id = dirent.inode_number(); + break; + } + } + + //䏋颿˜¯è®¡æ•°çš„内容 + for i in 0..file_count { + assert_eq!( + root_inode.read_at( + DIRENT_SZ * i, + dirent.as_bytes_mut(), + &self.block_device, + ), + DIRENT_SZ, + ); + //得到了自己的inode-number + if dirent.inode_number() == inode_id { + fs_println!("count_files::counting::dirent name is {}, inode number is {},but return None", + dirent.name(),dirent.inode_number()); + //如果找到了,那么就把空的写进去 + //就是用一个ä¸åˆæ³•的内容替æ¢çš„æ„æ€ + counter = counter + 1; + } + } + }); + // release efs lock manually because we will acquire it again in Inode::new + drop(fs); + // return nothing + return Some(counter); + } + + //åªæœ‰æ ¹ç›®å½•å¯ä»¥è°ƒç”¨ + pub fn count_files_from_me(&self) -> Option<usize>{ + let fs = self.fs.lock(); + + let mut counter = 0 as usize; + //新建一个目录项 + self.modify_disk_inode(|root_inode| { + // append file in the dirent + let file_count = (root_inode.size as usize) / DIRENT_SZ; + let mut dirent = DirEntry::empty(); + //䏋颿˜¯è®¡æ•°çš„内容 + for i in 0..file_count { + assert_eq!( + root_inode.read_at( + DIRENT_SZ * i, + dirent.as_bytes_mut(), + &self.block_device, + ), + DIRENT_SZ, + ); + //得到了自己的inode-number + if dirent.inode_number() == self.my_inode_id { + fs_println!("count_files::counting::dirent name is {}, inode number is {},", + dirent.name(),dirent.inode_number()); + //如果找到了,那么就把空的写进去 + //就是用一个ä¸åˆæ³•的内容替æ¢çš„æ„æ€ + counter = counter + 1; + } + } + }); + // release efs lock manually because we will acquire it again in Inode::new + drop(fs); + // return nothing + return Some(counter); + } + + //åªæœ‰æ ¹ç›®å½•å¯ä»¥è°ƒç”¨ + pub fn count_files_from_id(&self,id:u32) -> Option<usize>{ + let fs = self.fs.lock(); + + let mut counter = 0 as usize; + //新建一个目录项 + self.modify_disk_inode(|root_inode| { + // append file in the dirent + let file_count = (root_inode.size as usize) / DIRENT_SZ; + let mut dirent = DirEntry::empty(); + //䏋颿˜¯è®¡æ•°çš„内容 + for i in 0..file_count { + assert_eq!( + root_inode.read_at( + DIRENT_SZ * i, + dirent.as_bytes_mut(), + &self.block_device, + ), + DIRENT_SZ, + ); + //得到了自己的inode-number + if dirent.inode_number() == id { + fs_println!("count_files::counting::dirent name is {}, inode number is {},", + dirent.name(),dirent.inode_number()); + //如果找到了,那么就把空的写进去 + //就是用一个ä¸åˆæ³•的内容替æ¢çš„æ„æ€ + counter = counter + 1; + } + } + }); + // release efs lock manually because we will acquire it again in Inode::new + drop(fs); + // return nothing + return Some(counter); + } + + pub fn ls(&self) -> Vec<String> { let _ = self.fs.lock(); self.read_disk_inode(|disk_inode| { let file_count = (disk_inode.size as usize) / DIRENT_SZ; let mut v: Vec<String> = Vec::new(); for i in 0..file_count { - let mut dirent_bytes: DirentBytes = Default::default(); + let mut dirent = DirEntry::empty(); assert_eq!( disk_inode.read_at( i * DIRENT_SZ, - &mut dirent_bytes, + dirent.as_bytes_mut(), &self.block_device, ), DIRENT_SZ, ); - v.push(String::from(DirEntry::from_bytes(&dirent_bytes).name())); + v.push(String::from(dirent.name())); } v }) diff --git a/os/.cargo/config b/os/.cargo/config index 4275fcad6f8a3605fed9c98a841a8de4ef5e94a9..a3fa674332e971e07bdb0adb57bf42bdf31b075a 100644 --- a/os/.cargo/config +++ b/os/.cargo/config @@ -5,3 +5,8 @@ target = "riscv64gc-unknown-none-elf" rustflags = [ "-Clink-arg=-Tsrc/linker.ld", "-Cforce-frame-pointers=yes" ] + +[source.crates-io] +replace-with = 'tuna' +[source.tuna] +registry = "https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git" diff --git a/os/Cargo.toml b/os/Cargo.toml index bded64091260e8a867c49f072a9ae21e563cf809..e8a62369744b72dc02442c2204ce62017e06cd9b 100644 --- a/os/Cargo.toml +++ b/os/Cargo.toml @@ -8,6 +8,7 @@ edition = "2018" [dependencies] riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] } +# riscv = { git = "https://gitee.com/chyyuu/riscv", features = ["inline-asm"] } lazy_static = { version = "1.4.0", features = ["spin_no_std"] } buddy_system_allocator = "0.6" spin = "0.7.0" @@ -17,8 +18,16 @@ virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers" } k210-pac = { git = "https://github.com/wyfcyx/k210-pac" } k210-hal = { git = "https://github.com/wyfcyx/k210-hal" } k210-soc = { git = "https://github.com/wyfcyx/k210-soc" } +#k210-pac = { git = "https://gitee.com/chyyuu/k210-pac" } +#k210-hal = { git = "https://gitee.com/chyyuu/k210-hal" } +#k210-soc = { git = "https://gitee.com/chyyuu/k210-soc" } easy-fs = { path = "../easy-fs" } +log = "0.4" + +# rvm +# rvm = { git = "https://github.com/rcore-os/RVM", rev = "939eb0a", optional = true } +#rvm = { git = "https://github.com/chenzm-plusplus/RVM", rev = "382fc60", optional = true } [features] board_qemu = [] -board_k210 = [] \ No newline at end of file +board_k210 = [] diff --git a/os/Makefile b/os/Makefile index 4d86c12477953c68ab3e23c21d5bb18407a340a4..f6285a488ca91151e941008f654d405000282443 100644 --- a/os/Makefile +++ b/os/Makefile @@ -71,10 +71,9 @@ disasm-vim: kernel @vim $(DISASM_TMP) @rm $(DISASM_TMP) -run: tools run-inner +run: run-inner -tools: - (which $(K210-BURNER)) || (cd .. && git clone https://github.com/sipeed/kflash.py.git && mv kflash.py tools) + run-inner: build ifeq ($(BOARD),qemu) @@ -86,6 +85,7 @@ ifeq ($(BOARD),qemu) -drive file=$(FS_IMG),if=none,format=raw,id=x0 \ -device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0 else + (which $(K210-BURNER)) || (cd .. && git clone https://github.com/sipeed/kflash.py.git && mv kflash.py tools) @cp $(BOOTLOADER) $(BOOTLOADER).copy @dd if=$(KERNEL_BIN) of=$(BOOTLOADER).copy bs=$(K210_BOOTLOADER_SIZE) seek=1 @mv $(BOOTLOADER).copy $(KERNEL_BIN) @@ -100,4 +100,4 @@ debug: build tmux split-window -h "riscv64-unknown-elf-gdb -ex 'file $(KERNEL_ELF)' -ex 'set arch riscv:rv64' -ex 'target remote localhost:1234'" && \ tmux -2 attach-session -d -.PHONY: build env kernel clean disasm disasm-vim run-inner tools +.PHONY: build env kernel clean disasm disasm-vim run-inner \ No newline at end of file diff --git a/os/src/config.rs b/os/src/config.rs index 0633c4da9b255dd90784b1275822def127f0fc8c..46e3e8db12b33b3a9c46c71ff448694eaa48f6f1 100644 --- a/os/src/config.rs +++ b/os/src/config.rs @@ -4,12 +4,44 @@ pub const USER_STACK_SIZE: usize = 4096 * 2; pub const KERNEL_STACK_SIZE: usize = 4096 * 2; pub const KERNEL_HEAP_SIZE: usize = 0x20_0000; pub const MEMORY_END: usize = 0x80800000; + +// #[cfg(feature = "board_k210")] +// pub const MEMORY_END: usize = 0x80600000; + +// #[cfg(feature = "board_qemu")] +// pub const MEMORY_END: usize = 0x80800000; + pub const PAGE_SIZE: usize = 0x1000; pub const PAGE_SIZE_BITS: usize = 0xc; pub const TRAMPOLINE: usize = usize::MAX - PAGE_SIZE + 1; pub const TRAP_CONTEXT: usize = TRAMPOLINE - PAGE_SIZE; +pub const TASK_PRIORITY_INIT: usize = 16; +//=============== +// pub const PAGE_SIZE: usize = 0x1000;//16进制的100就是4096个å—节 +// pub const PAGE_SIZE_BITS: usize = 0xc;//表示我è¦ç”¨å¤šå°‘ä½çš„æ•°è¡¨ç¤ºä¸€ä¸ªpage,也就是page offsetçš„ä½æ•°ã€‚12ä½ +pub const MEMORY_MAP_SIZE: usize = 0x4_000_000;//è¡¨ç¤ºè¿›è¡Œä¸€æ¬¡å†…å˜æ˜ å°„æœ€å¤šæ˜ å°„å¤šå°‘å—节 + +// pub const TRAMPOLINE: usize = usize::MAX - PAGE_SIZE + 1; +// pub const TRAP_CONTEXT: usize = TRAMPOLINE - PAGE_SIZE; +// /// Return (bottom, top) of a kernel stack in kernel space. +// pub fn kernel_stack_position(app_id: usize) -> (usize, usize) { +// let top = TRAMPOLINE - app_id * (KERNEL_STACK_SIZE + PAGE_SIZE);//ä½“çŽ°åœ¨è¿™é‡Œï¼Œä¸¤ä¸ªç›¸é‚»å†…æ ¸æ ˆä¹‹é—´ä¼šé¢„ç•™ä¸€ä¸ªä¿æŠ¤page +// let bottom = top - KERNEL_STACK_SIZE; +// (bottom, top) +// } +pub const ISIZI_MAX: isize = isize::MAX; +// // pub const BIG_STRIDE: usize = 1024;//一个预先定义的大常数···多大好呢?就这么大好了 +pub const BIG_STRIDE: usize = 4096*4096; +// pub const MAX_RUN_TIME_MS: usize = 600; +pub const MAIL_SIZE: usize = 256; + + + + +//for map + #[cfg(feature = "board_k210")] pub const CLOCK_FREQ: usize = 403000000 / 62; @@ -18,7 +50,7 @@ pub const CLOCK_FREQ: usize = 12500000; #[cfg(feature = "board_qemu")] pub const MMIO: &[(usize, usize)] = &[ - (0x10000000, 0x10000), + (0x10001000, 0x1000), ]; #[cfg(feature = "board_k210")] @@ -39,4 +71,4 @@ pub const MMIO: &[(usize, usize)] = &[ (0x5200_0000, 0x1000), /* SPI0 */ (0x5300_0000, 0x1000), /* SPI1 */ (0x5400_0000, 0x1000), /* SPI2 */ -]; \ No newline at end of file +]; diff --git a/os/src/console.rs b/os/src/console.rs index 2bd5593046ac358ae6f950486336924a088bfbdc..e46da8cca97c5e491f0dc96e66196bd5157d62f6 100644 --- a/os/src/console.rs +++ b/os/src/console.rs @@ -1,5 +1,8 @@ -use core::fmt::{self, Write}; use crate::sbi::console_putchar; +use core::fmt::{self, Write}; + +// use lazy_static::lazy_static; +use core::option_env; struct Stdout; @@ -12,6 +15,14 @@ impl Write for Stdout { } } +// /// Add escape sequence to print with color in Linux console +// macro_rules! with_color { +// ($fmt: literal, $color_code: ident) => { +// concat!("\x1b[",$color_code,"m",$fmt, "\x1b[0m") +// }; +// } +//================basics function=================== + pub fn print(args: fmt::Arguments) { Stdout.write_fmt(args).unwrap(); } @@ -30,4 +41,102 @@ macro_rules! println { } } +#[macro_export] +macro_rules! fs_println{ + ($fmt: literal $(, $($arg: tt)+)?) => { + // $crate::console::print(format_args!(concat!("\x1b[31m",$fmt, "\n","\x1b[0m") $(, $($arg)+)?)); + if let Some(key) = option_env!("LOG"){ + $crate::console::print(format_args!(concat!("\x1b[38m[easy-fs] ",$fmt,"\n\x1b[0m") $(, $($arg)+)?)); + } + } +} + +#[allow(unused)] +pub fn my_log(){ + let key: Option<&'static str> = option_env!("LOG"); + println!("In test....."); + println!("the secret key might be: {:?}", key); +} + +//================more function=================== +#[macro_export] +macro_rules! kernel_println{ + ($fmt: literal $(, $($arg: tt)+)?) => { + // $crate::console::print(format_args!(concat!("\x1b[31m",$fmt, "\n","\x1b[0m") $(, $($arg)+)?)); + if let Some(_key) = option_env!("LOG"){ + $crate::console::print(format_args!(concat!("\x1b[35m[kernel] ",$fmt,"\n\x1b[0m") $(, $($arg)+)?)); + // _ => {}, + } + } +} + +#[macro_export] +macro_rules! error{ + ($fmt: literal $(, $($arg: tt)+)?) => { + // $crate::console::print(format_args!(concat!("\x1b[31m",$fmt, "\n","\x1b[0m") $(, $($arg)+)?)); + match option_env!("LOG"){ + Some("TRACE")|Some("trace") => $crate::console::print(format_args!(concat!("\x1b[31m[ERROR]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + Some("DEBUG")|Some("debug") => $crate::console::print(format_args!(concat!("\x1b[31m[ERROR]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + Some("INFO")|Some("info") => $crate::console::print(format_args!(concat!("\x1b[31m[ERROR]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + Some("WARN")|Some("warn") => $crate::console::print(format_args!(concat!("\x1b[31m[ERROR]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + Some("ERROR")|Some("error") => $crate::console::print(format_args!(concat!("\x1b[31m[ERROR]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + // None => $crate::console::print(format_args!(concat!("\x1b[31m[ERROR]",$fmt,"\n","\x1b[0m") $(, $($arg)+)?)), + _ => {}, + } + } +} + +#[macro_export] +macro_rules! warn{ + ($fmt: literal $(, $($arg: tt)+)?) => { + //$crate::console::print(format_args!(concat!("\x1b[93m",$fmt, "\n","\x1b[0m") $(, $($arg)+)?)); + match option_env!("LOG"){ + Some("INFO")|Some("info") => $crate::console::print(format_args!(concat!("\x1b[93m[WARN]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + Some("WARN")|Some("warn") => $crate::console::print(format_args!(concat!("\x1b[93m[WARN]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + Some("DEBUG")|Some("debug") => $crate::console::print(format_args!(concat!("\x1b[93m[WARN]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + Some("TRACE")|Some("trace") => $crate::console::print(format_args!(concat!("\x1b[93m[WARN]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + // None => $crate::console::print(format_args!(concat!("\x1b[93m[WARN]",$fmt,"\n","\x1b[0m") $(, $($arg)+)?)), + _ => {}, + } + } +} + +#[macro_export] +macro_rules! info{ + ($fmt: literal $(, $($arg: tt)+)?) => { + //如果LOGç‰çº§>=INFOæ‰§è¡Œä»¥ä¸‹è¿™ä¸€å¥ + // let key: Option<&'static str> = option_env!("LOG"); + // $crate::console::print(format_args!(concat!("\x1b[34m",$fmt, "\n","\x1b[0m") $(, $($arg)+)?)); + //å¦åˆ™ä»€ä¹ˆä¹Ÿä¸åš + match option_env!("LOG"){ + Some("TRACE")|Some("trace")|Some("Trace") => $crate::console::print(format_args!(concat!("\x1b[34m[INFO]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + Some("DEBUG")|Some("debug")|Some("Debug") => $crate::console::print(format_args!(concat!("\x1b[34m[INFO]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + Some("INFO")|Some("info")|Some("Info") => $crate::console::print(format_args!(concat!("\x1b[34m[INFO]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + // None => $crate::console::print(format_args!(concat!("\x1b[34m[INFO]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + _ => {}, + } + } +} +#[macro_export] +macro_rules! debug{ + ($fmt: literal $(, $($arg: tt)+)?) => { + //$crate::console::print(format_args!(concat!("\x1b[32m",$fmt, "\n","\x1b[0m") $(, $($arg)+)?)); + match option_env!("LOG"){ + Some("DEBUG")|Some("debug") => $crate::console::print(format_args!(concat!("\x1b[32m[DEBUG]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + Some("TRACE")|Some("trace") => $crate::console::print(format_args!(concat!("\x1b[32m[DEBUG]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + _ => {}, + } + } +} + +#[macro_export] +macro_rules! trace{ + ($fmt: literal $(, $($arg: tt)+)?) => { + // $crate::console::print(format_args!(concat!("\x1b[90m",$fmt, "\n","\x1b[0m") $(, $($arg)+)?)); + match option_env!("LOG"){ + Some("TRACE")|Some("trace") => $crate::console::print(format_args!(concat!("\x1b[90m[TRACE]",$fmt,"\n\x1b[0m") $(, $($arg)+)?)), + _ => {}, + } + } +} diff --git a/os/src/fs/inode.rs b/os/src/fs/inode.rs index 04ccb45f7fcf1c9cd613483d4e70886f702aa80c..4d621bc4adff8a911eda4d84f975ffa69a44925d 100644 --- a/os/src/fs/inode.rs +++ b/os/src/fs/inode.rs @@ -51,6 +51,20 @@ impl OSInode { } v } + pub fn get_my_inode_id(&self) -> Option<u32>{ + let mut inner = self.inner.lock(); + return inner.inode.get_my_inode_id(); + } + + pub fn count_files_from_me(&self) ->Option<usize>{ + let mut inner = self.inner.lock(); + return inner.inode.count_files_from_me(); + } + + pub fn count_files_from_id(&self,id:u32) ->Option<usize>{ + let mut inner = self.inner.lock(); + return inner.inode.count_files_from_id(id); + } } lazy_static! { @@ -95,8 +109,10 @@ impl OpenFlags { pub fn open_file(name: &str, flags: OpenFlags) -> Option<Arc<OSInode>> { let (readable, writable) = flags.read_write(); if flags.contains(OpenFlags::CREATE) { + kernel_println!("[open_file] creating file"); if let Some(inode) = ROOT_INODE.find(name) { // clear size + // kernel_println!("[open_file] creating file"); inode.clear(); Some(Arc::new(OSInode::new( readable, @@ -129,9 +145,34 @@ pub fn open_file(name: &str, flags: OpenFlags) -> Option<Arc<OSInode>> { } } +//perhaps done +pub fn get_inode_id(name: &str) -> Option<u32>{ + ROOT_INODE.get_inode_id(name) +} + +// pub fn create(&self, name: &str,old_name: &str) -> Option<Arc<Inode>> +pub fn create_linker(name:&str,old_name:&str) -> Option<Arc<Inode>>{ + ROOT_INODE.create_linker(name,old_name) +} + +// pub fn delete_linker(&self, name: &str) -> Option<bool> +pub fn delete_linker(name: &str) -> bool{ + ROOT_INODE.delete_linker(name) +} + +// pub fn count_files(&self, name: &str) -> Option<usize> +pub fn count_files(name:&str) ->Option<usize>{ + ROOT_INODE.count_files(name) +} + +pub fn count_files_from_id(id: u32) ->Option<usize>{ + ROOT_INODE.count_files_from_id(id) +} + impl File for OSInode { fn readable(&self) -> bool { self.readable } fn writable(&self) -> bool { self.writable } + fn inode_id(&self) -> Option<u32> { self.get_my_inode_id() } fn read(&self, mut buf: UserBuffer) -> usize { let mut inner = self.inner.lock(); let mut total_read_size = 0usize; diff --git a/os/src/fs/mail.rs b/os/src/fs/mail.rs new file mode 100644 index 0000000000000000000000000000000000000000..5a615e1530f75ef5e5ca991b6fbd337cf251d5b8 --- /dev/null +++ b/os/src/fs/mail.rs @@ -0,0 +1,252 @@ +//æ ¹æ®æµ‹ä¾‹å¯ä»¥çŸ¥é“,事实上mailè¦åšçš„事情就是从缓冲区读写,然åŽå˜åˆ°è¿›ç¨‹çš„mailç¼“å†²é‡Œé¢ +//为了实现进程之间通信,还是离ä¸å¼€ç”¨æˆ·ç¨‹åºè‡ªå·±çš„æŽ§åˆ¶å‘€ +use alloc::collections::VecDeque; +use super::File; +use alloc::sync::{Arc, Weak}; +use spin::Mutex; +use crate::mm::{ + UserBuffer, +}; +use crate::config::MAIL_SIZE; + +#[derive(Copy,Clone,PartialEq)] +pub struct Mail{ + fd_read: usize, + // fd_write: usize, +} + +impl Mail{ + pub fn new(read_end:usize)->Self{ + Self{ + fd_read: read_end, + // fd_write: write_end, + } + } + pub fn get_read_fd(&self)->usize{ + self.fd_read + } +} + +const MAIL_NUMBER_LIMIT:usize = 16; + +#[derive(Copy, Clone, PartialEq)] +enum MailBoxStatus { + FULL, + EMPTY, + NORMAL, +} + +pub struct MailBox{ + mails: VecDeque<Mail>, + limit: usize, + status: MailBoxStatus, +} + +impl MailBox{ + pub fn new() ->Self{ + Self{ + mails:VecDeque::new(),//åˆå§‹åŒ–为空 + limit: MAIL_NUMBER_LIMIT, + status: MailBoxStatus::EMPTY, + } + } + pub fn can_add_mail(&self)->bool{ + self.status != MailBoxStatus::FULL + } + pub fn can_read_mail(&self)->bool{ + self.status != MailBoxStatus::EMPTY + } + pub fn add_mail(&mut self,mail:Mail)->usize{ + if self.status==MailBoxStatus::FULL{ + return 0; + } + self.mails.push_back(mail); + if self.mails.len()>=self.limit{ + self.status=MailBoxStatus::FULL; + } + self.mails.len() + } + //VecDeque自己就会返回一个Option类型,所以这里函数的返回值使用Option类就å¯ä»¥ç±» + pub fn get_mail(&mut self)->Option<Mail>{ + let m = self.mails.pop_front(); + if self.mails.len() < self.limit{ + self.status=MailBoxStatus::NORMAL; + } + if self.mails.len() == 0{ + self.status=MailBoxStatus::EMPTY; + } + m + } +} +//===================================================================================== + +//比如说我è¦åˆ›å»ºä¸€ä¸ªMPipe,其实就是新建一个MPipeBuffer, +//ç„¶åŽè¯»ç«¯å’Œå†™ç«¯éƒ½åŒ…装æˆä¸€ä¸ªMPipe,用æ¥å’Œè¿›ç¨‹ä¹‹é—´äº¤äº’ + +pub struct MPipe { + readable: bool, + writable: bool, + buffer: Arc<Mutex<MPipeRingBuffer>>, +} + +impl MPipe { + pub fn read_end_with_buffer(buffer: Arc<Mutex<MPipeRingBuffer>>) -> Self { + Self { + readable: true, + writable: false, + buffer, + } + } + pub fn write_end_with_buffer(buffer: Arc<Mutex<MPipeRingBuffer>>) -> Self { + Self { + readable: false, + writable: true, + buffer, + } + } +} + +// const RING_BUFFER_SIZE: usize = 32; +// const RING_BUFFER_SIZE: usize = 256; +const RING_BUFFER_SIZE: usize = MAIL_SIZE; + +#[derive(Copy, Clone, PartialEq)] +enum RingBufferStatus { + FULL, + EMPTY, + NORMAL, +} + +pub struct MPipeRingBuffer { + arr: [u8; RING_BUFFER_SIZE], + head: usize, + tail: usize, + status: RingBufferStatus, + write_end: Option<Weak<MPipe>>, + //一个MPipebufferè¦çŸ¥é“è°åœ¨å†™å®ƒ +} + +impl MPipeRingBuffer { + pub fn new() -> Self { + Self { + arr: [0; RING_BUFFER_SIZE], + head: 0, + tail: 0, + status: RingBufferStatus::EMPTY, + write_end: None, + } + } + pub fn set_write_end(&mut self, write_end: &Arc<MPipe>) { + self.write_end = Some(Arc::downgrade(write_end)); + } + pub fn write_byte(&mut self, byte: u8) { + self.status = RingBufferStatus::NORMAL; + self.arr[self.tail] = byte; + self.tail = (self.tail + 1) % RING_BUFFER_SIZE; + if self.tail == self.head { + self.status = RingBufferStatus::FULL; + } + } + pub fn read_byte(&mut self) -> u8 { + self.status = RingBufferStatus::NORMAL; + let c = self.arr[self.head]; + self.head = (self.head + 1) % RING_BUFFER_SIZE; + if self.head == self.tail { + self.status = RingBufferStatus::EMPTY; + } + c + } + pub fn available_read(&self) -> usize { + if self.status == RingBufferStatus::EMPTY { + 0 + } else { + if self.tail > self.head { + self.tail - self.head + } else { + self.tail + RING_BUFFER_SIZE - self.head + } + } + } + pub fn available_write(&self) -> usize { + if self.status == RingBufferStatus::FULL { + 0 + } else { + RING_BUFFER_SIZE - self.available_read() + } + } + pub fn all_write_ends_closed(&self) -> bool { + self.write_end.as_ref().unwrap().upgrade().is_none() + } +} + +/// Return (read_end, write_end) +pub fn make_mpipe() -> (Arc<MPipe>, Arc<MPipe>) { + let buffer = Arc::new(Mutex::new(MPipeRingBuffer::new())); + let read_end = Arc::new( + MPipe::read_end_with_buffer(buffer.clone()) + ); + let write_end = Arc::new( + MPipe::write_end_with_buffer(buffer.clone()) + ); + buffer.lock().set_write_end(&write_end); + (read_end, write_end) +} + +impl File for MPipe { + fn readable(&self) -> bool { self.readable } + fn writable(&self) -> bool { self.writable } + fn inode_id(&self) -> Option<u32> { None } + fn read(&self, buf: UserBuffer) -> usize { + assert_eq!(self.readable, true); + let mut buf_iter = buf.into_iter(); + let mut read_size = 0usize; + loop { + let mut ring_buffer = self.buffer.lock(); + let loop_read = ring_buffer.available_read(); + debug!("MPipe::avalable_read is {}",loop_read); + if loop_read == 0 { + if ring_buffer.all_write_ends_closed() { + return read_size; + } + warn!("MPipe::still have bytes..."); + // suspend_current_and_run_next(); + // break; + return loop_read; + } + // read at most loop_read bytes + for _ in 0..loop_read { + if let Some(byte_ref) = buf_iter.next() { + unsafe { *byte_ref = ring_buffer.read_byte(); } + read_size += 1; + } else { + return read_size; + } + } + } + } + fn write(&self, buf: UserBuffer) -> usize { + assert_eq!(self.writable, true); + let mut buf_iter = buf.into_iter(); + let mut write_size = 0usize; + loop { + let mut ring_buffer = self.buffer.lock(); + let loop_write = ring_buffer.available_write(); + if loop_write == 0 { + drop(ring_buffer); + // warn!("MPipe::no space..."); + // suspend_current_and_run_next(); + // break; + return loop_write; + } + // write at most loop_write bytes + for _ in 0..loop_write { + if let Some(byte_ref) = buf_iter.next() { + ring_buffer.write_byte(unsafe { *byte_ref }); + write_size += 1; + } else { + return write_size; + } + } + } + } +} \ No newline at end of file diff --git a/os/src/fs/mod.rs b/os/src/fs/mod.rs index c015702d2dc2f20c013ebf46afa8776329b2f450..525df12cc63122dae5e493ca85cb961f53640e44 100644 --- a/os/src/fs/mod.rs +++ b/os/src/fs/mod.rs @@ -1,16 +1,24 @@ mod pipe; mod stdio; mod inode; +mod mail; use crate::mm::UserBuffer; pub trait File : Send + Sync { fn readable(&self) -> bool; fn writable(&self) -> bool; + fn inode_id(&self) -> Option<u32>; fn read(&self, buf: UserBuffer) -> usize; fn write(&self, buf: UserBuffer) -> usize; } pub use pipe::{Pipe, make_pipe}; pub use stdio::{Stdin, Stdout}; -pub use inode::{OSInode, open_file, OpenFlags, list_apps}; \ No newline at end of file +pub use inode::{ + OSInode, open_file, OpenFlags, list_apps, + get_inode_id, + create_linker,delete_linker,count_files, + count_files_from_id, +}; +pub use mail::{Mail,MailBox,MPipe,make_mpipe}; diff --git a/os/src/fs/pipe.rs b/os/src/fs/pipe.rs index 1027b472b09870f6f40ba6ed030a749d951192a4..2350436535d7dda4a8c88701ade49fcf58d7a142 100644 --- a/os/src/fs/pipe.rs +++ b/os/src/fs/pipe.rs @@ -5,6 +5,10 @@ use crate::mm::{ UserBuffer, }; use crate::task::suspend_current_and_run_next; +use crate::config::MAIL_SIZE; + +//比如说我è¦åˆ›å»ºä¸€ä¸ªPipe,其实就是新建一个PipeBuffer, +//ç„¶åŽè¯»ç«¯å’Œå†™ç«¯éƒ½åŒ…装æˆä¸€ä¸ªPipe,用æ¥å’Œè¿›ç¨‹ä¹‹é—´äº¤äº’ pub struct Pipe { readable: bool, @@ -29,7 +33,9 @@ impl Pipe { } } -const RING_BUFFER_SIZE: usize = 32; +// const RING_BUFFER_SIZE: usize = 32; +// const RING_BUFFER_SIZE: usize = 256; +const RING_BUFFER_SIZE: usize = MAIL_SIZE; #[derive(Copy, Clone, PartialEq)] enum RingBufferStatus { @@ -44,6 +50,7 @@ pub struct PipeRingBuffer { tail: usize, status: RingBufferStatus, write_end: Option<Weak<Pipe>>, + //一个pipebufferè¦çŸ¥é“è°åœ¨å†™å®ƒ } impl PipeRingBuffer { @@ -115,6 +122,7 @@ pub fn make_pipe() -> (Arc<Pipe>, Arc<Pipe>) { impl File for Pipe { fn readable(&self) -> bool { self.readable } fn writable(&self) -> bool { self.writable } + fn inode_id(&self) -> Option<u32> { None } fn read(&self, buf: UserBuffer) -> usize { assert_eq!(self.readable(), true); let mut buf_iter = buf.into_iter(); @@ -150,6 +158,7 @@ impl File for Pipe { let loop_write = ring_buffer.available_write(); if loop_write == 0 { drop(ring_buffer); + // warn!("Pipe::write, may cause dead lock..."); suspend_current_and_run_next(); continue; } diff --git a/os/src/fs/stdio.rs b/os/src/fs/stdio.rs index e8df79508f4a15bc7d86a3e5b7e279d0a39eac60..f3358ac76f0737e7c28bc80ea1db0f19fa782d8e 100644 --- a/os/src/fs/stdio.rs +++ b/os/src/fs/stdio.rs @@ -10,6 +10,7 @@ pub struct Stdout; impl File for Stdin { fn readable(&self) -> bool { true } fn writable(&self) -> bool { false } + fn inode_id(&self) -> Option<u32> { None } fn read(&self, mut user_buf: UserBuffer) -> usize { assert_eq!(user_buf.len(), 1); // busy loop @@ -35,6 +36,7 @@ impl File for Stdin { impl File for Stdout { fn readable(&self) -> bool { false } fn writable(&self) -> bool { true } + fn inode_id(&self) -> Option<u32> { None } fn read(&self, _user_buf: UserBuffer) -> usize{ panic!("Cannot read from stdout!"); } diff --git a/os/src/lang_items.rs b/os/src/lang_items.rs index 3f5462abbb720703adcc9ed8cc7aa1f8a07c61f3..619f4f5f436f5929c61b22c549c4ec8d9db66382 100644 --- a/os/src/lang_items.rs +++ b/os/src/lang_items.rs @@ -1,5 +1,5 @@ -use core::panic::PanicInfo; use crate::sbi::shutdown; +use core::panic::PanicInfo; #[panic_handler] fn panic(info: &PanicInfo) -> ! { diff --git a/os/src/linker-k210.ld b/os/src/linker-k210.ld index 4f9d2171fc557ee4d75e0ab6b4e2fe54b61aca36..eaa2c9ff1edbed9dea1d370dbf35054a6a2bd332 100644 --- a/os/src/linker-k210.ld +++ b/os/src/linker-k210.ld @@ -22,6 +22,7 @@ SECTIONS srodata = .; .rodata : { *(.rodata .rodata.*) + *(.srodata .srodata.*) } . = ALIGN(4K); @@ -29,6 +30,7 @@ SECTIONS sdata = .; .data : { *(.data .data.*) + *(.sdata .sdata.*) } . = ALIGN(4K); @@ -38,6 +40,7 @@ SECTIONS *(.bss.stack) sbss = .; *(.bss .bss.*) + *(.sbss .sbss.*) } . = ALIGN(4K); diff --git a/os/src/linker-qemu.ld b/os/src/linker-qemu.ld index 6b06e91646cee37c333ada71b3fc84172402f67a..5baafbd0a8bde097a69c458473520beca283b2f3 100644 --- a/os/src/linker-qemu.ld +++ b/os/src/linker-qemu.ld @@ -22,6 +22,7 @@ SECTIONS srodata = .; .rodata : { *(.rodata .rodata.*) + *(.srodata .srodata.*) } . = ALIGN(4K); @@ -29,6 +30,7 @@ SECTIONS sdata = .; .data : { *(.data .data.*) + *(.sdata .sdata.*) } . = ALIGN(4K); @@ -38,6 +40,7 @@ SECTIONS *(.bss.stack) sbss = .; *(.bss .bss.*) + *(.sbss .sbss.*) } . = ALIGN(4K); diff --git a/os/src/main.rs b/os/src/main.rs index e9a34bb8578dc78cbb951b2ef0d92a0d3744ccea..06308f66fbe42b2d6803d86bc5bbf9743e541188 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -31,15 +31,14 @@ fn clear_bss() { fn sbss(); fn ebss(); } - (sbss as usize..ebss as usize).for_each(|a| { - unsafe { (a as *mut u8).write_volatile(0) } - }); + (sbss as usize..ebss as usize).for_each(|a| unsafe { (a as *mut u8).write_volatile(0) }); } #[no_mangle] pub fn rust_main() -> ! { clear_bss(); - println!("[kernel] Hello, world!"); + kernel_println!("Hello, world!"); + //åˆ†é¡µæ¨¡å¼æ˜¯åœ¨å†…æ ¸åˆå§‹åŒ–期间开å¯çš„,也就是说现在已ç»å¼€å¯åˆ†é¡µæ¨¡å¼äº†ï¼ mm::init(); mm::remap_test(); trap::init(); @@ -49,4 +48,4 @@ pub fn rust_main() -> ! { task::add_initproc(); task::run_tasks(); panic!("Unreachable in rust_main!"); -} \ No newline at end of file +} diff --git a/os/src/mm/address.rs b/os/src/mm/address.rs index d5828ed275727c3ac1557471f30d0f45696feaba..a0e0ea94d4a7a5597b95993d93712cc779d0e7bb 100644 --- a/os/src/mm/address.rs +++ b/os/src/mm/address.rs @@ -86,6 +86,8 @@ impl From<VirtAddr> for VirtPageNum { impl From<VirtPageNum> for VirtAddr { fn from(v: VirtPageNum) -> Self { Self(v.0 << PAGE_SIZE_BITS) } } + +// 物ç†åœ°å€å®žçŽ°çš„åŠŸèƒ½æ˜¯ï¼šç»™å‡ºç‰©ç†åœ°å€å¯ä»¥è¿”回物ç†é¡µå· impl PhysAddr { pub fn floor(&self) -> PhysPageNum { PhysPageNum(self.0 / PAGE_SIZE) } pub fn ceil(&self) -> PhysPageNum { PhysPageNum((self.0 - 1 + PAGE_SIZE) / PAGE_SIZE) } @@ -159,6 +161,8 @@ impl StepByOne for PhysPageNum { } } +//æ ¹æ®ä»£ç å¯ä»¥çœ‹å‡ºï¼Œè¿™æ˜¯ä¸€ä¸ªå·¦é—å³å¼€åŒºé—´ +//[start,end] #[derive(Copy, Clone)] pub struct SimpleRange<T> where T: StepByOne + Copy + PartialEq + PartialOrd + Debug, { diff --git a/os/src/mm/frame_allocator.rs b/os/src/mm/frame_allocator.rs index 2cb6427bf0bb99701325b2996dd2e41a2bd9ddbe..5068cc8a52f3dab50f5ec2232da2c06b97fcd306 100644 --- a/os/src/mm/frame_allocator.rs +++ b/os/src/mm/frame_allocator.rs @@ -36,8 +36,10 @@ trait FrameAllocator { fn new() -> Self; fn alloc(&mut self) -> Option<PhysPageNum>; fn dealloc(&mut self, ppn: PhysPageNum); + fn frame_left(&self)->usize; } +//[current,end)å·¦é—å³å¼€åŒºé—´è¡¨ç¤ºè¿˜æœ‰å¤šå°‘个frameæœªåˆ†é… pub struct StackFrameAllocator { current: usize, end: usize, @@ -61,12 +63,14 @@ impl FrameAllocator for StackFrameAllocator { } fn alloc(&mut self) -> Option<PhysPageNum> { if let Some(ppn) = self.recycled.pop() { + trace!("alloc...{} pages left...",self.frame_left()); Some(ppn.into()) } else { if self.current == self.end { None } else { self.current += 1; + trace!("alloc...{} pages left...",self.frame_left()); Some((self.current - 1).into()) } } @@ -83,8 +87,15 @@ impl FrameAllocator for StackFrameAllocator { // recycle self.recycled.push(ppn); } + fn frame_left(&self) -> usize { + return self.end - self.current + self.recycled.len(); + } } +// impl StackFrameAllocator { + +// } + type FrameAllocatorImpl = StackFrameAllocator; lazy_static! { @@ -101,11 +112,19 @@ pub fn init_frame_allocator() { .init(PhysAddr::from(ekernel as usize).ceil(), PhysAddr::from(MEMORY_END).floor()); } +//问题:这个ppn是哪æ¥çš„? pub fn frame_alloc() -> Option<FrameTracker> { FRAME_ALLOCATOR .lock() .alloc() .map(|ppn| FrameTracker::new(ppn)) + //至于map哪个ppnï¼Œæ˜¯åˆ†é…æ–¹æ³•决定的,就ä¸éœ€è¦æˆ‘们管了 + //返回的是一个物ç†é¡µå¸§ +} + +//å‘å…¶ä»–æ¨¡å—æä¾›public接å£ï¼ŒçŸ¥é“现在还有多少个物ç†é¡µå¸§å¯ä»¥åˆ†é… +pub fn frame_left() -> usize{ + FRAME_ALLOCATOR.lock().frame_left() } pub fn frame_dealloc(ppn: PhysPageNum) { @@ -118,7 +137,7 @@ pub fn frame_dealloc(ppn: PhysPageNum) { pub fn frame_allocator_test() { let mut v: Vec<FrameTracker> = Vec::new(); for i in 0..5 { - let frame = frame_alloc().unwrap(); + let frame = frame_alloc().unwrap();//使用frame_alloc函数å¯ä»¥å¾—到一个物ç†é¡µå¸§ println!("{:?}", frame); v.push(frame); } diff --git a/os/src/mm/heap_allocator.rs b/os/src/mm/heap_allocator.rs index 2c7468f2c12c0aba1090855297d524209b0e73ce..9132c33fa128df8d4b4dfb8a45a45b14312b49ba 100644 --- a/os/src/mm/heap_allocator.rs +++ b/os/src/mm/heap_allocator.rs @@ -11,6 +11,8 @@ pub fn handle_alloc_error(layout: core::alloc::Layout) -> ! { static mut HEAP_SPACE: [u8; KERNEL_HEAP_SIZE] = [0; KERNEL_HEAP_SIZE]; + +//我的ç†è§£æ˜¯ï¼Œç”¨æ‰€æœ‰çš„程åºä¸€å…±åªæœ‰è¿™ä¹ˆå¤šç©ºé—´èƒ½åˆ†å‡ºåŽ»ã€‚ pub fn init_heap() { unsafe { HEAP_ALLOCATOR diff --git a/os/src/mm/memory_set.rs b/os/src/mm/memory_set.rs index b3a8b2e4927b0ef60dbb6fbdbea57d997cf928bd..ba9ad1f39546e6ed158f8919896527fc79d9e34c 100644 --- a/os/src/mm/memory_set.rs +++ b/os/src/mm/memory_set.rs @@ -1,6 +1,6 @@ use super::{PageTable, PageTableEntry, PTEFlags}; use super::{VirtPageNum, VirtAddr, PhysPageNum, PhysAddr}; -use super::{FrameTracker, frame_alloc}; +use super::{FrameTracker, frame_alloc, frame_left}; use super::{VPNRange, StepByOne}; use alloc::collections::BTreeMap; use alloc::vec::Vec; @@ -11,6 +11,7 @@ use spin::Mutex; use crate::config::{ MEMORY_END, PAGE_SIZE, + PAGE_SIZE_BITS, TRAMPOLINE, TRAP_CONTEXT, USER_STACK_SIZE, @@ -30,6 +31,9 @@ extern "C" { fn strampoline(); } +//KERNEL_SPACE是æ¯ä¸€ä¸ªapp有一份的 +//但是问题æ¥äº†ï¼šæ€Žä¹ˆå–得特定的appçš„KERNEL_SPACE? +//在进程控制å—里é¢ï¼Œæ¯ä¸€ä¸ªè¿›ç¨‹éƒ½æœ‰ä¸€ä¸ªå¯¹åº”çš„KERNEL_SPACE lazy_static! { pub static ref KERNEL_SPACE: Arc<Mutex<MemorySet>> = Arc::new(Mutex::new( MemorySet::new_kernel() @@ -45,6 +49,19 @@ pub struct MemorySet { areas: Vec<MapArea>, } +fn convert_usize_to_permission(port: usize)->Option<MapPermission>{ + match port{ + 1 => Some(MapPermission::R), + 2 => Some(MapPermission::W), + 3 => Some(MapPermission::R | MapPermission::W), + 4 => Some(MapPermission::X), + 5 => Some(MapPermission::X | MapPermission::R), + 6 => Some(MapPermission::X | MapPermission::W), + 7 => Some(MapPermission::X | MapPermission::W | MapPermission::R), + _ => None + } +} + impl MemorySet { pub fn new_bare() -> Self { Self { @@ -55,7 +72,9 @@ impl MemorySet { pub fn token(&self) -> usize { self.page_table.token() } - /// Assume that no conflicts. + + /// å‡è®¾å·²ç»åˆ†é…好了物ç†é¡µé¢ï¼Œå»ºç«‹ä¸€ä¸ªå¯¹åº”关系 + /// 这个函数åªèƒ½åœ¨å·²ç»ç”³è¯·å®Œç©ºé—´æ‰èƒ½è°ƒç”¨ pub fn insert_framed_area(&mut self, start_va: VirtAddr, end_va: VirtAddr, permission: MapPermission) { self.push(MapArea::new( start_va, @@ -199,19 +218,26 @@ impl MemorySet { ), None); (memory_set, user_stack_top, elf.header.pt2.entry_point() as usize) } + // pub fn from_existed_user(user_space: &MemorySet) -> MemorySet { + //先创建一个空的地å€ç©ºé—´ let mut memory_set = Self::new_bare(); // map trampoline + //æ˜ å°„è·³è½¬é¡µé¢ï¼ˆï¼Ÿï¼Ÿï¼Ÿå…¶å®žä¸Šä¸€ä¸ªå®žéªŒæˆ‘就没有太ç†è§£ä»€ä¹ˆæ˜¯è·³æ¿é¡µé¢ï¼Œä¸è¿‡çœ‹èµ·æ¥æš‚æ—¶ä¸æ˜¯éžå¸¸å½±å“哦 memory_set.map_trampoline(); // copy data sections/trap_context/user_stack for area in user_space.areas.iter() { let new_area = MapArea::from_another(area); + //先把别人的areaå¤åˆ¶è¿‡æ¥ + //放进memory_seté‡Œé¢ + //注æ„,这里push进去的时候其实就调用了areaçš„map,就已ç»åˆ†é…了物ç†é¡µå¸§ memory_set.push(new_area, None); // copy data from another space for vpn in area.vpn_range { let src_ppn = user_space.translate(vpn).unwrap().ppn(); let dst_ppn = memory_set.translate(vpn).unwrap().ppn(); dst_ppn.get_bytes_array().copy_from_slice(src_ppn.get_bytes_array()); + //所以这里就是å¯ä»¥ç›´æŽ¥å¤åˆ¶æ•°æ®çš„ï¼ } } memory_set @@ -230,6 +256,120 @@ impl MemorySet { //*self = Self::new_bare(); self.areas.clear(); } + + pub fn v2p(&self,va:VirtAddr)->Option<PhysAddr>{ + let vpn = va.floor(); + let page_offset = va.page_offset(); + // let pte = self.translate(vpn); + if let Some(pte) = self.translate(vpn){ + return Some(PhysAddr(((usize::from(pte.ppn())<< PAGE_SIZE_BITS) + page_offset) as usize)); + } + return None; + } + + pub fn unmap_the_chosen_area(&mut self,range: VPNRange)->isize{ + for area in &mut self.areas{ + let size = area.unmap_the_chosen_area(&mut self.page_table,range) as isize; + if size != -1 { + return size; + } + } + return -1 as isize; + } + + pub fn mmap(&mut self,start: usize, len: usize, port: usize) -> isize{ + //è¦æ£€æŸ¥çš„内容: + //1. 物ç†å†…å˜è¿˜å¤Ÿç”¨å— + //2. 这个地å€èŒƒå›´å†…æ˜¯ä¸æ˜¯æœ‰å“ªäº›å·²ç»è¢«æ˜ 射过了 + + if start % PAGE_SIZE != 0 { + return -1 as isize; + } + if len == 0 { + // warn!("in mmap...number=0"); + return 0 as isize; + } + let number = ((len - 1 + PAGE_SIZE) /PAGE_SIZE )as usize; + //å‘ä¸Šå–æ•´,è¡¨ç¤ºä¼šç”¨åˆ°å‡ ä¸ªpage + + //ä»¥é˜²ä¸‡ä¸€ï¼Œå†æ£€æŸ¥ä¸€é读写æƒé™é—®é¢˜ + if (port & !0x7 != 0)||(port & 0x7 == 0) { + return -1 as isize; + } + + //æ£€æŸ¥ä¸€ä¸‹çŽ°åœ¨è¿˜æœ‰å‡ ä¸ªpageï¼Œæ˜¯ä¸æ˜¯å¤Ÿç”¨.done + if frame_left() < number { + return -1 as isize; + } + + let permission = convert_usize_to_permission(port); + match permission{ + Some(MapPermission) => {}, + None => return -1 as isize, + } + + //这个地å€èŒƒå›´æ˜¯ä¸æ˜¯æœ‰äººå·²ç»æ˜ 射过了? + //æ ¹æ®ä»£ç ,调用translate检查å³å¯ + //mmap给分é…的空间都是在用户æ€ä¸‹ä½¿ç”¨çš„ï¼Œå› æ¤å¯ä»¥ç»™Uæƒé™å“¦ + let mut area = MapArea::new((start).into(), + (start+len).into(), + MapType::Framed, + permission.unwrap() | MapPermission::U); + + //调用translate,检查是å¦å…¨éƒ¨èƒ½å®Œæˆæ˜ å°„ + if area.not_map_check(&self.page_table)==false { + // warn!("[kernel] have mapped!"); + return -1 as isize; + } + + area.map(&mut self.page_table); + + let size = usize::from(area.vpn_range.get_end()) - usize::from(area.vpn_range.get_start()); + + self.areas.push(area); + + //ä»¥ä¸Šåˆæ³•性检查结æŸä¹‹åŽï¼Œå¯ä»¥ç›´æŽ¥åˆ†é…。分为2æ¥ï¼š + //1,申请物ç†é¡µé¢ï¼ˆæ€Žä¹ˆç”³è¯·ï¼Ÿç”³è¯·å®Œç»™è°ï¼Ÿï¼‰ + // 这里ä¸ç”¨æ‰‹åŠ¨å†™ï¼Œå› ä¸ºåœ¨map的代ç 里é¢å·²ç»è°ƒç”¨äº†åˆ†é…物ç†é¡µå¸§çš„函数 + + //问题:现在的困难在于,æ¯ä¸€ä¸ªä¸åŒçš„进程都会有ä¸åŒçš„æ˜ 射规则。 + //我在这里怎么访问“当å‰è¿›ç¨‹ä¸‹çš„。。。。â€å‘¢ï¼ŒKERNELSPACEå¥½åƒæ˜¯ä¸€ä¸ªä¸åŒè¿›ç¨‹ä¸‹çš„东西 + // debug!("[kernel] in mmap...size alloc is {},{}",number,size); + assert_eq!(number, size); + // debug!("[kernel] in mmap...size alloc is {}",size); + + return (size*PAGE_SIZE) as isize; + } + + /// 接å£ï¼šfn unmmap(start: usize, len: usize) -> isize + /// 在系统调用处已ç»è¿›è¡Œäº†æ•°æ®åˆæ³•æ€§æ£€æŸ¥ï¼Œå› æ¤åœ¨è¿™é‡Œå¯ä»¥ç›´æŽ¥è¿›è¡Œåˆ†é… + /// startï¼šå¼€å§‹åœ°å€ + /// number:è¦åˆ†é…å‡ ä¸ªpage + pub fn munmap(&mut self,start: usize, len: usize) -> isize{ + //è¦æ£€æŸ¥çš„内容: + //1. 物ç†å†…å˜è¿˜å¤Ÿç”¨å— + //2. 这个地å€èŒƒå›´å†…æ˜¯ä¸æ˜¯æœ‰å“ªäº›å·²ç»è¢«æ˜ 射过了 + + if start % PAGE_SIZE != 0 { + return -1 as isize; + } + if len == 0 { + // warn!("in mmap...number=0"); + return 0 as isize; + } + + let start_va: VirtAddr = start.into(); + let end_va: VirtAddr = (start+len).into(); + let start_vpn: VirtPageNum = start_va.floor(); + let end_vpn: VirtPageNum = end_va.ceil(); + + //è¿™æ˜¯è¢«æ˜ å°„è¿‡åŽ»çš„maparea里é¢çš„地å€èŒƒå›´ + let range = VPNRange::new(start_vpn, end_vpn); + + return self.unmap_the_chosen_area(range); + // return -1 as isize; + } + } pub struct MapArea { @@ -238,7 +378,7 @@ pub struct MapArea { map_type: MapType, map_perm: MapPermission, } - +//按照规则,一次åªèƒ½åˆ†é…整数个page impl MapArea { pub fn new( start_va: VirtAddr, @@ -269,6 +409,7 @@ impl MapArea { MapType::Identical => { ppn = PhysPageNum(vpn.0); } + //ç»å¸¸ä¼šé‡åˆ°ç‰©ç†å†…å˜ä¸è¶³çš„问题啊 MapType::Framed => { let frame = frame_alloc().unwrap(); ppn = frame.ppn; @@ -319,6 +460,60 @@ impl MapArea { current_vpn.step(); } } + //print range + pub fn print_range(&self) { + debug!("[kernel] MapArea::range ({:#x},{:#x})", + usize::from(self.vpn_range.get_start()), + usize::from(self.vpn_range.get_end()) + ); + } + //check if has mapped... + //找到问题了ï¼è¿™é‡Œä¸æ˜¯åº”该寻找kernel space的页表 + //而是寻找当å‰çš„é¡µè¡¨æ˜¯å¦æœ‰æ˜ 射。。。 + pub fn not_map_check(&self,page_table: &PageTable)-> bool{ + for vpn in self.vpn_range{ + if let Some(pte) = page_table.translate(vpn){ + if pte.is_valid(){ + // warn!("[kernel] vpn have mapped is {:#x}",usize::from(pte.ppn())); + return false + } + } + } + return true; + } + //check if not mapped... + pub fn have_mapped_check(&self,page_table: &PageTable)-> bool{ + self.print_range(); + for vpn in self.vpn_range{ + if let Some(pte) = page_table.translate(vpn){ + if !pte.is_valid(){ + // warn!("[kernel] vpn not mapped is {:#x}",usize::from(pte.ppn())); + return false + } + } + } + return true; + } + pub fn match_area_with_vpnrange(&self, range: VPNRange)->bool{ + if (self.vpn_range.get_start() == range.get_start()) && (self.vpn_range.get_end() == range.get_end()){ + true + }else{ + false + } + } + pub fn unmap_the_chosen_area(&mut self,page_table: &mut PageTable,range: VPNRange)->isize{ + if self.match_area_with_vpnrange(range){ + if !self.have_mapped_check(page_table){ + //如果å‘现有还没有map过的页表项想è¦unmap + // warn!("[kernel] vpn not mapped yet "); + return -1 as isize; + } + self.unmap(page_table); + let size = usize::from(range.get_end()) - usize::from(range.get_start()); + return size as isize; + } + return -1 as isize; + } } #[derive(Copy, Clone, PartialEq, Debug)] @@ -327,6 +522,8 @@ pub enum MapType { Framed, } +//done:在MapArea这里,è¦ç»™PermissionåŠ ä¸ŠUæƒé™å•Š + bitflags! { pub struct MapPermission: u8 { const R = 1 << 1; @@ -354,5 +551,6 @@ pub fn remap_test() { kernel_space.page_table.translate(mid_data.floor()).unwrap().executable(), false, ); + // kernel_space.insert_framed_area(); println!("remap_test passed!"); } \ No newline at end of file diff --git a/os/src/mm/mod.rs b/os/src/mm/mod.rs index dbd47fe798f177a599d9ec7272d23e3e35f17fee..3f07670595456879cfb4d0774cf465832b57a7ec 100644 --- a/os/src/mm/mod.rs +++ b/os/src/mm/mod.rs @@ -4,12 +4,21 @@ mod frame_allocator; mod page_table; mod memory_set; -use page_table::PTEFlags; -use address::VPNRange; -pub use address::{PhysAddr, VirtAddr, PhysPageNum, VirtPageNum, StepByOne}; -pub use frame_allocator::{FrameTracker, frame_alloc, frame_dealloc,}; + +pub use address::{PhysAddr, VirtAddr,VPNRange, PhysPageNum, VirtPageNum, StepByOne}; +// use crate::config::{ +// PAGE_SIZE, +// }; + +pub use frame_allocator::{ + FrameTracker, + frame_alloc, + frame_dealloc, + frame_left, +}; pub use page_table::{ PageTable, + PTEFlags, PageTableEntry, translated_byte_buffer, translated_str, @@ -17,12 +26,19 @@ pub use page_table::{ translated_refmut, UserBuffer, UserBufferIterator, + check_byte_buffer_valid, +}; + +pub use memory_set::{MemorySet, KERNEL_SPACE, MapPermission}; +pub use memory_set::{ + remap_test, + kernel_token, + // mmap, + // munmap, }; -pub use memory_set::{MemorySet, KERNEL_SPACE, MapPermission, kernel_token}; -pub use memory_set::remap_test; pub fn init() { heap_allocator::init_heap(); frame_allocator::init_frame_allocator(); KERNEL_SPACE.lock().activate(); -} \ No newline at end of file +} diff --git a/os/src/mm/page_table.rs b/os/src/mm/page_table.rs index b1a227fa11c632cbdccfc9c6245f9bb99f86befd..2140068a67cc7233b298a8ab49ea57246f789ee0 100644 --- a/os/src/mm/page_table.rs +++ b/os/src/mm/page_table.rs @@ -12,6 +12,7 @@ use alloc::vec; use alloc::string::String; use bitflags::*; +//物ç†é¡µçš„æ ‡å¿— bitflags! { pub struct PTEFlags: u8 { const V = 1 << 0; @@ -45,7 +46,7 @@ impl PageTableEntry { pub fn ppn(&self) -> PhysPageNum { (self.bits >> 10 & ((1usize << 44) - 1)).into() } - pub fn flags(&self) -> PTEFlags { + pub fn flags(&self) -> PTEFlags {//页表的低8使˜¯flags PTEFlags::from_bits(self.bits as u8).unwrap() } pub fn is_valid(&self) -> bool { @@ -83,27 +84,35 @@ impl PageTable { frames: Vec::new(), } } + ///PageTable::find_pte_create 在多级页表找到一个虚拟页å·å¯¹åº”的页表项的å¯å˜å¼•用方便åŽç»çš„读写。 + /// 如果在 é历的过程ä¸å‘现有节点尚未创建则会新建一个节点。 + /// 注æ„在更新页表项的时候,ä¸ä»…è¦æ›´æ–°ç‰©ç†é¡µå·ï¼Œè¿˜è¦å°†æ ‡å¿—ä½ V ç½® 1, + /// ä¸ç„¶ç¡¬ä»¶åœ¨æŸ¥å¤šçº§é¡µè¡¨çš„æ—¶å€™ï¼Œä¼šè®¤ä¸ºè¿™ä¸ªé¡µè¡¨é¡¹ä¸åˆæ³•ï¼Œä»Žè€Œè§¦å‘ Page Fault 而ä¸èƒ½å‘下走。 fn find_pte_create(&mut self, vpn: VirtPageNum) -> Option<&mut PageTableEntry> { + trace!("Pagetable::find_pte_create...token is {:#x}, vpn is {:#x}", self.token(), usize::from(vpn)); let idxs = vpn.indexes(); let mut ppn = self.root_ppn; let mut result: Option<&mut PageTableEntry> = None; for i in 0..3 { + // debug!("i is {}",i); let pte = &mut ppn.get_pte_array()[idxs[i]]; if i == 2 { result = Some(pte); break; } - if !pte.is_valid() { + if !pte.is_valid() {//如果é历的过程ä¸å‘现有页表ä¸å˜åœ¨ï¼Œé‚£ä¹ˆå°±åˆ›å»ºå®ƒ let frame = frame_alloc().unwrap(); *pte = PageTableEntry::new(frame.ppn, PTEFlags::V); self.frames.push(frame); } ppn = pte.ppn(); } + // debug!("resule is..."); result } + //这个函数的功能是给出虚拟地å€ï¼Œç„¶åŽæ‰¾åˆ°å…¶ç‰©ç†åœ°å€ fn find_pte(&self, vpn: VirtPageNum) -> Option<&PageTableEntry> { - let idxs = vpn.indexes(); + let idxs = vpn.indexes();//说明了在页表ä¸å¯»æ‰¾æ˜ 射的方法 let mut ppn = self.root_ppn; let mut result: Option<&PageTableEntry> = None; for i in 0..3 { @@ -113,24 +122,35 @@ impl PageTable { break; } if !pte.is_valid() { - return None; + return None;//如果有æŸä¸€ä¸ªåœ°æ–¹è¿˜æ²¡æœ‰æ˜ 射,那就说明这个虚拟地å€è¿˜æ²¡æœ‰æ˜ å°„ + //返回值为None时,就å¯ä»¥å»ºç«‹æ˜ 射关系了 } ppn = pte.ppn(); } result } #[allow(unused)] - pub fn map(&mut self, vpn: VirtPageNum, ppn: PhysPageNum, flags: PTEFlags) { + pub fn map(&mut self, vpn: VirtPageNum, ppn: PhysPageNum, flags: PTEFlags) ->bool{ + trace!("Pagetable::mapping...token is {:#x} \n vpn is {:#x}, ppn is {:#x}",self.token(), usize::from(vpn), usize::from(ppn)); let pte = self.find_pte_create(vpn).unwrap(); + // 问题:为什么这里å‘现页表是已ç»not-valid的,就能说明之å‰map过了? + // å› ä¸ºcreateå‡½æ•°æ— è®ºå¦‚ä½•éƒ½ä¼šè¿”å›žä¸€ä¸ªpte的。如果是新创建的自然ä¸ä¼šæœ‰é—®é¢˜ï¼Œä¸€å®šæ˜¯valid的。 assert!(!pte.is_valid(), "vpn {:?} is mapped before mapping", vpn); *pte = PageTableEntry::new(ppn, flags | PTEFlags::V); + return true; } #[allow(unused)] - pub fn unmap(&mut self, vpn: VirtPageNum) { + pub fn unmap(&mut self, vpn: VirtPageNum) ->bool{ + trace!("Pagetable::unmapping...token is {:#x} \n vpn is {:#x}",self.token(),usize::from(vpn)); let pte = self.find_pte_create(vpn).unwrap(); assert!(pte.is_valid(), "vpn {:?} is invalid before unmapping", vpn); *pte = PageTableEntry::empty(); + return true; } + + // + //如果这个虚拟地å€å·²ç»è¢«æ˜ 射了,那么就返回pte,å¦åˆ™è¿”回None + //所以想è¦å»ºç«‹æ–°çš„æ˜ 射,应该先检查地å€èŒƒå›´å†…è¿”å›žå€¼æ˜¯ä¸æ˜¯None,如果有一个返回值为None,那么就ä¸èƒ½ç”¨ pub fn translate(&self, vpn: VirtPageNum) -> Option<PageTableEntry> { self.find_pte(vpn) .map(|pte| {pte.clone()}) @@ -144,37 +164,81 @@ impl PageTable { (aligned_pa_usize + offset).into() }) } + //注æ„ï¼è¿™é‡Œçš„tokenç»™å‡ºçš„å¹¶ä¸æ˜¯ç‰©ç†é¡µå·å•ŠÂ·Â·Â·Â·Â·Â· pub fn token(&self) -> usize { + trace!("[kernel] PageTable::token is {:#x}",8usize << 60 | self.root_ppn.0); 8usize << 60 | self.root_ppn.0 } } -pub fn translated_byte_buffer(token: usize, ptr: *const u8, len: usize) -> Vec<&'static mut [u8]> { +pub fn translated_byte_buffer(token: usize, ptr: *const u8, len: usize) -> Option<Vec<&'static mut [u8]>> { let page_table = PageTable::from_token(token); let mut start = ptr as usize; let end = start + len; let mut v = Vec::new(); + //check addr while start < end { let start_va = VirtAddr::from(start); let mut vpn = start_va.floor(); - let ppn = page_table - .translate(vpn) - .unwrap() - .ppn(); - vpn.step(); - let mut end_va: VirtAddr = vpn.into(); - end_va = end_va.min(VirtAddr::from(end)); - if end_va.page_offset() == 0 { - v.push(&mut ppn.get_bytes_array()[start_va.page_offset()..]); - } else { - v.push(&mut ppn.get_bytes_array()[start_va.page_offset()..end_va.page_offset()]); + if let Some(pte) = page_table.translate(vpn){ + let ppn = pte.ppn(); + vpn.step(); + let mut end_va: VirtAddr = vpn.into(); + end_va = end_va.min(VirtAddr::from(end)); + if end_va.page_offset() == 0 { + v.push(&mut ppn.get_bytes_array()[start_va.page_offset()..]); + } else { + v.push(&mut ppn.get_bytes_array()[start_va.page_offset()..end_va.page_offset()]); + } + start = end_va.into(); + }else{ + return None; + } + } + + // while start < end { + // let start_va = VirtAddr::from(start); + // let mut vpn = start_va.floor(); + // let ppn = page_table + // .translate(vpn) + // .unwrap() + // .ppn(); + // vpn.step(); + // let mut end_va: VirtAddr = vpn.into(); + // end_va = end_va.min(VirtAddr::from(end)); + // if end_va.page_offset() == 0 { + // v.push(&mut ppn.get_bytes_array()[start_va.page_offset()..]); + // } else { + // v.push(&mut ppn.get_bytes_array()[start_va.page_offset()..end_va.page_offset()]); + // } + // start = end_va.into(); + // } + Some(v) +} + +pub fn check_byte_buffer_valid(token: usize, ptr: *const u8, len: usize) -> bool { + let page_table = PageTable::from_token(token); + let mut start = ptr as usize; + let end = start + len; + //check addr + while start < end { + let start_va = VirtAddr::from(start); + let mut vpn = start_va.floor(); + if let Some(pte) = page_table.translate(vpn){ + let ppn = pte.ppn(); + vpn.step(); + let mut end_va: VirtAddr = vpn.into(); + end_va = end_va.min(VirtAddr::from(end)); + start = end_va.into(); + }else{ + return false; } - start = end_va.into(); } - v + true } /// Load a string from other address spaces into kernel space without an end `\0`. +//ptr其实是å—符串的地å€ï¼Œè¯•试看这个å—ç¬¦ä¸²æ˜¯ä¸æ˜¯èƒ½ç¿»è¯‘æˆString哦 pub fn translated_str(token: usize, ptr: *const u8) -> String { let page_table = PageTable::from_token(token); let mut string = String::new(); diff --git a/os/src/sbi.rs b/os/src/sbi.rs index 36e15fcc30b8f6a1f3cdd87cef99588cc5976f9e..1412c65f9a8afc7664e91b9f27df1d4a05820cf1 100644 --- a/os/src/sbi.rs +++ b/os/src/sbi.rs @@ -40,4 +40,3 @@ pub fn shutdown() -> ! { sbi_call(SBI_SHUTDOWN, 0, 0, 0); panic!("It should shutdown!"); } - diff --git a/os/src/syscall/flinker.rs b/os/src/syscall/flinker.rs new file mode 100644 index 0000000000000000000000000000000000000000..24791fe5fb268e56aebfd969f2117600e3172210 --- /dev/null +++ b/os/src/syscall/flinker.rs @@ -0,0 +1,210 @@ + +#[repr(C)] +#[derive(Debug,Clone,Copy)] +pub struct Stat { + /// 文件所在ç£ç›˜é©±åŠ¨å™¨å· + pub dev: u64, + /// inode 文件所在 inode ç¼–å· + pub ino: u64, + /// 文件类型 + pub mode: StatMode, + /// 硬链接数é‡ï¼Œåˆå§‹ä¸º1 + pub nlink: u32, + /// æ— éœ€è€ƒè™‘ï¼Œä¸ºäº†å…¼å®¹æ€§è®¾è®¡ + pad: [u64; 7], +} + +bitflags! { + pub struct StatMode: u32 { + const NULL = 0; + /// directory + const DIR = 0o040000; + /// ordinary regular file + const FILE = 0o100000; + } +} + +//下é¢çš„内容就是建立一个key-wordçš„å—å…¸ +//1.å—典里é¢å˜å‚¨çš„æ˜¯æ˜ 射关系,å—符串到å—符串,string到stringçš„ +//2.è¿™ä¸ªæ˜ å°„å…³ç³»å˜å‚¨åœ¨ç£ç›˜ä¸ŠæŸä¸ªæ–‡ä»¶ä¸ï¼Œå¯åЍOSçš„æ—¶å€™æŠŠè¿™ä¸ªæ–‡ä»¶åŠ è½½å‡ºæ¥ +//3.OSå…³é—的时候写回去å³å¯ + +use core::any::Any; +use alloc::sync::Arc; +use spin::Mutex; +use lazy_static::*; +use alloc::string::String; +use alloc::collections::btree_map::BTreeMap; +use super::fs::*; +use crate::fs::{ + make_pipe, OpenFlags, open_file, OSInode, + create_linker,delete_linker,count_files, + get_inode_id, + File, + Stdin, + Stdout, + count_files_from_id, +}; +use crate::mm::{ + translated_str, + VirtAddr, +}; +use crate::task::{ + current_user_token, + current_task, + current_user_v2p, +}; +use super::process::sys_getpid; + +lazy_static! { + pub static ref PATH_MAPPER: Mutex<BTreeMap<String,String>> = Mutex::new(BTreeMap::new()); +} + +pub fn put_link(fake_path:String, real_path:String){ + PATH_MAPPER.lock().insert(fake_path,real_path); +} + +pub fn get_link(fake_path:&String) -> Option<String>{ + if let Some(str) = PATH_MAPPER.lock().get(fake_path){ + Some(String::from(str))//这里必须这么写, + //å› ä¸ºget方法返回的是临时å˜é‡ï¼Œäº‹å®žä¸Šå¹¶ä¸èƒ½ç›´æŽ¥è¿”回给外é¢çš„函数 + }else{ + None + } +} + +pub fn remove_link(fake_path:&String) ->Option<String>{ + PATH_MAPPER.lock().remove(fake_path) +} + + +//============================= + +//lab7 +pub fn sys_linkat5(olddirfd: isize, oldpath: *const u8, newdirfd: isize, newpath: *const u8, flags: u32) -> isize{ + info!("sys_linkat5..."); + sys_linkat(oldpath, newpath, flags) +} +//我大概有æ€è·¯äº†ï¼Œå¤§æ¦‚就是ç£ç›˜ä¸Šåˆ†é…一个文件专门用æ¥å˜å‚¨æ˜ å°„ä¿¡æ¯ï¼Œå˜å‚¨ä¸€ä¸ªdictï¼Œå¦‚æžœäº§ç”Ÿäº†è¿™æ ·çš„ç³»ç»Ÿè°ƒç”¨ +//就在dicé‡Œé¢æ·»åŠ å€¼ï¼Œå˜å‚¨æŠŠæŸä¸ªè·¯å¾„æ˜ å°„åˆ°å“ªé‡Œçš„ä¿¡æ¯ +//unlinkå°±æ˜¯æŠŠåœ°å€æ˜ å°„ä¿¡æ¯åˆ 除 +//çœ‹æ ·ååªè¦å˜å‚¨å—符串就å¯ä»¥äº† +//ç…§ç†æ¥è¯´æ˜¯è¦å†™åœ¨ç£ç›˜ä¸Šçš„,但是现在å¯ä»¥æš‚时先写在内å˜é‡Œé¢ +//我知é“了ï¼åªè¦ç…§æŠ„用户æ€ï¼Œå°±å¯ä»¥çŸ¥é“如何open如何使用。我在这里确实需è¦ä¸€ä¸ªæ–‡ä»¶æ¥å˜å‚¨è¿™äº›æ˜ 射关系, +//所以OS或许还需è¦å¯¹ç”¨æˆ·ç¨‹åºåšå‡ºä¸€äº›è¦æ±‚,比如说ä¸å…许使用以.开头的文件å,这些文件åé™å®šä¸ºç³»ç»Ÿæ–‡ä»¶ +//but now, we can ignore the security and use any name we'd like to + + +//äº‹å®žä¸Šï¼Œç³»ç»Ÿè°ƒç”¨æŽ¥å£æ˜¯syscall有5ä¸ªå‚æ•°ã€‚但是我实在ä¸çŸ¥é“æ€Žä¹ˆè¿™æ ·å®žçŽ°ï¼Œæ‰€ä»¥ä¸ºäº†å…ˆå†™å®Œå®žéªŒ +//å¯ä»¥å…ˆæŒ‰syscall走,userlib里é¢çš„æŽ¥å£ä¹Ÿæ”¹æ”¹å°±å¯ä»¥äº† +//但是最åŽå®žçŽ°å®žéªŒçš„æ—¶å€™å¤§æ¦‚è¿˜è¦å†æ”¹æ”¹ +pub fn sys_linkat(oldpath: *const u8, newpath: *const u8, flags: u32) -> isize{ + let token = current_user_token(); + let real_path = translated_str(token, oldpath); + let fake_path = translated_str(token, newpath); + info!("[sys_linkat]...real_path:{},fake_path:{}",real_path,fake_path); + if let Some(inode) = create_linker(fake_path.as_str(),real_path.as_str()){ + return -1 as isize; + }else{ + return 0 as isize; + } +} + +pub fn sys_unlinkat(dirfd: isize, path: *const u8, flags: u32) -> isize{ + let token = current_user_token(); + let fake_path = translated_str(token, path); + info!("[sys_unlinkat]..."); + if delete_linker(fake_path.as_str()){ + return 0 as isize; + }else{ + return -1 as isize; + } +} + +pub fn return_if_file(f: &(dyn Any + Send + Sync)) -> Option<&Arc<OSInode>>{ + if let Some(file) = f.downcast_ref::<Arc<OSInode>>() { + println!("It's a Arc<OSInode>"); + return Some(file) + } else { + warn!("Not a OSInode..."); + return None; + } +} + +pub fn sys_fstat(fd: usize, st: *mut Stat) -> isize{ + info!("[sys_fstat]...fd:{:#x},st:{:#x}",fd,st as usize); + + let task = current_task().unwrap(); + //get-data + let mut inner = task.acquire_inner_lock(); + + //TODO这儿肯定会写出æ»é”ï¼ï¼ï¼ï¼ + //也ä¸ä¸€å®šã€‚。。 + if let Some(inode) = &inner.fd_table[fd]{ + //判æ–è¿™é‡Œæ˜¯ä¸æ˜¯OSInode类型 + let inode = inode.clone(); + drop(inner); + if let Some(inode_id) = inode.inode_id(){ + info!("[sys_fstat] inode_id is {}",inode_id); + //TODO:exception solve + + let count = count_files_from_id(inode_id).unwrap(); + + //这边drop掉。但是关键是···类型转æ¢çš„æ—¶å€™ä¼šå†åŠ ä¸€æ¬¡é”ï¼Œè¿™æ ·å°±æ»é”了······Orz + + //ä»¿ä½›æ˜Žç™½äº†Â·Â·Â·Â·Â·Â·å› ä¸ºçŽ°åœ¨å¤„ç†ç³»ç»Ÿè°ƒç”¨è‚¯å®šæ˜¯è¿è¡Œåœ¨å†…æ ¸æ€ + //但是这里给的是用户æ€çš„虚拟地å€ã€‚那这就确实是有问题的 + //å› æ¤è¿™é‡Œå¤§æ¦‚是真的需è¦å–出物ç†åœ°å€ï¼Œç„¶åŽè®¿é—®ç‰©ç†åœ°å€ã€‚ + //å› ä¸ºOS在页表åˆå§‹åŒ–的时候以åŠå»ºç«‹äº†ç‰©ç†åœ°å€åˆ°ç‰©ç†åœ°å€çš„æ˜ å°„ï¼Œå› æ¤ç›´æŽ¥è®¿é—®ç‰©ç†åœ°å€ä¹Ÿæ˜¯æ²¡é—®é¢˜çš„å§å¤§æ¦‚ + let pa = current_user_v2p(VirtAddr::from(st as usize)); + + println!("v2p convert end"); + + // info!("[sys_fstat]...physics addr is {:#x}",pa_st as usize); + match pa { + //pub dev: u64, + // /// inode 文件所在 inode ç¼–å· + // pub ino: u64, + // /// 文件类型 + // pub mode: StatMode, + // /// 硬链接数é‡ï¼Œåˆå§‹ä¸º1 + // pub nlink: u32, + Some(pa_t)=>{ + // let pa_ts = usize::from(pa.unwrap()) as *mut TimeVal; + let pa_st = usize::from(pa_t) as *mut Stat; + info!("[sys_fstat]...physics addr is {:#x}",pa_st as usize); + + unsafe{ + match (*pa_st){ + Stat => { + (*pa_st).dev = 1 as u64; + (*pa_st).ino = inode_id as u64; + (*pa_st).mode = StatMode::FILE; + (*pa_st).nlink = count as u32; + } + _ => { + warn!("[sys_fstat] NULL"); + }, + } + } + }, + _ =>{ + warn!("[get_time] NONE"); + } + } + debug!("sys_get_time return..."); + return 0 as isize; + info!("[sys_fstat]..."); + //todo:从文件æè¿°ç¬¦åˆ°Inode或者name + //todo:getfiledata如何得到文件类型是文件夹还是普通文件? + -1 + }else{ + warn!("[sys_fstat] cant't find inode id..."); + return -1 as isize; + } + }else{ + warn!("[sys_fstat] no file in fdtable[fd]..."); + return -1 as isize; + } + //这里是é¿å…å‘生所有æƒè½¬ç§» +} \ No newline at end of file diff --git a/os/src/syscall/fs.rs b/os/src/syscall/fs.rs index 79eac32aeddbe6eca7ee0a5166cc0633d1b577e8..4fb3d1573ef256504b5f64a75ebed901859c6cec 100644 --- a/os/src/syscall/fs.rs +++ b/os/src/syscall/fs.rs @@ -3,12 +3,48 @@ use crate::mm::{ translated_byte_buffer, translated_refmut, translated_str, + check_byte_buffer_valid, +}; +use crate::fs::{ + make_pipe, OpenFlags, open_file, }; -use crate::task::{current_user_token, current_task}; -use crate::fs::{make_pipe, OpenFlags, open_file}; use alloc::sync::Arc; +use crate::task::{ + current_user_token, + mail_user_token_pid, + + current_task, + mail_write_to_pid, + mail_write_to_me, + mail_get_from_me, + mail_not_full_me, + mail_not_full_pid, + mail_not_empty_me, + +}; + +use super::process::sys_getpid; +use crate::config::{ + MAIL_SIZE, +}; + +use super::flinker::{ + get_link, +}; + +/// ä»£ç æ®µ .text ä¸å…许被修改; +/// åªè¯»æ•°æ®æ®µ .rodata ä¸å…许被修改,也ä¸å…许从它上é¢å–指; +/// .data/.bss å‡å…许被读写,但是ä¸å…许从它上é¢å–指。 +/// +/// 功能:将内å˜ä¸ç¼“冲区ä¸çš„æ•°æ®å†™å…¥æ–‡ä»¶ã€‚ +/// 傿•°ï¼š`fd` 表示待写入文件的文件æè¿°ç¬¦ï¼› +/// `buf` 表示内å˜ä¸ç¼“冲区的起始地å€ï¼› +/// `len` 表示内å˜ä¸ç¼“冲区的长度。 +/// 返回值:返回æˆåŠŸå†™å…¥çš„é•¿åº¦ã€‚ +/// syscall ID:64 pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize { + debug!("sys_write...fd {}, buf {:#x}, len {}",fd,buf as usize,len); let token = current_user_token(); let task = current_task().unwrap(); let inner = task.acquire_inner_lock(); @@ -22,15 +58,21 @@ pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize { let file = file.clone(); // release Task lock manually to avoid deadlock drop(inner); - file.write( - UserBuffer::new(translated_byte_buffer(token, buf, len)) - ) as isize + // file.write( + // UserBuffer::new(translated_byte_buffer(token, buf, len)) + // ) as isize + if let Some(tsf) = translated_byte_buffer(token, buf, len){ + file.write(UserBuffer::new(tsf)) as isize + }else{ + -1 + } } else { -1 } } pub fn sys_read(fd: usize, buf: *const u8, len: usize) -> isize { + debug!("[sys_read]..."); let token = current_user_token(); let task = current_task().unwrap(); let inner = task.acquire_inner_lock(); @@ -43,16 +85,20 @@ pub fn sys_read(fd: usize, buf: *const u8, len: usize) -> isize { return -1; } // release Task lock manually to avoid deadlock + // 问题:为什么是在这里drop的? drop(inner); - file.read( - UserBuffer::new(translated_byte_buffer(token, buf, len)) - ) as isize + if let Some(tsf) = translated_byte_buffer(token, buf, len){ + file.read(UserBuffer::new(tsf)) as isize + }else{ + -1 + } } else { -1 } } pub fn sys_open(path: *const u8, flags: u32) -> isize { + info!("[sys_open]..."); let task = current_task().unwrap(); let token = current_user_token(); let path = translated_str(token, path); @@ -60,12 +106,26 @@ pub fn sys_open(path: *const u8, flags: u32) -> isize { path.as_str(), OpenFlags::from_bits(flags).unwrap() ) { + //inode类型是OSInode,就是一个文件(神奇ï¼ï¼‰ let mut inner = task.acquire_inner_lock(); let fd = inner.alloc_fd(); inner.fd_table[fd] = Some(inode); - fd as isize + return fd as isize; } else { - -1 + //å¦åˆ™å°±å¯»æ‰¾link的路径,如果能找到且å¯ä»¥æ‰“å¼€ + if let Some(real_path) = get_link(&path){ + if let Some(inode) = open_file( + real_path.as_str(), + OpenFlags::from_bits(flags).unwrap() + ) { + //inode类型是OSInode,就是一个文件(神奇ï¼ï¼‰ + let mut inner = task.acquire_inner_lock(); + let fd = inner.alloc_fd(); + inner.fd_table[fd] = Some(inode); + return fd as isize; + } + } + return -1 as isize; } } @@ -93,9 +153,15 @@ pub fn sys_pipe(pipe: *mut usize) -> isize { inner.fd_table[write_fd] = Some(pipe_write); *translated_refmut(token, pipe) = read_fd; *translated_refmut(token, unsafe { pipe.add(1) }) = write_fd; + //总而言之以上两å¥è¯çš„å«ä¹‰æ˜¯ï¼ŒæŠŠread_fdå’Œwrite_fd都写给用户æ€å•¦ 0 } +/// 功能:将进程ä¸ä¸€ä¸ªå·²ç»æ‰“开的文件å¤åˆ¶ä¸€ä»½å¹¶åˆ†é…到一个新的文件æè¿°ç¬¦ä¸ã€‚ +/// 傿•°ï¼šfd 表示进程ä¸ä¸€ä¸ªå·²ç»æ‰“开的文件的文件æè¿°ç¬¦ã€‚ +/// 返回值:如果出现了错误则返回 -1,å¦åˆ™èƒ½å¤Ÿè®¿é—®å·²æ‰“开文件的新文件æè¿°ç¬¦ã€‚ +/// å¯èƒ½çš„é”™è¯¯åŽŸå› æ˜¯ï¼šä¼ å…¥çš„ fd å¹¶ä¸å¯¹åº”ä¸€ä¸ªåˆæ³•的已打开文件。 +/// syscall ID:24 pub fn sys_dup(fd: usize) -> isize { let task = current_task().unwrap(); let mut inner = task.acquire_inner_lock(); @@ -108,4 +174,151 @@ pub fn sys_dup(fd: usize) -> isize { let new_fd = inner.alloc_fd(); inner.fd_table[new_fd] = Some(Arc::clone(inner.fd_table[fd].as_ref().unwrap())); new_fd as isize +} + +//把邮箱里é¢çš„内容写到缓冲区 +pub fn sys_mail_read(buf: *mut u8, l: usize)->isize{ + //å› ä¸ºè¿™é‡Œæ˜¯ç›´æŽ¥å¤ç”¨äº†pipe,所以会å—到一些é™åˆ¶ã€‚比如说,pipe如果写超了,就会直接切æ¢è¿›ç¨‹Â·Â·Â·Â·Â·Â· + //ç„¶åŽä½ 就会å‘çŽ°è‡ªå·±å¥½åƒæ»é”了。 + //除éžè‡ªå·±æ¨¡ä»¿pipeé‡å†™ä¸€ä¸ªçœŸæ£çš„mail,å¦åˆ™å°±åªèƒ½è¿™æ ·åœ¨è¿›å…¥å‡½æ•°ä¹‹å‰ + //一定è¦åˆ¤æ–有没有超范围啊 + let mut len = l; + //è¿™æ˜¯æµ‹è¯•æ˜¯å¦æœ‰æŠ¥æ–‡å¯ä»¥è¯» + if len==0{ + warn!("[mail_read] len=0,may fail"); + if let Some(not_empty) = mail_not_empty_me(){ + if(not_empty){ + return 0 as isize; + } + }else{ + + } + return -1 as isize; + } + if len>MAIL_SIZE{ + len = MAIL_SIZE; + } + //如果地å€éžæ³•,就ä¸èƒ½è¯»äº† + let token = current_user_token(); + if !check_byte_buffer_valid(token, buf, len){ + warn!("[mail_read] invalid byte buffer address,may fail"); + return -1 as isize; + } + + //如果是è¦ç»™è‡ªå·±å†™ + //å°±ä¸èƒ½åœ¨TASK_MANAGERé‡Œé¢æ‰¾ï¼Œæ‰¾ä¸åˆ°çš„ + //这个ä¸éœ€è¦è¿”回 + if let Some(read_fd) = mail_get_from_me(){ + //如果返回了文件æè¿°ç¬¦ï¼Œä¹Ÿå°±æ˜¯å¯ä»¥å†™çš„æ„æ€ + // let task = current_task().unwrap(); + // let mut inner = task.acquire_inner_lock(); + // inner.fd_table[read_fd] = Some(mpipe_read); + // drop(inner); + let len = sys_read(read_fd,buf,len); + if sys_close(read_fd)!= -1 { + return len as isize; + }else{ + return -1 as isize; + } + }else{ + warn!("[mail_read] can't get mail,may fail"); + return -1 as isize; + } +} + +//把缓冲区里é¢çš„内容写进进程pid的邮箱 +pub fn sys_mail_write(pid: usize, buf: *mut u8, l: usize)->isize{ + //å› ä¸ºè¿™é‡Œæ˜¯ç›´æŽ¥å¤ç”¨äº†pipe,所以会å—到一些é™åˆ¶ã€‚比如说,pipe如果写超了,就会直接切æ¢è¿›ç¨‹Â·Â·Â·Â·Â·Â· + //ç„¶åŽä½ 就会å‘çŽ°è‡ªå·±å¥½åƒæ»é”了。 + //除éžè‡ªå·±æ¨¡ä»¿pipeé‡å†™ä¸€ä¸ªçœŸæ£çš„mail,å¦åˆ™å°±åªèƒ½è¿™æ ·åœ¨è¿›å…¥å‡½æ•°ä¹‹å‰ + //一定è¦åˆ¤æ–有没有超范围啊 + + //地å€é”™è¯¯æ˜¯éœ€è¦å…ˆæ£€æŸ¥çš„。。。 + let mut len = l; + let p = sys_getpid() as isize;//my pid is p + if len==0{ + warn!("[mail_write] len=0,may fail"); + if (p == pid as isize){ + if let Some(not_full) = mail_not_full_me(){ + if(not_full){ + return 0 as isize; + }else{ + + } + } + return -1 as isize; + }else{ + if let Some(not_full) = mail_not_full_pid(pid){ + if(not_full){ + return 0 as isize; + }else{ + + } + } + return -1 as isize; + } + } + if len>MAIL_SIZE{ + warn!("[mail_write] len too long,continue"); + len = MAIL_SIZE; + } + + if (p == pid as isize){ + //先检查地å€é”™è¯¯ + //如果地å€éžæ³•,就ä¸èƒ½è¯»äº† + let token = current_user_token(); + if !check_byte_buffer_valid(token, buf, len){ + return -1 as isize; + } + //如果是è¦ç»™è‡ªå·±å†™ + //å°±ä¸èƒ½åœ¨TASK_MANAGERé‡Œé¢æ‰¾ï¼Œæ‰¾ä¸åˆ°çš„ + if let Some(mpipe_write) = mail_write_to_me(){ + //如果返回了文件æè¿°ç¬¦ï¼Œä¹Ÿå°±æ˜¯å¯ä»¥å†™çš„æ„æ€ + let task = current_task().unwrap(); + let mut inner = task.acquire_inner_lock(); + let write_fd = inner.alloc_fd(); + inner.fd_table[write_fd] = Some(mpipe_write); + drop(inner); + if sys_write(write_fd,buf,len) != -1{ + if sys_close(write_fd)!= -1 { + return len as isize; + }else{ + warn!("[mail_write] sys_close fail,fail"); + return -1 as isize; + } + }else{ + warn!("[mail_write] sys_write fail,fail"); + return -1 as isize; + } + }else{ + warn!("[mail_write] can't get mail,fail"); + return -1 as isize; + } + }else{ + //先检查地å€é”™è¯¯ + //如果地å€éžæ³•,就ä¸èƒ½è¯»äº† + if let Some(token) = mail_user_token_pid(pid){ + if !check_byte_buffer_valid(token, buf, len){ + return -1 as isize; + } + }else{ + return -1 as isize; + } + + //å¦åˆ™å°±åœ¨æ²¡æœ‰æ£åœ¨è¿è¡Œçš„taské‡Œé¢æ‰¾æ˜¯å¦å¯ä»¥æ–°å»ºä¸€å°mail + if let Some(mpipe_write) = mail_write_to_pid(pid){ + //如果返回了文件æè¿°ç¬¦ï¼Œä¹Ÿå°±æ˜¯å¯ä»¥å†™çš„æ„æ€ + let task = current_task().unwrap(); + let mut inner = task.acquire_inner_lock(); + let write_fd = inner.alloc_fd(); + inner.fd_table[write_fd] = Some(mpipe_write); + drop(inner); + sys_write(write_fd,buf,len); + sys_close(write_fd); + return len as isize; + }else{ + warn!("[mail_write] can't get mail,fail"); + return -1 as isize; + } + } } \ No newline at end of file diff --git a/os/src/syscall/memory.rs b/os/src/syscall/memory.rs new file mode 100644 index 0000000000000000000000000000000000000000..090eba8c1bdf3fa0a598f80e808a55d12f5d2194 --- /dev/null +++ b/os/src/syscall/memory.rs @@ -0,0 +1,58 @@ +use crate::task::{ + mmap, + munmap, +}; + +use crate::config::{ + PAGE_SIZE, + MEMORY_MAP_SIZE, +}; + +pub fn sys_mmap(start: usize, len: usize, port: usize) -> isize{ + debug!("sys_mmap...start = {:#x}, len = {}, port = {}...",start,len,port); + //需è¦åšå‡ 件事: + //1.检查数æ®ç±»åž‹æ˜¯å¦åˆæ³•: + //- startå’Œé¡µå¯¹é½ + //- lenä¸èƒ½è¿‡å¤§ä¸èƒ½è¿‡å° + //- portæ»¡è¶³ä¸€äº›è¦æ±‚ + if start % PAGE_SIZE != 0 { + return -1 as isize; + } + if len == 0 { + return 0 as isize; + } + if len > MEMORY_MAP_SIZE { + return -1 as isize; + } + if (port & !0x7 != 0)||(port & 0x7 == 0) { + return -1 as isize; + } + // return -1 as isize; + return mmap(start, len, port); +} + +pub fn sys_munmap(start: usize, len: usize) -> isize{ + debug!("sys_munmap...start = {:#x}, len = {}",start,len); + //需è¦åšå‡ 件事: + //1.检查数æ®ç±»åž‹æ˜¯å¦åˆæ³•: + //- startå’Œé¡µå¯¹é½ + //- lenä¸èƒ½è¿‡å¤§ä¸èƒ½è¿‡å° + if start % PAGE_SIZE != 0 { + return -1 as isize; + } + if len == 0 { + return 0 as isize; + } + if len > MEMORY_MAP_SIZE { + return -1 as isize; + } + //2.分é…ã€‚å¦‚æžœè¿˜æœ‰ç©ºé—´åˆ†é…æˆåŠŸå°±è¿”å›žsize,注æ„返回的是å—èŠ‚æ•°è€Œä¸æ˜¯é¡µæ•°ï¼Œåˆ†é…失败就返回-1 + + let result = munmap(start, len); + if result == -1 { + return -1 as isize; + } + else { + return result * (PAGE_SIZE as isize); + } +} \ No newline at end of file diff --git a/os/src/syscall/mod.rs b/os/src/syscall/mod.rs index 4683d055b9656fcc84a706aff83e68190f53726a..365264635d520ae58f542ba745e6c7c4694bfd9b 100644 --- a/os/src/syscall/mod.rs +++ b/os/src/syscall/mod.rs @@ -11,14 +11,34 @@ const SYSCALL_GETPID: usize = 172; const SYSCALL_FORK: usize = 220; const SYSCALL_EXEC: usize = 221; const SYSCALL_WAITPID: usize = 260; +// const SYSCALL_GETTIMEOFDAY: usize = 169; +const SYSCALL_SET_PRIORITY: usize = 140; +const SYSCALL_MMAP: usize = 222; +const SYSCALL_MUNMAP: usize = 215; +const SYSCALL_SPAWN: usize = 400; +const SYSCALL_MAIL_READ: usize = 401; +const SYSCALL_MAIL_WRITE: usize = 402; +//=====================lab7=============================== +const SYSCALL_UNLINKAT: usize = 35; +const SYSCALL_LINKAT: usize = 37; +const SYSCALL_FSTAT: usize = 80; mod fs; mod process; +mod memory; +mod trap; +mod flinker; use fs::*; use process::*; +use memory::*; +use trap::*; +use crate::timer::TimeVal; +use flinker::*; +//现在的问题就是TimeVal为什么地å€ä¸èƒ½ç”¨ï¼Ÿç…§ç†æ¥è¯´åº”该在创建的时候自动修改了æ‰å¯¹ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { + trace!("in syscall...{},{},{},{}",syscall_id,args[0],args[1],args[2]); match syscall_id { SYSCALL_DUP=> sys_dup(args[0]), SYSCALL_OPEN => sys_open(args[0] as *const u8, args[1] as u32), @@ -28,12 +48,45 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { SYSCALL_WRITE => sys_write(args[0], args[1] as *const u8, args[2]), SYSCALL_EXIT => sys_exit(args[0] as i32), SYSCALL_YIELD => sys_yield(), - SYSCALL_GET_TIME => sys_get_time(), + + // SYSCALL_GET_TIME => sys_get_time(), + //[time as *const _ as usize, tz, 0] + //lab3 + SYSCALL_GET_TIME => sys_get_time(args[0] as *mut TimeVal, args[1]), + SYSCALL_SET_PRIORITY => sys_set_priority(args[0]), + + //lab4 + SYSCALL_MMAP => sys_mmap(args[0],args[1],args[2]), + SYSCALL_MUNMAP => sys_munmap(args[0],args[1]), + + //lab5 SYSCALL_GETPID => sys_getpid(), SYSCALL_FORK => sys_fork(), SYSCALL_EXEC => sys_exec(args[0] as *const u8, args[1] as *const usize), SYSCALL_WAITPID => sys_waitpid(args[0] as isize, args[1] as *mut i32), + SYSCALL_SPAWN => sys_spawn(args[0] as *const u8, args[1] as *const usize), + + //lab6 + SYSCALL_MAIL_READ => sys_mail_read(args[0] as *mut u8, args[1]), + SYSCALL_MAIL_WRITE => sys_mail_write(args[0], args[1] as *mut u8, args[2]), + + //lab7 + //=====================lab7=============================== + SYSCALL_FSTAT => sys_fstat(args[0], args[1] as *mut Stat), + //important: permantly + SYSCALL_UNLINKAT => sys_unlinkat(args[0] as isize, args[1] as *const u8, args[2] as u32), + // SYSCALL_LINKAT => sys_linkat(args[0] as *const u8, args[1] as *const u8, args[2]), + _ => panic!("Unsupported syscall_id: {}", syscall_id), } } +//问题:有些syscallä¼ è¿›æ¥5ä¸ªå‚æ•°ï¼Œæˆ‘该怎么调用它啊??? +//现在暂且ä¸ä¼šè§£å†³ï¼Œæ‰€ä»¥å…ˆç”¨ç€syscall的调用 +pub fn syscall5(syscall_id: usize, args: [usize; 5]) -> isize{ + match syscall_id { + SYSCALL_LINKAT => sys_linkat5(args[0] as isize, args[1] as *const u8, args[2] as isize, args[3] as *const u8, args[4] as u32), + // _ => panic!("Unsupported syscall5_id: {}", syscall_id), + _ => syscall(syscall_id, [args[0], args[1], args[2]]), + } +} \ No newline at end of file diff --git a/os/src/syscall/process.rs b/os/src/syscall/process.rs index bfd592d6f197d0e7536746db1942e3111385936d..299b51784ce3ce06ad619a26ffb0570bdc13a073 100644 --- a/os/src/syscall/process.rs +++ b/os/src/syscall/process.rs @@ -4,8 +4,11 @@ use crate::task::{ current_task, current_user_token, add_task, + + TaskPriority, + set_priority, + // current_user_v2p, }; -use crate::timer::get_time_ms; use crate::mm::{ translated_str, translated_refmut, @@ -15,11 +18,18 @@ use crate::fs::{ open_file, OpenFlags, }; + use alloc::sync::Arc; use alloc::vec::Vec; use alloc::string::String; +use crate::config::{ + ISIZI_MAX, +}; + + pub fn sys_exit(exit_code: i32) -> ! { + kernel_println!("[kernel] Application exited with code {}", exit_code); exit_current_and_run_next(exit_code); panic!("Unreachable in sys_exit!"); } @@ -29,18 +39,19 @@ pub fn sys_yield() -> isize { 0 } -pub fn sys_get_time() -> isize { - get_time_ms() as isize -} - pub fn sys_getpid() -> isize { current_task().unwrap().pid.0 as isize } pub fn sys_fork() -> isize { + let token = current_user_token(); + info!("sys_fork...current user toker is {:#x}",token); + let current_task = current_task().unwrap(); let new_task = current_task.fork(); + //出现一个新的task之åŽä¼šè‡ªåŠ¨åˆ†é…一个pidçš„ let new_pid = new_task.pid.0; + info!("sys_fork...new pid is {}",new_pid); // modify trap context of new_task, because it returns immediately after switching let trap_cx = new_task.acquire_inner_lock().get_trap_cx(); // we do not have to move to next instruction since we have done it before @@ -48,6 +59,8 @@ pub fn sys_fork() -> isize { trap_cx.x[10] = 0; // add new task to scheduler add_task(new_task); + //sogaï¼Œå› ä¸ºfork出æ¥çš„ä¼šè‡ªåŠ¨åŠ å…¥è¿›ç¨‹æ± é‡Œé¢ + //简å•点说就是,放在Manager那个队列里é¢ï¼Œç‰ç€è¢«è°ƒç”¨å“¦ new_pid as isize } @@ -63,6 +76,7 @@ pub fn sys_exec(path: *const u8, mut args: *const usize) -> isize { args_vec.push(translated_str(token, arg_str_ptr as *const u8)); unsafe { args = args.add(1); } } + info!("sys_exec...path is {}",path.as_str()); if let Some(app_inode) = open_file(path.as_str(), OpenFlags::RDONLY) { let all_data = app_inode.read_all(); let task = current_task().unwrap(); @@ -71,14 +85,71 @@ pub fn sys_exec(path: *const u8, mut args: *const usize) -> isize { // return argc because cx.x[10] will be covered with it later argc as isize } else { + warn!("[exec] app not found, fail"); -1 } } +pub fn sys_spawn(path: *const u8, mut args: *const usize) -> isize{ + //æ¢ä¸€ç§æ€è·¯Â·Â·Â·Â·Â·Â·spawn1çš„å†…éƒ¨å®žçŽ°çš„æ•ˆæžœæ˜¯æŠŠæŒ‡å®šçš„å‡½æ•°åŠ è½½è¿›åŽ» + //ç„¶åŽå†æ¥ä¸€ä¸ªå‡½æ•°spawn2æ¥è´Ÿè´£æ‰§è¡Œè¿™ä¸ªå‡½æ•° + + // let token = current_user_token(); + // let path = translated_str(token, path);//总之就是把*const u8翻译æˆString类型 + // info!("sys_spawn...{}",path.as_str()); + //处ç†è¦æ‰“å¼€çš„åº”ç”¨ä¿¡æ¯ + let token = current_user_token(); + //path is String + let path = translated_str(token, path); + let mut args_vec: Vec<String> = Vec::new(); + // spawnæš‚æ—¶ä¸æ”¯æŒæ·»åР傿•°äº†å§ + // loop { + // let arg_str_ptr = *translated_ref(token, args); + // if arg_str_ptr == 0 { + // break; + // } + // args_vec.push(translated_str(token, arg_str_ptr as *const u8)); + // unsafe { args = args.add(1); } + // } + info!("sys_spawn...path is {}",path.as_str()); + if let Some(app_inode) = open_file(path.as_str(), OpenFlags::RDONLY) { + let all_data = app_inode.read_all(); + let current_task = current_task().unwrap(); + let argc = args_vec.len(); + + let new_task = current_task.spawn_from(all_data.as_slice(), args_vec); + // task.exec(all_data.as_slice(), args_vec); + let new_pid = new_task.pid.0; + add_task(new_task); + // return argc because cx.x[10] will be covered with it later + // return argc as isize; + return new_pid as isize + } else { + warn!("[spawn] app not found, fail"); + return -1 as isize; + } + // if let Some(data) = get_app_data_by_name(path.as_str()) { + // let current_task = current_task().unwrap(); + // let new_task = current_task.spawn_from(data); + // //出现一个新的task之åŽä¼šè‡ªåŠ¨åˆ†é…一个pidçš„ + // let new_pid = new_task.pid.0; + // info!("sys_spawn_from...new pid is {}",new_pid); + // // add new task to scheduler + // add_task(new_task); + // //sogaï¼Œå› ä¸ºfork出æ¥çš„ä¼šè‡ªåŠ¨åŠ å…¥è¿›ç¨‹æ± é‡Œé¢ + // //简å•点说就是,放在Manager那个队列里é¢ï¼Œç‰ç€è¢«è°ƒç”¨å“¦ + // new_pid as isize + // } else { + // -1 + // } +} + /// If there is not a child process whose pid is same as given, return -1. /// Else if there is a child process but it is still running, return -2. +/// å¦åˆ™å°±è¿”回child pidçš„ç¼–å· pub fn sys_waitpid(pid: isize, exit_code_ptr: *mut i32) -> isize { let task = current_task().unwrap(); + // kernel_println!("finding {}' children...",task.pid.0); // find a child process // ---- hold current PCB lock @@ -95,21 +166,37 @@ pub fn sys_waitpid(pid: isize, exit_code_ptr: *mut i32) -> isize { .enumerate() .find(|(_, p)| { // ++++ temporarily hold child PCB lock - p.acquire_inner_lock().is_zombie() && (pid == -1 || pid as usize == p.getpid()) + (p.acquire_inner_lock().is_zombie()) && (pid == -1 || pid as usize == p.getpid()) // ++++ release child PCB lock }); if let Some((idx, _)) = pair { let child = inner.children.remove(idx); // confirm that child will be deallocated after being removed from children list assert_eq!(Arc::strong_count(&child), 1); + // println!("[kernel] find pid :{}",child.pid.0); + // confirm that child will be deallocated after removing from children list + // assert_eq!(Arc::strong_count(&child), 1); let found_pid = child.getpid(); // ++++ temporarily hold child lock let exit_code = child.acquire_inner_lock().exit_code; // ++++ release child PCB lock *translated_refmut(inner.memory_set.token(), exit_code_ptr) = exit_code; + kernel_println!("find pid have done :{}",found_pid); found_pid as isize } else { + // println!("[kernel] children not found"); -2 } // ---- release current PCB lock automatically -} \ No newline at end of file +} + +//sys_set_priority +pub fn sys_set_priority(prio: usize) -> isize{ + debug!("[kernel] sys_set_priority...{}",prio); + if prio>=2 && prio<=ISIZI_MAX as usize { + set_priority(TaskPriority::from(prio)); + return prio as isize + } + return -1 as isize +} + diff --git a/os/src/syscall/trap.rs b/os/src/syscall/trap.rs new file mode 100644 index 0000000000000000000000000000000000000000..a4cf3e44f96c00733777a327fae3b556422b537f --- /dev/null +++ b/os/src/syscall/trap.rs @@ -0,0 +1,58 @@ +use crate::timer::{ + // get_time, + get_time_ms, + TimeVal +}; +use crate::mm::{ + VirtAddr, +}; + +use crate::task::{ + current_user_v2p, +}; + +// pub fn sys_get_time() -> isize { +// get_time_ms() as isize +// } + + +pub fn sys_get_time(ts: *mut TimeVal, _tz: usize) -> isize{ + info!("in sys_get_time...{:#x},{}",ts as usize,_tz); + let t = get_time_ms() as usize; + + // let pa_top = KERNEL_SPACE.lock().v2p(VirtAddr::from(kernel_stack_top)).unwrap(); + //ä»¿ä½›æ˜Žç™½äº†Â·Â·Â·Â·Â·Â·å› ä¸ºçŽ°åœ¨å¤„ç†ç³»ç»Ÿè°ƒç”¨è‚¯å®šæ˜¯è¿è¡Œåœ¨å†…æ ¸æ€ + //但是这里给的是用户æ€çš„虚拟地å€ã€‚那这就确实是有问题的 + //å› æ¤è¿™é‡Œå¤§æ¦‚是真的需è¦å–出物ç†åœ°å€ï¼Œç„¶åŽè®¿é—®ç‰©ç†åœ°å€ã€‚ + //å› ä¸ºOS在页表åˆå§‹åŒ–的时候以åŠå»ºç«‹äº†ç‰©ç†åœ°å€åˆ°ç‰©ç†åœ°å€çš„æ˜ å°„ï¼Œå› æ¤ç›´æŽ¥è®¿é—®ç‰©ç†åœ°å€ä¹Ÿæ˜¯æ²¡é—®é¢˜çš„å§å¤§æ¦‚ + let pa = current_user_v2p(VirtAddr::from(ts as usize)); + //todo:注æ„一下secå’Œusecä¸åœ¨ä¸€é¡µçš„æƒ…况 + //但是似乎概率比较å°ï¼Œå°±å…ˆä¸ç®¡äº†å§ + match pa { + Some(pa_t)=>{ + // let pa_ts = usize::from(pa.unwrap()) as *mut TimeVal; + let pa_ts = usize::from(pa_t) as *mut TimeVal; + info!("in sys_get_time...physics addr is {:#x}",pa_ts as usize); + unsafe{ + //ä¸ºä»€ä¹ˆæ— æ³•å–出地å€ï¼Ÿå…ˆè®¿é—®ç‰©ç†åœ°å€è¯•试看啦 + match (*pa_ts){//这里使用指针就跑飞了。为什么? + //æ˜¯å› ä¸ºè™šæ‹Ÿåœ°å€çš„问题å—? + TimeVal => { + info!("sec = {}, usec = {}",(*pa_ts).sec,(*pa_ts).usec); + (*pa_ts).sec = t/1000; + (*pa_ts).usec = t*1000; + info!("sec = {}, usec = {}",(*pa_ts).sec,(*pa_ts).usec); + } + _ => { + warn!("[sys_get_time] NULL"); + }, + } + } + }, + _ =>{ + warn!("[get_time] NONE"); + } + } + debug!("sys_get_time return..."); + return 0 as isize; +} diff --git a/os/src/task/context.rs b/os/src/task/context.rs index 340bc098ea8ec1e16e054c41cb1d534d6bde26ce..573bf3335a06a29771f3a896289ac5b9ece174b4 100644 --- a/os/src/task/context.rs +++ b/os/src/task/context.rs @@ -2,12 +2,12 @@ use crate::trap::trap_return; #[repr(C)] pub struct TaskContext { - ra: usize, - s: [usize; 12], + pub ra: usize, + pub s: [usize; 12], } impl TaskContext { - pub fn goto_trap_return() -> Self { + pub fn goto_trap_return() -> Self {//这里是trap return的上下文,把返回地å€å†™è¿›äº†ra寄å˜å™¨é‡Œé¢ Self { ra: trap_return as usize, s: [0; 12], diff --git a/os/src/task/manager.rs b/os/src/task/manager.rs index ed22391622d406508d2c15d04951169f1fd24132..fe04280f6411d705f26bc191397f2990a181629b 100644 --- a/os/src/task/manager.rs +++ b/os/src/task/manager.rs @@ -1,4 +1,9 @@ -use super::TaskControlBlock; +use super::{ + TaskControlBlock, +}; +use crate::fs::{ + MPipe, +}; use alloc::collections::VecDeque; use alloc::sync::Arc; use spin::Mutex; @@ -19,6 +24,50 @@ impl TaskManager { pub fn fetch(&mut self) -> Option<Arc<TaskControlBlock>> { self.ready_queue.pop_front() } + //äº‹å®žè¯æ˜Žï¼Œè¿™æ ·å†™æ˜¯å¯ä»¥çš„ï¼ï¼ï¼ + //ä½†æ˜¯éœ€è¦æ³¨æ„一点。如果是自己给自己写,会å‘现并ä¸èƒ½åœ¨è¿™é‡Œæ‰¾åˆ°ã€‚å› ä¸ºæ£åœ¨è¿è¡Œçš„进程会被从TaskManager里é¢å–å‡ºæ¥ + //放在Processor里é¢è¿è¡Œ + pub fn call_test(&mut self,pid: usize){ + for item in self.ready_queue.iter_mut(){ + debug!("TaskManager::call_test...pid is {}",item.pid.0); + if item.pid.0 == pid { + item.call_test(); + } + } + } + pub fn mail_write_to_pid(&mut self, pid:usize)-> Option<Arc<MPipe>>{ + for item in self.ready_queue.iter_mut(){ + debug!("TaskManager::mail_write_to_pid...pid is {}",item.pid.0); + if item.pid.0 == pid { + return item.mail_create_from_pipe(); + } + } + None + } + pub fn mail_not_full_pid(&mut self, pid:usize)-> Option<bool>{ + for item in self.ready_queue.iter_mut(){ + debug!("TaskManager::mail_not_full_pid...pid is {}",item.pid.0); + if item.pid.0 == pid { + return item.mail_not_full(); + } + } + None + } + pub fn mail_user_token_pid(&mut self,pid:usize)->Option<usize>{ + for item in self.ready_queue.iter_mut(){ + debug!("TaskManager::mail_not_full_pid...pid is {}",item.pid.0); + if item.pid.0 == pid { + return Some(item.acquire_inner_lock().get_user_token()) + } + } + None + } + // pub fn mail_create_from_pipe(&self)->Option<Arc<Pipe>>{ + // pub fn current_user_token() -> usize { + // let task = current_task().unwrap(); + // let token = task.acquire_inner_lock().get_user_token(); + // token + // } } lazy_static! { @@ -31,4 +80,23 @@ pub fn add_task(task: Arc<TaskControlBlock>) { pub fn fetch_task() -> Option<Arc<TaskControlBlock>> { TASK_MANAGER.lock().fetch() +} + +pub fn call_test(pid: usize){ + kernel_println!("call_test...pid is {}",pid); + TASK_MANAGER.lock().call_test(pid); +} + +pub fn mail_write_to_pid(pid:usize)-> Option<Arc<MPipe>>{ + debug!("mail_write_to_pid...pid is {}",pid); + TASK_MANAGER.lock().mail_write_to_pid(pid) +} + +pub fn mail_not_full_pid(pid:usize)-> Option<bool>{ + debug!("mail_write_to_pid...pid is {}",pid); + TASK_MANAGER.lock().mail_not_full_pid(pid) +} + +pub fn mail_user_token_pid(pid:usize) ->Option<usize>{ + TASK_MANAGER.lock().mail_user_token_pid(pid) } \ No newline at end of file diff --git a/os/src/task/mod.rs b/os/src/task/mod.rs index e943016c4a1111d6836025dad15c886990e09520..8cb1b5b013ea296e7a3cc088cce11f52252b2913 100644 --- a/os/src/task/mod.rs +++ b/os/src/task/mod.rs @@ -4,13 +4,19 @@ mod task; mod manager; mod processor; mod pid; +mod stride; +mod priority; use crate::fs::{open_file, OpenFlags}; use switch::__switch; use task::{TaskControlBlock, TaskStatus}; use alloc::sync::Arc; -use manager::fetch_task; use lazy_static::*; + +//===================================================================== +// æœ¬æ–‡ä»¶ä¸æ˜¯è¦å‘å…¶ä»–æ¨¡å—æä¾›çš„ä»£ç +//===================================================================== + pub use context::TaskContext; pub use processor::{ @@ -20,10 +26,33 @@ pub use processor::{ current_trap_cx, take_current_task, schedule, + + set_priority, + mmap, + munmap, + current_user_v2p, + mail_write_to_me, + mail_get_from_me, + mail_not_full_me, + mail_not_empty_me, +}; +pub use manager::{ + add_task, + fetch_task, + call_test, + mail_write_to_pid, + mail_not_full_pid, + mail_user_token_pid, }; -pub use manager::add_task; pub use pid::{PidHandle, pid_alloc, KernelStack}; +pub use priority::{ + TaskPriority, +}; + +//===================================================================== +// 以下部分的代ç 都和进程调度相关 +//===================================================================== pub fn suspend_current_and_run_next() { // There must be an application running. let task = take_current_task().unwrap(); @@ -45,6 +74,7 @@ pub fn suspend_current_and_run_next() { pub fn exit_current_and_run_next(exit_code: i32) { // take from Processor let task = take_current_task().unwrap(); + kernel_println!("exit current task is {}",task.pid.0); // **** hold current PCB lock let mut inner = task.acquire_inner_lock(); // Change status to Zombie @@ -86,3 +116,7 @@ lazy_static! { pub fn add_initproc() { add_task(INITPROC.clone()); } + +//===================================================================== +// ä»¥ä¸‹éƒ¨åˆ†çš„ä»£ç æ˜¯ä¸ºäº†å®žçŽ°ç³»ç»Ÿè°ƒç”¨ã€‚ç›®å‰æ”¯æŒçš„和进程相关的系统调用,有: +//===================================================================== diff --git a/os/src/task/pid.rs b/os/src/task/pid.rs index 7cfdb83d8176817d671c118a1adddbe9f7fbebb4..17fc62edc23a19fb2eb508dc1d9c8a01bd1f5d36 100644 --- a/os/src/task/pid.rs +++ b/os/src/task/pid.rs @@ -62,6 +62,7 @@ pub fn kernel_stack_position(app_id: usize) -> (usize, usize) { (bottom, top) } +//å†…æ ¸æ ˆå¯ä»¥æ ¹æ®è¿›ç¨‹ç¼–å·æ¥è‡ªåŠ¨ä¸ºè¿›ç¨‹åˆ†é…地å€å“¦ pub struct KernelStack { pid: usize, } diff --git a/os/src/task/priority.rs b/os/src/task/priority.rs new file mode 100644 index 0000000000000000000000000000000000000000..c16bb1e9682c9b1a52dc4ff2877dd1083a819ed6 --- /dev/null +++ b/os/src/task/priority.rs @@ -0,0 +1,24 @@ + +use crate::config::TASK_PRIORITY_INIT; + +#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)] +pub struct TaskPriority(pub usize); + +impl From<usize> for TaskPriority{ + fn from(v: usize) -> Self { Self(v) } +} +impl From<TaskPriority> for usize { + fn from(v: TaskPriority) -> Self { v.0 } +} + +impl TaskPriority{ + pub fn new() -> Self { + TaskPriority(TASK_PRIORITY_INIT) + } + pub fn get_priority(&self)-> TaskPriority { + TaskPriority(self.0) + } + pub fn set_priority(&mut self, prio: TaskPriority){ + self.0 = prio.0; + } +} \ No newline at end of file diff --git a/os/src/task/processor.rs b/os/src/task/processor.rs index e6895c408b0c4024aea406d753221543671145a7..a0384c15c1ac51c5027c030e560801e65411b9d6 100644 --- a/os/src/task/processor.rs +++ b/os/src/task/processor.rs @@ -2,7 +2,19 @@ use super::TaskControlBlock; use alloc::sync::Arc; use core::cell::RefCell; use lazy_static::*; -use super::{fetch_task, TaskStatus}; +use super::{ + fetch_task, + TaskStatus, + TaskPriority, + // set_priority, +}; +use crate::mm::{ + VirtAddr, + PhysAddr, +}; +use crate::fs::{ + MPipe, +}; use super::__switch; use crate::trap::TrapContext; @@ -40,7 +52,8 @@ impl Processor { task_inner.task_status = TaskStatus::Running; drop(task_inner); // release - self.inner.borrow_mut().current = Some(task); + // 先把å„ç§å˜é‡å˜äº†ï¼Œç„¶åŽcurrent修改,然åŽè¿›å…¥switchå‡½æ•°é‡Œé¢ + self.inner.borrow_mut().current = Some(task);//å¯ä»¥è®¤ä¸ºæ˜¯è½¬ç§»äº†æ‰€æœ‰æƒ unsafe { __switch( idle_task_cx_ptr2, @@ -50,9 +63,11 @@ impl Processor { } } } + //é—®é¢˜ï¼šä¸ºä»€ä¹ˆéœ€è¦æŠŠå½“å‰ä»»åŠ¡â€œå–出æ¥â€ï¼Ÿ pub fn take_current(&self) -> Option<Arc<TaskControlBlock>> { self.inner.borrow_mut().current.take() } + //这个函数会把taskå¤åˆ¶ä¸€ä»½ï¼Œæ‰€ä»¥å¹¶ä¸åƒä¸Šé¢é‚£ä¸ªå‡½æ•°ä¸€æ ·ç›´æŽ¥æ‰€æœ‰æƒéƒ½å˜äº† pub fn current(&self) -> Option<Arc<TaskControlBlock>> { self.inner.borrow().current.as_ref().map(|task| Arc::clone(task)) } @@ -84,6 +99,54 @@ pub fn current_trap_cx() -> &'static mut TrapContext { current_task().unwrap().acquire_inner_lock().get_trap_cx() } + +//===================================================================== +// ä»¥ä¸‹éƒ¨åˆ†çš„ä»£ç æ˜¯ä¸ºäº†å®žçŽ°ç³»ç»Ÿè°ƒç”¨ã€‚ç›®å‰æ”¯æŒçš„和进程相关的系统调用,有: +//===================================================================== +pub fn set_priority(prio:TaskPriority){ + let task = current_task().unwrap(); + task.set_priority(prio); +} + +pub fn mmap(start: usize, len: usize, port: usize) -> isize{ + let task = current_task().unwrap(); + task.mmap(start, len, port) +}//函数结æŸè‡ªåŠ¨é‡Šæ”¾é” + +pub fn munmap(start: usize, len: usize) -> isize{ + let task = current_task().unwrap(); + task.munmap(start,len) +} + +pub fn current_user_v2p(va:VirtAddr)->Option<PhysAddr>{ + let task = current_task().unwrap(); + task.v2p(va) +} + +pub fn mail_write_to_me()-> Option<Arc<MPipe>>{ + let task = current_task().unwrap(); + debug!("PROCESSOR::mail_write_to_me..."); + task.mail_create_from_pipe() +} + +//注æ„ï¼è¿™é‡Œè¿”回的是文件æè¿°ç¬¦ +pub fn mail_get_from_me()->Option<usize>{ + let task = current_task().unwrap(); + debug!("PROCESSOR::mail_get_from_me..."); + task.mail_get() +} + +pub fn mail_not_full_me()->Option<bool>{ + let task = current_task().unwrap(); + task.mail_not_full() +} + +pub fn mail_not_empty_me()->Option<bool>{ + let task = current_task().unwrap(); + task.mail_not_empty() +} + + pub fn schedule(switched_task_cx_ptr2: *const usize) { let idle_task_cx_ptr2 = PROCESSOR.get_idle_task_cx_ptr2(); unsafe { diff --git a/os/src/task/stride.rs b/os/src/task/stride.rs new file mode 100644 index 0000000000000000000000000000000000000000..c5a6d9c063d670bfb90afb491390d55dd7fbacaf --- /dev/null +++ b/os/src/task/stride.rs @@ -0,0 +1,42 @@ +// // for stride +// // 代ç 结构还需è¦å†ä¼˜åŒ–一下 +// extern crate alloc; + +// use crate::config::BIG_STRIDE; +// use super::get_task_priority; + + +// /* +// 注æ„ï¼šåªæœ‰å¤„于ready状æ€çš„进程会被放在这里é¢ã€‚ +// å› æ¤è¿™ä¸ªè°ƒåº¦ç®—法åªéœ€è¦ç®€å•进行分装。 +// 注æ„ï¼ï¼ï¼ä½†æ˜¯åœ¨task管ç†çš„éƒ¨åˆ†ï¼Œæ¯æ¬¡åˆ‡æ¢è¿›ç¨‹ç‰è¿›ç¨‹çŠ¶æ€æ”¹å˜æ—¶ä¹Ÿè¦æ”¹å˜å † +// */ + +// #[derive(Copy, Clone, PartialEq)] +// pub struct TaskStride{ +// task: usize,//è¿™ä¸ªè¿›ç¨‹çš„ç¼–å· +// stride: usize +// } +// impl TaskStride{ +// pub fn new(tsk:usize)-> Self{ +// TaskStride{ +// task:tsk, +// stride:0 as usize, +// } +// } +// // pub fn set_task_number(&mut self,tsk:usize){ +// // self.task = tsk; +// // } +// pub fn get_task_number(&self)->usize{ +// self.task +// } +// pub fn get_my_stride(&self) -> usize{ +// self.stride +// } +// fn get_stride_pass(&self)->usize{ +// BIG_STRIDE / get_task_priority(self.get_task_number()) +// } +// pub fn run_me(&mut self){ +// self.stride += self.get_stride_pass(); +// } +// } \ No newline at end of file diff --git a/os/src/task/switch.S b/os/src/task/switch.S index 262511fe7aae9f561b7873a4c1c987b2936bdc41..d346a757c22749e8a017fe9350219db44af13015 100644 --- a/os/src/task/switch.S +++ b/os/src/task/switch.S @@ -12,11 +12,13 @@ __switch: # current_task_cx_ptr2: &*const TaskContext, # next_task_cx_ptr2: &*const TaskContext # ) + # a0ä½œä¸ºç¬¬ä¸€ä¸ªå‡½æ•°å‚æ•°ï¼Œä¿å˜çš„æ˜¯å‡½æ•°è¿”回地å€çš„åœ°å€ # push TaskContext to current sp and save its address to where a0 points to addi sp, sp, -13*8 - sd sp, 0(a0) + sd sp, 0(a0) #将地å€a0å˜å‚¨çš„东西(task_cx_ptr)拿出æ¥èµ‹å€¼ç»™sp # fill TaskContext with ra & s0-s11 - sd ra, 0(sp) + sd ra, 0(sp) #地å€ä¸ºa0的地方,现在也是地å€ä¸ºsp的地方,å˜å‚¨çš„æ˜¯TaskContext的开始地å€ï¼Œ + # åŒæ—¶ä¹Ÿæ˜¯TaskContextä¸çš„ra,所以把地å€ä¸ºa0的地方å˜å‚¨çš„åœ°å€æ‹¿å‡ºæ¥äº¤ç»™ra .set n, 0 .rept 12 SAVE_SN %n diff --git a/os/src/task/task.rs b/os/src/task/task.rs index ee5fc53e1b51174a84778c329d303b530d6469b3..f7f1adb1bfc34a48869616d518c0eec16be4b453 100644 --- a/os/src/task/task.rs +++ b/os/src/task/task.rs @@ -4,18 +4,31 @@ use crate::mm::{ KERNEL_SPACE, VirtAddr, translated_refmut, + PhysAddr, }; use crate::trap::{TrapContext, trap_handler}; use crate::config::{TRAP_CONTEXT}; -use super::TaskContext; +use super::{ + TaskContext, + TaskPriority, +}; use super::{PidHandle, pid_alloc, KernelStack}; use alloc::sync::{Weak, Arc}; use alloc::vec; use alloc::vec::Vec; use alloc::string::String; use spin::{Mutex, MutexGuard}; -use crate::fs::{File, Stdin, Stdout}; +use crate::fs::{ + File, + Stdin, + Stdout, + Mail, + MailBox, + MPipe, + make_mpipe, +}; +// #[derive(Copy, Clone, PartialEq)] pub struct TaskControlBlock { // immutable pub pid: PidHandle, @@ -25,15 +38,17 @@ pub struct TaskControlBlock { } pub struct TaskControlBlockInner { - pub trap_cx_ppn: PhysPageNum, - pub base_size: usize, - pub task_cx_ptr: usize, - pub task_status: TaskStatus, - pub memory_set: MemorySet, - pub parent: Option<Weak<TaskControlBlock>>, - pub children: Vec<Arc<TaskControlBlock>>, + pub trap_cx_ppn: PhysPageNum,//指出了应用地å€ç©ºé—´ä¸çš„ Trap 上下文(详è§ç¬¬å››ç« )被放在的物ç†é¡µå¸§çš„物ç†é¡µå·ã€‚ + pub base_size: usize,//应用数æ®ä»…有å¯èƒ½å‡ºçŽ°åœ¨åº”ç”¨åœ°å€ç©ºé—´ä½ŽäºŽ base_size å—节的区域ä¸ã€‚借助它我们å¯ä»¥æ¸…楚的知é“应用有多少数æ®é©»ç•™åœ¨å†…å˜ä¸ã€‚ + pub task_cx_ptr: usize,//指出一个暂åœçš„ä»»åŠ¡çš„ä»»åŠ¡ä¸Šä¸‹æ–‡åœ¨å†…æ ¸åœ°å€ç©ºé—´ï¼ˆæ›´ç¡®åˆ‡çš„è¯´æ˜¯åœ¨è‡ªèº«å†…æ ¸æ ˆï¼‰ä¸çš„ä½ç½®ï¼Œç”¨äºŽä»»åŠ¡åˆ‡æ¢ã€‚ + pub task_status: TaskStatus,//维护当å‰è¿›ç¨‹çš„æ‰§è¡Œçжæ€ã€‚ + pub memory_set: MemorySet,// + pub task_priority: TaskPriority,//add + pub parent: Option<Weak<TaskControlBlock>>,//指å‘当å‰è¿›ç¨‹çš„父进程(如果å˜åœ¨çš„è¯ï¼‰ã€‚æ³¨æ„æˆ‘们使用 Weak è€Œéž Arc æ¥åŒ…裹å¦ä¸€ä¸ªä»»åŠ¡æŽ§åˆ¶å—ï¼Œå› æ¤è¿™ä¸ªæ™ºèƒ½æŒ‡é’ˆå°†ä¸ä¼šå½±å“父进程的引用计数。 + pub children: Vec<Arc<TaskControlBlock>>,//则将当å‰è¿›ç¨‹çš„æ‰€æœ‰å进程的任务控制å—以 Arc 智能指针的形å¼ä¿å˜åœ¨ä¸€ä¸ªå‘é‡ä¸ï¼Œè¿™æ ·æ‰èƒ½å¤Ÿæ›´æ–¹ä¾¿çš„æ‰¾åˆ°å®ƒä»¬ã€‚ pub exit_code: i32, pub fd_table: Vec<Option<Arc<dyn File + Send + Sync>>>, + pub mailbox:MailBox,//add } impl TaskControlBlockInner { @@ -89,6 +104,7 @@ impl TaskControlBlock { task_cx_ptr: task_cx_ptr as usize, task_status: TaskStatus::Ready, memory_set, + task_priority: TaskPriority::new(), parent: None, children: Vec::new(), exit_code: 0, @@ -100,6 +116,7 @@ impl TaskControlBlock { // 2 -> stderr Some(Arc::new(Stdout)), ], + mailbox: MailBox::new(), }), }; // prepare TrapContext in user space @@ -145,6 +162,32 @@ impl TaskControlBlock { // make the user_sp aligned to 8B for k210 platform user_sp -= user_sp % core::mem::size_of::<usize>(); + // å› ä¸ºçŽ°åœ¨spawn䏿”¯æŒå‚æ•°ï¼Œæ‰€ä»¥å°±å…ˆè¿™æ ·å§ + // push arguments on user stack + user_sp -= (args.len() + 1) * core::mem::size_of::<usize>(); + let argv_base = user_sp; + let mut argv: Vec<_> = (0..=args.len()) + .map(|arg| { + translated_refmut( + memory_set.token(), + (argv_base + arg * core::mem::size_of::<usize>()) as *mut usize + ) + }) + .collect(); + *argv[args.len()] = 0; + for i in 0..args.len() { + user_sp -= args[i].len() + 1; + *argv[i] = user_sp; + let mut p = user_sp; + for c in args[i].as_bytes() { + *translated_refmut(memory_set.token(), p as *mut u8) = *c; + p += 1; + } + *translated_refmut(memory_set.token(), p as *mut u8) = 0; + } + // make the user_sp aligned to 8B for k210 platform + user_sp -= user_sp % core::mem::size_of::<usize>(); + // **** hold current PCB lock let mut inner = self.acquire_inner_lock(); // substitute memory_set @@ -164,13 +207,20 @@ impl TaskControlBlock { *inner.get_trap_cx() = trap_cx; // **** release current PCB lock } + + //fork在åšä»€ä¹ˆå‘¢ï¼Ÿ pub fn fork(self: &Arc<TaskControlBlock>) -> Arc<TaskControlBlock> { // ---- hold parent PCB lock let mut parent_inner = self.acquire_inner_lock(); // copy user space(include trap context) + //但是这个实际上用ä¸åˆ° let memory_set = MemorySet::from_existed_user( + //å¤åˆ¶ä¸€ä»½ä¸€æ¨¡ä¸€æ ·çš„用户空间 + //确实······感觉这里å¤åˆ¶è¿™ä¸€ä»½å‡ºæ¥ï¼Œå°±æ˜¯ä¸ºäº†å˜æˆä¸€ä¸ªæ•°æ®ç»“æž„å˜èµ·æ¥ï¼Œå¥½åƒä»€ä¹ˆä½œç”¨ä¹Ÿæ²¡æœ‰ã€‚ + //å› ä¸ºçœŸçš„task被执行的时候,用到的是exec里é¢å–出æ¥çš„memory_setå‘€ &parent_inner.memory_set ); + //å–出å¤åˆ¶å‡ºæ¥çš„空间的物ç†é¡µå· let trap_cx_ppn = memory_set .translate(VirtAddr::from(TRAP_CONTEXT).into()) .unwrap() @@ -181,6 +231,7 @@ impl TaskControlBlock { let kernel_stack_top = kernel_stack.get_top(); // push a goto_trap_return task_cx on the top of kernel stack let task_cx_ptr = kernel_stack.push_on_top(TaskContext::goto_trap_return()); + // copy fd table let mut new_fd_table: Vec<Option<Arc<dyn File + Send + Sync>>> = Vec::new(); for fd in parent_inner.fd_table.iter() { @@ -199,10 +250,12 @@ impl TaskControlBlock { task_cx_ptr: task_cx_ptr as usize, task_status: TaskStatus::Ready, memory_set, - parent: Some(Arc::downgrade(self)), + task_priority: TaskPriority::new(), + parent: Some(Arc::downgrade(self)),//似乎这里是弱引用? children: Vec::new(), exit_code: 0, fd_table: new_fd_table, + mailbox: MailBox::new(),//邮箱并ä¸èƒ½å’Œçˆ¶è¿›ç¨‹å…±äº«ï¼Œä¸ç„¶å‡ ä¸ªå‡½æ•°ä¹‹é—´äº’ç›¸ä¼ é€’ä¿¡æ¯å°±æ˜¯åœ¨èƒ¡æ‰¯äº† }), }); // add child @@ -216,10 +269,213 @@ impl TaskControlBlock { task_control_block // ---- release parent PCB lock } + + // 这个函数å‡è®¾å·²ç»åœ¨è°ƒç”¨å‰å–出了elf_data,å¯ä»¥ç›´æŽ¥æ‹¿æ¥ç”¨äº†å“¦~ + // 会返回一个新建的进程控制å—.这个新建的进程控制å—,会把 + // pub fn spawn(&self, elf_data: &[u8]) -> isize{ + pub fn spawn_from(self: &Arc<TaskControlBlock>, elf_data: &[u8], args: Vec<String>) -> Arc<TaskControlBlock>{ + // memory_set with elf program headers/trampoline/trap context/user stack + let (memory_set, mut user_sp, entry_point) = MemorySet::from_elf(elf_data); + let trap_cx_ppn = memory_set + .translate(VirtAddr::from(TRAP_CONTEXT).into()) + .unwrap() + .ppn(); + + // [lab7]add + // push arguments on user stack + user_sp -= (args.len() + 1) * core::mem::size_of::<usize>(); + let argv_base = user_sp; + let mut argv: Vec<_> = (0..=args.len()) + .map(|arg| { + translated_refmut( + memory_set.token(), + (argv_base + arg * core::mem::size_of::<usize>()) as *mut usize + ) + }) + .collect(); + *argv[args.len()] = 0; + for i in 0..args.len() { + user_sp -= args[i].len() + 1; + *argv[i] = user_sp; + let mut p = user_sp; + for c in args[i].as_bytes() { + *translated_refmut(memory_set.token(), p as *mut u8) = *c; + p += 1; + } + *translated_refmut(memory_set.token(), p as *mut u8) = 0; + } + // make the user_sp aligned to 8B for k210 platform + user_sp -= user_sp % core::mem::size_of::<usize>(); + + + // alloc a pid and a kernel stack in kernel space + let pid_handle = pid_alloc(); + let kernel_stack = KernelStack::new(&pid_handle); + let kernel_stack_top = kernel_stack.get_top(); + // push a task context which goes to trap_return to the top of kernel stack + let task_cx_ptr = kernel_stack.push_on_top(TaskContext::goto_trap_return()); + + //å‡ ä¹Žå°±å’Œnewå‡½æ•°ä¸€æ ·ï¼Œå”¯ä¸€çš„åŒºåˆ«åœ¨äºŽnew的时候还è¦å»ºç«‹è¿›ç¨‹ä¹‹é—´çš„父å关系 + // ---- hold parent PCB lock + let mut parent_inner = self.acquire_inner_lock(); + // copy fd table + let mut new_fd_table: Vec<Option<Arc<dyn File + Send + Sync>>> = Vec::new(); + for fd in parent_inner.fd_table.iter() { + if let Some(file) = fd { + new_fd_table.push(Some(file.clone())); + } else { + new_fd_table.push(None); + } + } + let task_control_block = Arc::new(TaskControlBlock { + pid: pid_handle, + kernel_stack, + inner: Mutex::new(TaskControlBlockInner { + trap_cx_ppn, + base_size: user_sp, + task_cx_ptr: task_cx_ptr as usize, + task_status: TaskStatus::Ready, + memory_set, + task_priority: TaskPriority::new(), + parent: Some(Arc::downgrade(self)), + children: Vec::new(), + exit_code: 0, + fd_table: new_fd_table, + mailbox: MailBox::new(),//邮箱并ä¸èƒ½å’Œçˆ¶è¿›ç¨‹å…±äº«ï¼Œä¸ç„¶å‡ ä¸ªå‡½æ•°ä¹‹é—´äº’ç›¸ä¼ é€’ä¿¡æ¯å°±æ˜¯åœ¨èƒ¡æ‰¯äº† + }), + }); + // add child + parent_inner.children.push(task_control_block.clone()); + // modify kernel_sp in trap_cx + // prepare TrapContext in user space + + //let trap_cx = task_control_block.acquire_inner_lock().get_trap_cx(); + let mut trap_cx = TrapContext::app_init_context( + entry_point, + user_sp, + KERNEL_SPACE.lock().token(), + kernel_stack_top, + trap_handler as usize, + ); + trap_cx.x[10] = args.len(); + trap_cx.x[11] = argv_base; + *task_control_block.acquire_inner_lock().get_trap_cx() = trap_cx; + // return + task_control_block + // ---- release parent PCB lock + } + +//===================================================================== +// sys_calls +//===================================================================== + pub fn getpid(&self) -> usize { self.pid.0 } + pub fn set_priority(&self,prio:TaskPriority){ + // **** hold current PCB lock + let mut inner = self.acquire_inner_lock(); + inner.task_priority.set_priority(prio); + // **** release current PCB lock + } + pub fn get_priority(&self) -> TaskPriority{ + // **** hold current PCB lock + let inner = self.acquire_inner_lock(); + inner.task_priority.get_priority() + // **** release current PCB lock + } + + pub fn mmap(&self,start: usize, len: usize, port: usize) -> isize{ + // **** hold current PCB lock + let mut inner = self.acquire_inner_lock(); + inner.memory_set.mmap(start, len, port) + // **** release current PCB lock + } + pub fn munmap(&self,start: usize, len: usize) -> isize{ + // **** hold current PCB lock + let mut inner = self.acquire_inner_lock(); + inner.memory_set.munmap(start, len) + // **** release current PCB lock + } + + pub fn v2p(&self,va:VirtAddr)->Option<PhysAddr>{ + let inner = self.acquire_inner_lock(); + inner.memory_set.v2p(va) + } + + // let mut inner = task.acquire_inner_lock(); + // let (pipe_read, pipe_write) = make_pipe(); + // let read_fd = inner.alloc_fd(); + // inner.fd_table[read_fd] = Some(pipe_read); + // let write_fd = inner.alloc_fd(); + // inner.fd_table[write_fd] = Some(pipe_write); + + //mail_write,æ„æ€æ˜¯ä¸çŸ¥é“是è°ï¼Œåæ£æœ‰äººç»™æˆ‘写了一æ¡é‚®ä»¶ï¼Œè¦æˆ‘å˜èµ·æ¥ + //这也就表明,事实上我这个进程å³ä½¿å¹¶æ²¡æœ‰åœ¨è¿è¡Œï¼Œä¹Ÿå¾—能调用这个函数 + //但是事实上这个函数并ä¸å…³å¿ƒé‚®ä»¶æ˜¯ä»€ä¹ˆï¼Œè¿™ä¸ªå‡½æ•°åªç®¡åˆ›å»ºæ–°çš„pipe,用æ¥å˜å‚¨è‡ªå·± + //如果返回值是None,说明创建失败了 + //需è¦è¿”回的是文件æè¿°ç¬¦,是用æ¥å†™çš„ + pub fn mail_create_from_pipe(&self)->Option<Arc<MPipe>>{ + kernel_println!("TaskControlblock::mail_create_from_pipe...pid is {}",self.pid.0); + // **** hold current PCB lock + let mut inner = self.acquire_inner_lock(); + // kernel_println!("TaskControlblock::mail_create_from_pipe...pid is {}",self.pid.0); + //ï¼ï¼ï¼ï¼ï¼ä¸€å®šè¦å…ˆåˆ¤æ– + //如果邮箱满了那就ä¸èƒ½å†™äº† + if inner.mailbox.can_add_mail(){ + let (mpipe_read, mpipe_write) = make_mpipe(); + let read_fd = inner.alloc_fd(); + inner.fd_table[read_fd] = Some(mpipe_read); + // ç»™ç›®æ ‡è¿›ç¨‹åˆ†é…read_fdå°±å¯ä»¥äº† + // 写pipe的文件æè¿°ç¬¦ä¸éœ€è¦å˜å“¦ + // let write_fd = inner.alloc_fd(); + // inner.fd_table[write_fd] = Some(pipe_write); + let mail = Mail::new(read_fd); + inner.mailbox.add_mail(mail); + drop(inner); + Some(mpipe_write) + }else{ + drop(inner); + None + } + // **** release current PCB lock + } + pub fn mail_get(&self)->Option<usize>{ + kernel_println!("TaskControlblock::mail_get...pid is {}",self.pid.0); + // **** hold current PCB lock + let mut inner = self.acquire_inner_lock(); + // kernel_println!("TaskControlblock::mail_create_from_pipe...pid is {}",self.pid.0); + //ï¼ï¼ï¼ï¼ï¼ä¸€å®šè¦å…ˆåˆ¤æ– + //如果邮箱满了那就ä¸èƒ½å†™äº† + //å› ä¸ºä¹‹å‰ä¼šè¿›è¡Œåˆ¤æ–,如果没有å—符è¦å†™ï¼Œå°±ä¸ä¼šåˆ›å»ºé‚®ç®±äº† + //如果还有邮件 + if let Some(mail) = inner.mailbox.get_mail(){ + // if let Some(mpipe_read) = inner.fd_table[mail.get_read_fd()]{//就是文件æè¿°ç¬¦ç¡®å®žå¯¹åº”了一个mail + // return S + // }else{ + // warn!("no mail to read"); + // } + return Some(mail.get_read_fd());//返回能读mail的文件æè¿°ç¬¦å³å¯ + // ç»™ç›®æ ‡è¿›ç¨‹åˆ†é…read_fdå°±å¯ä»¥äº† + // 写pipe的文件æè¿°ç¬¦ä¸éœ€è¦å˜å“¦ + }else{ + None + } + // **** release current PCB lock + } + pub fn mail_not_full(&self)->Option<bool>{ + let inner = self.acquire_inner_lock(); + return Some(inner.mailbox.can_add_mail()); + } + pub fn mail_not_empty(&self) ->Option<bool>{ + let inner = self.acquire_inner_lock(); + return Some(inner.mailbox.can_read_mail()); + } + pub fn call_test(&self){ + let inner = self.acquire_inner_lock(); + kernel_println!("TaskControlBlock::call_test"); + } } #[derive(Copy, Clone, PartialEq)] @@ -227,4 +483,5 @@ pub enum TaskStatus { Ready, Running, Zombie, + // Exited, } \ No newline at end of file diff --git a/os/src/timer.rs b/os/src/timer.rs index 92d50e3ade2b54f5b935d44f7948bb72c12b7ff8..8fcf5b8461ff70e495dba1860c076706cce48586 100644 --- a/os/src/timer.rs +++ b/os/src/timer.rs @@ -5,14 +5,25 @@ use crate::config::CLOCK_FREQ; const TICKS_PER_SEC: usize = 100; const MSEC_PER_SEC: usize = 1000; +#[repr(C)] +#[derive(Debug,Clone,Copy)] +pub struct TimeVal { + pub sec: usize, + pub usec: usize, +} + +//时钟周期数 pub fn get_time() -> usize { time::read() } +//毫秒数 pub fn get_time_ms() -> usize { + trace!("in get_time_ms,{},{},{},{}",get_time(),CLOCK_FREQ,MSEC_PER_SEC,time::read() / (CLOCK_FREQ / MSEC_PER_SEC)); time::read() / (CLOCK_FREQ / MSEC_PER_SEC) } pub fn set_next_trigger() { + trace!("timer::set_next_trigger....new timer is {}",get_time() + CLOCK_FREQ / TICKS_PER_SEC); set_timer(get_time() + CLOCK_FREQ / TICKS_PER_SEC); -} \ No newline at end of file +} diff --git a/os/src/trap/mod.rs b/os/src/trap/mod.rs index f83560b2948c72335c9e87e4beabfb27f71d4a51..c0a4e91469729a30af963832bc3634b83e88b102 100644 --- a/os/src/trap/mod.rs +++ b/os/src/trap/mod.rs @@ -1,4 +1,5 @@ mod context; +// use crate::sbi::shutdown; use riscv::register::{ mtvec::TrapMode, @@ -12,15 +13,21 @@ use riscv::register::{ stval, sie, }; -use crate::syscall::syscall; +use crate::syscall::{ + syscall5, +}; use crate::task::{ exit_current_and_run_next, suspend_current_and_run_next, current_user_token, current_trap_cx, + // TASK_MANAGER, }; use crate::timer::set_next_trigger; use crate::config::{TRAP_CONTEXT, TRAMPOLINE}; +// use crate::timer::set_next_trigger; +// use crate::timer::{get_time,get_time_ms}; +// use crate::config::MAX_RUN_TIME_MS; global_asm!(include_str!("trap.S")); @@ -46,6 +53,7 @@ pub fn enable_timer_interrupt() { #[no_mangle] pub fn trap_handler() -> ! { + // debug!("in trap_handler......"); set_kernel_trap_entry(); let scause = scause::read(); let stval = stval::read(); @@ -55,18 +63,27 @@ pub fn trap_handler() -> ! { let mut cx = current_trap_cx(); cx.sepc += 4; // get system call return value - let result = syscall(cx.x[17], [cx.x[10], cx.x[11], cx.x[12]]); + // let result = syscall(cx.x[17], [cx.x[10], cx.x[11], cx.x[12]]); + let result = syscall5(cx.x[17], [cx.x[10], cx.x[11], cx.x[12], cx.x[13], cx.x[14]]); // cx is changed during sys_exec, so we have to call it again cx = current_trap_cx(); cx.x[10] = result as usize; } + //æ“ä½œç³»ç»Ÿæ€Žä¹ˆçŸ¥é“æ•°æ®è¯»å¥½ï¼Ÿ + //OS请求device读数æ®ï¼Œç„¶åŽdevice读好之åŽå‘èµ·ä¸æ– + //但是在我们这次实验里é¢ï¼Œæ˜¯ç›´æŽ¥è¯»çš„ã€‚ä½¿ç”¨ä¸æ–&&DMA工作é‡è¿˜æ˜¯å¾ˆå¤§çš„ + //ç¡¬ä»¶åœ¨è¿›å…¥çš„æ—¶å€™è¿›è¡Œä¸æ–å±è”½ã€‚ + //å†…æ ¸åœ¨æ‰§è¡Œè¿‡ç¨‹ä¸æ˜¯å¦å…è®¸åµŒå¥—ä¸æ–,å–å†³äºŽå†…æ ¸çš„å®žçŽ°ã€‚ Trap::Exception(Exception::StoreFault) | Trap::Exception(Exception::StorePageFault) | Trap::Exception(Exception::InstructionFault) | Trap::Exception(Exception::InstructionPageFault) | Trap::Exception(Exception::LoadFault) | Trap::Exception(Exception::LoadPageFault) => { - println!( + //问题:是å¦å¯ä»¥åªæ¢å‡ºè¿›ç¨‹çš„一部分? + //如果没有页机制,那么整个进程æ¢å‡ºåŽ»å¾ˆå¥½ã€‚ä½†æ˜¯åœ¨æœ‰äº†é¡µæœºåˆ¶ä¹‹åŽï¼Œå°±å¹¶ä¸æ˜¯å¾ˆæœ‰å¿…è¦æŠŠæ•´ä¸ªè¿›ç¨‹éƒ½æ¢å‡ºåŽ»ã€‚ + //å„ç§ä¸œè¥¿éƒ½æœ‰è‡ªå·±é€‚用的场景 + kernel_println!( "[kernel] {:?} in application, bad addr = {:#x}, bad instruction = {:#x}, core dumped.", scause.cause(), stval, @@ -76,24 +93,30 @@ pub fn trap_handler() -> ! { exit_current_and_run_next(-2); } Trap::Exception(Exception::IllegalInstruction) => { - println!("[kernel] IllegalInstruction in application, core dumped."); + kernel_println!("[kernel] IllegalInstruction in application, core dumped."); // illegal instruction exit code exit_current_and_run_next(-3); } - Trap::Interrupt(Interrupt::SupervisorTimer) => { - set_next_trigger(); - suspend_current_and_run_next(); + Trap::Interrupt(Interrupt::SupervisorTimer) => {//å‘çŽ°æ—¶é’Ÿä¸æ–: + // println!("[kernel] trap_handler::Exception::SupervisorTimer"); + set_next_trigger();//å…ˆé‡æ–°è®¾ç½®ä¸€ä¸ª 10ms 的计时器 + suspend_current_and_run_next();//调用 suspend_current_and_run_next 函数暂åœå½“å‰åº”用并切æ¢åˆ°ä¸‹ä¸€ä¸ª } _ => { + // exit_current_and_run_next(-10); + // kernel_println!("[kernel] Upsupported trap of app {},core dumped.", get_task_current()); + // exit_current_and_run_next(); panic!("Unsupported trap {:?}, stval = {:#x}!", scause.cause(), stval); } } //println!("before trap_return"); + // drop(tm); trap_return(); } #[no_mangle] pub fn trap_return() -> ! { + //æ ¹æ®æ±‡ç¼–的结果,确实是进入了trap return函数没错 set_user_trap_entry(); let trap_cx_ptr = TRAP_CONTEXT; let user_satp = current_user_token(); diff --git a/reports/lab1.md b/reports/lab1.md new file mode 100644 index 0000000000000000000000000000000000000000..b49a2a2c6c135184744331f3b62edaaf5822b02d --- /dev/null +++ b/reports/lab1.md @@ -0,0 +1,73 @@ +# RustOS-lab1 + +é™ˆå¼ èŒ 2017013678 计74 + +[TOC] + +## ä¸€ã€æœ¬æ¬¡å®žéªŒå¢žåŠ äº†ä»€ä¹ˆ + +1. 模仿println!实现了error!ã€warn!ç‰5ä¸ªå® +2. 支æŒå‘½ä»¤è¡Œå‚æ•°LOG=xxx,å¯ä»¥åœ¨è¿è¡Œæ—¶æŒ‡å®šè¾“出ç‰çº§ + +## 二ã€å®žéªŒæˆªå›¾ + +` make run LOG=info` + + + +`make run LOG=trace` + + + +## 三ã€å›žç”问题 + +### 为了方便 os 处ç†ï¼Œï¼æ€è½¯ä»¶ä¼šå°† S æ€å¼‚常/䏿–委托给 S æ€è½¯ä»¶ï¼Œè¯·æŒ‡å‡ºæœ‰å“ªäº›å¯„å˜å™¨è®°å½•了委托信æ¯ï¼Œrustsbi 委托了哪些异常/䏿–?(也å¯ä»¥ç›´æŽ¥ç»™å‡ºå¯„å˜å™¨çš„值) + +æŠŠä¸æ–全部委托给了S层。midelegå’Œmedelegåˆ†åˆ«è®°å½•äº†ä¸æ–和异常委托的信æ¯ã€‚è®¾ç½®å®Œä¸æ–异常委托åŽï¼Œä¸¤ä¸ªå¯„å˜å™¨çš„ä¿¡æ¯å¦‚下: + +| register | value | +| -------- | ------ | +| medeleg | 0xb1ab | +| mideleg | 0x222 | + +### 请å¦ä¹ gdb 调试工具的使用(这对åŽç»è°ƒè¯•很é‡è¦),并通过 gdb 简å•è·Ÿè¸ªä»Žæœºå™¨åŠ ç”µåˆ°è·³è½¬åˆ° 0x80200000 的简å•过程。åªéœ€è¦æè¿°é‡è¦çš„跳转å³å¯ï¼Œåªéœ€è¦æè¿°åœ¨ qemu 上的情况。 + +#### 上电检查 + +上电之åŽä»Ž0x0000开始的ä½ç½®éƒ½æ˜¯unimpï¼Œç¬¬ä¸€æ¡æŒ‡ä»¤ä½äºŽ0x1000。 + +0x1000æ‰§è¡Œå‡ æ¡æŒ‡ä»¤åŽè·³è½¬åˆ°0x80000000,也就是进入了rustsbi,代ç 如下。 + +```assembly +0x1000: auipc t0,0x0 + │ 0x1004: addi a1,t0,32 + │ 0x1008: csrr a0,mhartid + │ 0x100c: ld t0,24(t0) + │ 0x1010: jr t0 +``` + +#### 进入rustsbi + +进入rustsbiåŽï¼Œ + +- 先会跳转到start函数,执行和hart_id有关的åˆå§‹åŒ–æ“作,然åŽä¼šè¿›å…¥mainå‡½æ•°ï¼Œç»§ç»æ‰§è¡Œå…³äºŽhartçš„åˆå§‹åŒ– +- main函数所åšçš„主è¦å·¥ä½œæ˜¯ä¸ºä»ŽMæ€è¿›å…¥Sæ€åšå‡†å¤‡ï¼Œç±»ä¼¼ä»ŽSæ€trap进了Mæ€ä¹‹åŽè¦è¿”回Sæ€ã€‚ +- 调用_start_trapç‰å‡½æ•°å¯¹ä¸æ–异常处ç†è¿›è¡Œåˆå§‹åŒ–ï¼Œè®¾ç½®ä¸æ–处ç†å‡½æ•°çš„å…¥å£åœ°å€ï¼Œè®¾ç½®ä¸æ–模å¼ä¸ºç›´æŽ¥ä¸æ–模å¼ã€‚ +- 接下æ¥å¯¹rustsbi进行åˆå§‹åŒ–,å†å°†Mæ€ä¸æ–和异常都委托给S层。 +- 输出rustsbi的欢迎信æ¯ã€‚ +- 最åŽï¼Œä¿®æ”¹mepc到OSçš„èµ·å§‹åœ°å€ `0x80200000`,修改MPP,å†é€šè¿‡ç³»ç»Ÿè°ƒç”¨å°±è¿›å…¥äº†Sæ€ï¼Œè·³è½¬åˆ°OS的起始地å€å¼€å§‹è¿è¡Œæ“作系统。 + +#### è¿è¡ŒOS + +使用下é¢çš„æŒ‡ä»¤å¯ä»¥å¯¹os.binè¿›è¡Œåæ±‡ç¼–,å‘现os的地å€ç¡®å®žæ˜¯ä»Ž0x80200000开始的。 + +`rust-objdump -S -d target/riscv64gc-unknown-none-elf/release/os > target/riscv64gc-unknown-none-elf/release/os.s -x --arch-name=riscv64 ` + +## å››ã€ä½ 对本次实验设计åŠéš¾åº¦/工作é‡çš„çœ‹æ³•ï¼Œä»¥åŠæœ‰å“ªäº›éœ€è¦æ”¹è¿›çš„地方 + +ä½œä¸ºç†Ÿæ‚‰ä»£ç æ¡†æž¶å’Œç†Ÿæ‚‰Rustè¯è¨€çš„第一个实验我觉得难度比较åˆé€‚。 + +代ç å†…å®¹å»ºè®®å†æ”¹è¿›ä¸€ä¸‹ï¼Œå› 为这次实验的内容å³ä½¿å®Œå…¨ä¸çœ‹æŒ‡å¯¼ä¹¦çš„任何内容,就对ç€println!å®é”改也能改出æ¥ï¼Œè€Œä¸”代ç é‡ä»¿ä½›ä¸å˜åœ¨ä¸€æ ·çš„å°ã€‚ + +真æ£çš„工作é‡åœ¨ç†è§£ä»£ç 框架和rustsbi,简而言之就是希望å¯ä»¥æœ‰å’Œä»£ç 框架关系更大一些的实验内容。 + diff --git a/reports/lab1/info.png b/reports/lab1/info.png new file mode 100644 index 0000000000000000000000000000000000000000..2f37ec914cc838822fb6dd1abee4ebaac55b48d9 Binary files /dev/null and b/reports/lab1/info.png differ diff --git a/reports/lab1/trace.png b/reports/lab1/trace.png new file mode 100644 index 0000000000000000000000000000000000000000..dedcb48ab661ece334a6640286000e54545f9666 Binary files /dev/null and b/reports/lab1/trace.png differ diff --git a/reports/lab2.md b/reports/lab2.md new file mode 100644 index 0000000000000000000000000000000000000000..036bad021196cbfdebef7730d2c84e955bbe266e --- /dev/null +++ b/reports/lab2.md @@ -0,0 +1,141 @@ +# RustOS-lab2 + +é™ˆå¼ èŒ 2017013678 计74 + +[TOC] + +## æœ¬æ¬¡å®žéªŒå¢žåŠ äº†ä»€ä¹ˆ + +1. 在batch.rs文件ä¸å¢žåŠ public函数,å…许其他模å—获得当å‰è¿è¡Œè¿›ç¨‹çš„地å€ç©ºé—´(left,right)以åŠç”¨æˆ·æ ˆåœ°å€ç©ºé—´(left2,right2) +2. 在系统调用syswriteå¤„è¿›è¡Œæ£€æŸ¥ï¼Œåªæœ‰åœ¨ä»¥ä¸Šä¸¤ä¸ªç©ºé—´èŒƒå›´å†…的内容å…许输出。 + +## 回ç”问题 + +### 问题1 + +<<<<<<< HEAD +æ£ç¡®è¿›å…¥ U æ€åŽï¼Œç¨‹åºçš„特å¾è¿˜åº”有:使用 S æ€ç‰¹æƒæŒ‡ä»¤ï¼Œè®¿é—® S æ€å¯„å˜å™¨åŽä¼šæŠ¥é”™ã€‚ç›®å‰ç”±äºŽä¸€äº›å…¶ä»–åŽŸå› ï¼Œè¿™äº›é—®é¢˜ä¸å¤ªå¥½æµ‹è¯•,请åŒå¦ä»¬å¯ä»¥è‡ªè¡Œæµ‹è¯•这些内容(å‚考 [å‰ä¸‰ä¸ªæµ‹ä¾‹](https://github.com/DeathWish5/rCore_tutorial_tests/tree/master/user/src/bin) ),æè¿°ç¨‹åºå‡ºé”™è¡Œä¸ºï¼ŒåŒæ—¶æ³¨æ„æ³¨æ˜Žä½ ä½¿ç”¨çš„ sbi åŠå…¶ç‰ˆæœ¬ã€‚ + +修改测试程åºï¼Œåœ¨Uæ€ç¨‹åºä¸åŠ å…¥è®¿é—®Sæ€å¯„å˜å™¨çš„代ç ,è¿è¡Œå¾—到以下报错信æ¯ã€‚å› ä¸ºUæ€æ²¡æœ‰è®¿é—®Sæ€å¯„å˜å™¨çš„æƒé™ï¼Œå› æ¤è®¿é—®Sæ€å¯„å˜å™¨ä¼šå¼•å…¥StoreFault,就会跳转到异常处ç†ä¸StoreFaultçš„ä½ç½®ï¼Œç»“æŸè¿™ä¸ªtask,è¿è¡Œä¸‹ä¸€ä¸ªtask。 + +```toml +[INFO][kernel] Loading app_1 +Into Test store_fault, we will insert an invalid store operation... +Kernel should kill this application! +[kernel] PageFault in application, core dumped. +``` +======= +> æ£ç¡®è¿›å…¥ U æ€åŽï¼Œç¨‹åºçš„特å¾è¿˜åº”有:使用 S æ€ç‰¹æƒæŒ‡ä»¤ï¼Œè®¿é—® S æ€å¯„å˜å™¨åŽä¼šæŠ¥é”™ã€‚ç›®å‰ç”±äºŽä¸€äº›å…¶ä»–åŽŸå› ï¼Œè¿™äº›é—®é¢˜ä¸å¤ªå¥½æµ‹è¯•,请åŒå¦ä»¬å¯ä»¥è‡ªè¡Œæµ‹è¯•这些内容(å‚考 [å‰ä¸‰ä¸ªæµ‹ä¾‹](https://github.com/DeathWish5/rCore_tutorial_tests/tree/master/user/src/bin) ),æè¿°ç¨‹åºå‡ºé”™è¡Œä¸ºï¼ŒåŒæ—¶æ³¨æ„æ³¨æ˜Žä½ ä½¿ç”¨çš„ sbi åŠå…¶ç‰ˆæœ¬ã€‚ + +修改测试程åºï¼Œåœ¨Uæ€ç¨‹åºä¸åŠ å…¥è®¿é—®Sæ€å¯„å˜å™¨çš„代ç ,è¿è¡Œå¾—到以下报错信æ¯ã€‚å› ä¸ºUæ€æ²¡æœ‰è®¿é—®Sæ€å¯„å˜å™¨çš„æƒé™ï¼Œå› æ¤è®¿é—®Sæ€å¯„å˜å™¨ä¼šæŠ¥ivalid instruction,从而产生rustssbi-panic,进而退出。 + + + +我使用的sbi是0.1.1版。 +>>>>>>> ch2 + +### 问题2 + +请结åˆç”¨ä¾‹ç†è§£ [trap.S](https://github.com/rcore-os/rCore-Tutorial-v3/blob/ch2/os/src/trap/trap.S) ä¸ä¸¤ä¸ªå‡½æ•° `__alltraps` å’Œ `__restore` 的作用,并回ç”å¦‚ä¸‹å‡ ä¸ªé—®é¢˜: + +#### 问题2.1 + +L40: 刚进入 `__restore` 时,`a0` 代表了什么值。请指出 `__restore` 的两ç§ä½¿ç”¨æƒ…景。 + +<<<<<<< HEAD +刚进入 `__restore` 时,`a0` ä»£è¡¨çš„æ˜¯å†…æ ¸æ ˆçš„æ ˆé¡¶åœ°å€ã€‚ +======= +刚进入 `__restore` 时,`a0` ä»£è¡¨çš„æ˜¯å†…æ ¸æ ˆçš„æ ˆé¡¶åœ°å€ã€‚使用__restore的两个场景如下: +>>>>>>> ch2 + +- 场景1: 准备进入Uæ€ï¼Œè¿è¡Œç”¨æˆ·ç¨‹åº +- 场景2: 䏿–/异常处ç†ç»“æŸï¼Œè¦è¿”回Uæ€ + +#### 问题2.2 + +L46-L51: è¿™å‡ è¡Œæ±‡ç¼–ä»£ç 特殊处ç†äº†å“ªäº›å¯„å˜å™¨ï¼Ÿè¿™äº›å¯„å˜å™¨çš„çš„å€¼å¯¹äºŽè¿›å…¥ç”¨æˆ·æ€æœ‰ä½•æ„义?请分别解释。 + +把å˜å‚¨åœ¨æ ˆä¸Šçš„sstatusã€sepcå’Œsscratch寄å˜å™¨ä»Žæ ˆä¸Šæ¢å¤å‡ºæ¥ã€‚ + +sstatus表示了进入trap之å‰çš„特æƒçº§ï¼›sepcå˜å‚¨çš„æ˜¯ç”¨æˆ·æ€è¿›å…¥trap之å‰çš„虚拟地å€ï¼ˆç›®å‰è¿˜æ²¡æœ‰å®žçŽ°ï¼Œæ‰€ä»¥å¤§æ¦‚æ˜¯å®žé™…åœ°å€ï¼‰ï¼Œsscratch寄å˜å™¨å˜å‚¨çš„æ˜¯ç”¨æˆ·æ ˆæ ˆé¡¶ã€‚(接下æ¥è¦è®©sp指å‘ç”¨æˆ·æ ˆæ ˆé¡¶ï¼Œsscratch指å‘å†…æ ¸æ ˆæ ˆé¡¶ï¼‰ã€‚ + +``` +ld t0, 32*8(sp) +ld t1, 33*8(sp) +ld t2, 2*8(sp) +csrw sstatus, t0 +csrw sepc, t1 +csrw sscratch, t2 +``` + +#### 问题2.3 + +L53-L59: 为何跳过了 `x2` å’Œ `x4`? + +å› ä¸º`x2`就是`sp`,`tp(x4)` é™¤éžæˆ‘们手动出于一些特殊用途使用它,å¦åˆ™ä¸€èˆ¬ä¹Ÿä¸ä¼šè¢«ç”¨åˆ°ï¼Œåœ¨è¿›å…¥ä¸æ–的时候这些寄å˜å™¨ä¹Ÿæ²¡æœ‰å˜åœ¨å†…æ ¸æ ˆé‡Œã€‚ + +``` +ld x1, 1*8(sp) +ld x3, 3*8(sp) +.set n, 5 +.rept 27 + LOAD_GP %n + .set n, n+1 +.endr +``` + +#### 问题2.4 + +L63: 该指令之åŽï¼Œ`sp` å’Œ `sscratch` ä¸çš„值分别有什么æ„义? + +åœ¨è¿™æ¡æŒ‡ä»¤ä¹‹åŽï¼Œsp指å‘çš„æ˜¯ç”¨æˆ·æ ˆæ ˆé¡¶ï¼Œsscratch指å‘å†…æ ¸æ ˆæ ˆé¡¶ã€‚ + +``` +csrrw sp, sscratch, sp +``` + +#### 问题2.5 + +` __restore`:ä¸å‘生状æ€åˆ‡æ¢åœ¨å“ªä¸€æ¡æŒ‡ä»¤ï¼Ÿä¸ºä½•该指令执行之åŽä¼šè¿›å…¥ç”¨æˆ·æ€ï¼Ÿ + +状æ€å‘生切æ¢åœ¨sret。CPU执行该指令会åšï¼šCPU从S-Modeå˜ä¸ºU-Mode,pc指å‘sepcï¼ˆä¹Ÿå°±æ˜¯é™·å…¥å†…æ ¸å‰çš„æŒ‡ä»¤åœ°å€ï¼‰ï¼Œsp指å‘ç”¨æˆ·æ ˆæ ˆé¡¶ã€‚ + +#### 问题2.6 + +从 U æ€è¿›å…¥ S æ€æ˜¯å“ªä¸€æ¡æŒ‡ä»¤å‘生的? + +Uæ€è¿›å…¥Sæ€æ˜¯åœ¨sbi.rsä¸è°ƒç”¨sbi_call(xxx)æ—¶å†…è”æ±‡ç¼–代ç çš„ecall指令会使程åºç”±Uæ€è¿›å…¥Sæ€ã€‚ + +### 问题3 + +> æè¿°ç¨‹åºé™·å…¥å†…æ ¸çš„ä¸¤å¤§åŽŸå› æ˜¯ä¸æ–和异常,请问 riscv64 支æŒå“ªäº›ä¸æ–ï¼å¼‚常?如何判æ–è¿›å…¥å†…æ ¸æ˜¯ç”±äºŽä¸æ–还是异常?æè¿°é™·å…¥å†…æ ¸æ—¶çš„å‡ ä¸ªé‡è¦å¯„å˜å™¨åŠå…¶å€¼ã€‚ + +riscv64将䏿–/异常类型ä¿å˜åœ¨scause寄å˜å™¨ä¸ï¼Œä¸‹è¡¨ä¸å±•ç¤ºäº†ä¸æ–和异常的编å·ã€‚判æ–䏿–/异常åªéœ€è¦çœ‹æœ€é«˜ä½æ˜¯1ï¼ˆä¸æ–)还是0(异常)。 + + + +é™·å…¥å†…æ ¸æ—¶çš„é‡è¦å¯„å˜å™¨ï¼š + +| 寄å˜å™¨ | 功能 | +| -------- | ------------------------------------------------------------ | +| ssstatus | ä¿å˜ä¸æ–/异常å±è”½ä½ã€è¿”回åŽçš„特æƒçº§ã€ä¸æ–模å¼ï¼ˆdirect or vector)ç‰ä¿¡æ¯ | +| scause | ä¿å˜ä¸æ–/å¼‚å¸¸ç¼–å· | +| sepc | 记录å‘ç”Ÿä¸æ–å‰çš„æŒ‡ä»¤çš„è™šæ‹Ÿåœ°å€ | +| sscratch | é™·å…¥å†…æ ¸å‰ä¿å˜çš„æ˜¯å†…æ ¸æ ˆåœ°å€ï¼Œé™·å…¥å†…æ ¸åŽä¿å˜ç”¨æˆ·æ ˆåœ°å€ | + +(以上内容å‚考:The RISC-V Instruction Set Manual) + +<<<<<<< HEAD +======= +### 问题4 + +>å¯¹äºŽä»»ä½•ä¸æ–, __alltraps ä¸éƒ½éœ€è¦ä¿å˜æ‰€æœ‰å¯„å˜å™¨å—ï¼Ÿä½ æœ‰æ²¡æœ‰æƒ³åˆ°ä¸€äº›åŠ é€Ÿ __alltraps çš„æ–¹æ³•ï¼Ÿç®€å•æè¿°ä½ çš„æƒ³æ³•ã€‚ + +一般还是需è¦ä¿å˜å¯„å˜å™¨çš„ï¼Œå› ä¸ºä¸æ–&&异常有å¯èƒ½å‘生在任何地方,所以需è¦ç¡®ä¿ä¸Šä¸‹æ–‡çš„一致性。 + +åŠ é€Ÿçš„æ–¹æ³•æœ‰æ˜¯æœ‰ï¼Œä½†æ˜¯æ„Ÿè§‰æ€»ä½“ä¸Šè¿˜æ˜¯å¾—ä¸å¿å¤±ã€‚比如说,å¯ä»¥ä¿®æ”¹CPU架构,为ecallè®¾è®¡ç‰¹æ®Šçš„ä¸Šä¸‹æ–‡åˆ‡æ¢æŒ‡ä»¤å’Œå¯„å˜å™¨ï¼Œæˆ–者约定调用ecallåªä¿å˜æŸäº›ç‰¹å®šå¯„å˜å™¨ã€‚但是问题在于多ä¿å˜å‡ 个寄å˜å™¨å¹¶ä¸ä¼šæœ‰å¤šä¹ˆæ˜Žæ˜¾çš„æ€§èƒ½æŸå¤±ï¼Œä½†æ˜¯è¿™äº›ä¼˜åŒ–å´ä¼šç ´åå®‰å…¨æ€§ï¼Œè€Œä¸”è¿™æ ·çš„CPUå’ŒOS看起æ¥ä¸€ç‚¹éƒ½ä¸ä¼˜ç¾Žã€‚ + +>>>>>>> ch2 +## ä½ å¯¹æœ¬æ¬¡å®žéªŒè®¾è®¡åŠéš¾åº¦/工作é‡çš„çœ‹æ³•ï¼Œä»¥åŠæœ‰å“ªäº›éœ€è¦æ”¹è¿›çš„地方 + +我觉得难度比较åˆé€‚。 diff --git a/reports/lab2/panic.png b/reports/lab2/panic.png new file mode 100644 index 0000000000000000000000000000000000000000..dd779139a41155f041beedc76fa15abe8883cb48 Binary files /dev/null and b/reports/lab2/panic.png differ diff --git a/reports/lab2/q1.png b/reports/lab2/q1.png new file mode 100644 index 0000000000000000000000000000000000000000..1c73a2529e063e19b115a0c35084bc761d1bca06 Binary files /dev/null and b/reports/lab2/q1.png differ diff --git a/reports/lab2/result.png b/reports/lab2/result.png new file mode 100644 index 0000000000000000000000000000000000000000..3574951af174636b93e05a55c91595b213b1bd97 Binary files /dev/null and b/reports/lab2/result.png differ diff --git a/reports/lab2/scause.png b/reports/lab2/scause.png new file mode 100644 index 0000000000000000000000000000000000000000..921924a0500aa4cd196855ea3ba4d3e8f8fed9dd Binary files /dev/null and b/reports/lab2/scause.png differ diff --git a/reports/lab3.md b/reports/lab3.md new file mode 100644 index 0000000000000000000000000000000000000000..0fe595e49c61cb6ec1dce4e78ce435064dde113e --- /dev/null +++ b/reports/lab3.md @@ -0,0 +1,125 @@ +# RustOS-lab3 实验报告 + +é™ˆå¼ èŒ 2017013678 计74 + +[TOC] + +## æœ¬æ¬¡å®žéªŒå¢žåŠ äº†ä»€ä¹ˆï¼Ÿ + +1. 将实验2的对sys_write的检查è¿ç§»è¿‡æ¥ã€‚为什么需è¦é‡æ–°å†™å‘¢ï¼Œå› 为å…许多程åºå¹¶è¡Œä¹‹åŽï¼Œç”¨æˆ·æ ˆåœ°å€å’Œç”¨æˆ·ç¨‹åºåœ°å€éƒ½å‘生了å˜åŒ–,所以需è¦ä¿®æ”¹åœ°å€åˆ¤æ–。 +2. å¢žåŠ äº†ç³»ç»Ÿè°ƒç”¨ï¼šsys_get_timeå’Œsys_set_priority +3. å¢žåŠ äº†stride调度算法,验è¯å‘现strideå’Œä¼˜å…ˆçº§æˆæ£æ¯” +4. 为了使用BinaryHeapï¼Œå¢žåŠ äº†chapter4ä¸çš„动æ€å†…å˜åˆ†é…,但事实是最åŽè¿˜æ˜¯é€‰æ‹©äº†ç”¨æ•°ç»„å½¢å¼å˜å‚¨æ¯ä¸ªè¿›ç¨‹çš„stride相关信æ¯ã€‚ +5. åšå‡ºä»¥ä¸Šå¤„ç†çš„åŽŸå› åœ¨äºŽï¼šè¦é€‰æ‹©æ‰§è¡Œçš„è¿›ç¨‹è¦æ»¡è¶³å¤„于Ready状æ€ï¼Œä½†æ˜¯stride最å°çš„进程并ä¸ä¸€å®šæ˜¯Readyçš„ã€‚å¯¹æ¤æœ‰ä¸¤ç§è§£å†³æ–¹å¼ï¼šä¸€æ˜¯åªæŠŠReady状æ€çš„è¿›ç¨‹æ”¾è¿›å †é‡Œï¼Œä½†æ˜¯æ¤ç§è§£å†³æ–¹å¼éœ€è¦åœ¨è¿›ç¨‹çŠ¶æ€æ”¹å˜æ—¶æ›´æ–°å †çš„ä¿¡æ¯ï¼Œå–å‡ºè¿›ç¨‹çš„æœ€åæƒ…å†µæ—¶é—´å¤æ‚度为O(NlogN),而且代ç éžå¸¸ä¸ç®€æ´ã€‚å¦ä¸€ç§æ–¹æ³•æ˜¯æŠŠæ‰€æœ‰è¿›ç¨‹éƒ½æ”¾è¿›å †é‡Œï¼Œæ¯æ¬¡å–å‡ºæ—¶æ£€æŸ¥æ˜¯å¦æ»¡è¶³Ready状æ€ï¼Œæœ€å情况下å–å‡ºè¿›ç¨‹æ—¶é—´å¤æ‚度也è¦O(NlogN);两ç§è§£å†³æ–¹å¼å‡ä¸å¦‚直接选择使用数组å˜å‚¨è¿›ç¨‹ã€‚ + + + +## 简ç”作业 + +### 问题1 + +> ç®€è¦æè¿°è¿™ä¸€ç« çš„è¿›ç¨‹è°ƒåº¦ç–略。何时进行进程切æ¢ï¼Ÿå¦‚何选择下一个è¿è¡Œçš„è¿›ç¨‹ï¼Ÿå¦‚ä½•å¤„ç†æ–°åŠ å…¥çš„è¿›ç¨‹ï¼Ÿ + +åœ¨æ¯æ¬¡æ—¶é’Ÿä¸æ–产生的时候进行进程切æ¢ã€‚ + +使用stride算法选择下一个è¿è¡Œçš„进程。 + +æš‚æ—¶æ— æ³•å¤„ç†æ–°åŠ å…¥çš„è¿›ç¨‹ï¼Œå› ä¸ºæœ¬ç« é‡‡ç”¨çš„æ–¹å¼æ˜¯åœ¨æ“作系统å¯åŠ¨çš„æ—¶å€™ï¼Œæ£€æŸ¥æœ‰å¤šå°‘ä¸ªå¾…è¿è¡Œç¨‹åºå¹¶ä¸€æ¬¡æ€§æŠŠæ‰€æœ‰è¿›ç¨‹éƒ½åŠ è½½è¿›æ¥ï¼Œè¿›ç¨‹ç®¡ç†æ¨¡å—也是在åˆå§‹åŒ–的时候就确定了大å°ã€‚ + +### 问题2 + +> 在 C 版代ç ä¸ï¼ŒåŒæ ·å®žçŽ°äº†ç±»ä¼¼ RR 的调度算法,但是由于没有 VecDeque è¿™æ ·ç›´æŽ¥å¯ç”¨çš„æ•°æ®ç»“构(Rust很棒对ä¸å¯¹ï¼‰ï¼ŒC 版代ç çš„å®žçŽ°ä¸¥æ ¼æ¥è®²å˜åœ¨ä¸€å®šé—®é¢˜ã€‚大致情况如下:C版代ç ä½¿ç”¨ä¸€ä¸ªè¿›ç¨‹æ± ï¼ˆä¹Ÿå°±æ˜¯ä¸€ä¸ª struct proc 的数组)管ç†è¿›ç¨‹è°ƒåº¦ï¼Œå½“一个时间片用尽åŽï¼Œé€‰æ‹©ä¸‹ä¸€ä¸ªè¿›ç¨‹é€»è¾‘在 [chapter3相关代ç ](https://github.com/DeathWish5/ucore-Tutorial/blob/ch3/kernel/proc.c#L60-L74) ,也就是当第 i å·è¿›ç¨‹ç»“æŸåŽï¼Œä¼šä»¥ i -> max_num -> 0 -> i 的顺åºéåŽ†è¿›ç¨‹æ± ï¼Œç›´åˆ°æ‰¾åˆ°ä¸‹ä¸€ä¸ªå°±ç»ªè¿›ç¨‹ã€‚C ç‰ˆä»£ç æ–°è¿›ç¨‹åœ¨è°ƒåº¦æ± ä¸çš„ä½ç½®é€‰æ‹©è§ [chapter5相关代ç ](https://github.com/DeathWish5/ucore-Tutorial/blob/ch5/kernel/proc.c#L90-L98) ,也就是从头到尾éåŽ†è¿›ç¨‹æ± ï¼Œæ‰¾åˆ°ç¬¬ä¸€ä¸ªç©ºä½ã€‚ + +#### (2-1) 在目å‰è¿™ä¸€ç« (chapter3)两ç§è°ƒåº¦ç–略有实质ä¸åŒå—? + +> 考虑在一个完整的 os ä¸ï¼Œéšæ—¶å¯èƒ½æœ‰æ–°è¿›ç¨‹äº§ç”Ÿï¼Œè¿™ä¸¤ç§ç–略是å¦å®žè´¨ç›¸åŒï¼Ÿ + +ç›®å‰æ²¡æœ‰å®žè´¨ä¸åŒã€‚由于目å‰çš„æ‰€æœ‰è¿›ç¨‹éƒ½ä¼šä¸€æ¬¡æ€§åŠ è½½å®Œæˆï¼Œmax_num是ä¸å˜çš„ï¼Œå› æ¤åªæœ‰æ•ˆçŽ‡ä¸Šå˜åœ¨ä¸€å®šå·®åˆ«ï¼Œä½†æ˜¯æ¯ä¸ªè¿›ç¨‹éƒ½æœ‰æœºä¼šè½®è½¬åˆ°ï¼Œä¹Ÿæ»¡è¶³å…ˆäº§ç”Ÿçš„进程先执行的特点。 + +但是在完整的osä¸ï¼Œéšæ—¶éƒ½ä¼šç”¨æ–°çš„è¿›ç¨‹äº§ç”Ÿï¼Œä¸‹é¢çš„é—®é¢˜å°±æ˜¯å…ˆäº§ç”Ÿçš„è¿›ç¨‹åŽæ‰§è¡Œçš„å例。 + +#### (2-2) 其实 C 版调度ç–略在公平性上å˜åœ¨æ¯”较大的问题 + +> 请找到一个进程产生和结æŸçš„æ—¶é—´åºåˆ—,使得在该调度算法下å‘ç”Ÿï¼šå…ˆåˆ›å»ºçš„è¿›ç¨‹åŽæ‰§è¡Œçš„çŽ°è±¡ã€‚ä½ éœ€è¦ç»™å‡ºç±»ä¼¼ä¸‹é¢ä¾‹å的信æ¯ï¼ˆæœ‰æ›´è¯¦ç»†çš„åˆ†æžæè¿°æ›´å¥½ï¼Œä½†å°½é‡ç²¾ç®€ï¼‰ã€‚åŒæ—¶æŒ‡å‡ºè¯¥åºåˆ—åœ¨ä½ å®žçŽ°çš„ stride è°ƒåº¦ç®—æ³•ä¸‹é¡ºåºæ˜¯æ€Žæ ·çš„? + +ä¾‹å¦‚è¿›ç¨‹æ± å¤§å°ä¸º4。 + +###### 调度顺åºä¸¾ä¾‹ + +| 时间点 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | +| -------- | --------------- | ---- | ---- | ---- | ------ | -------------- | ------ | ---- | ---- | +| è¿è¡Œè¿›ç¨‹ | | p1 | p2 | p3 | p4 | p1 | p2 | p6 | p5 | +| 事件 | p1,p2,p3,p4产生 | | | | p4ç»“æŸ | p5产生,p3ç»“æŸ | p6产生 | | | +| | | | | | | | | | | + +进程产生顺åºï¼š1,2,3,4,5,6ï¼› + +进程执行顺åºï¼š1,2,3,4,1,2,6,5ï¼› + +å› ä¸ºä¸è€ƒè™‘进程优先级,å…许进程在其他进程执行时结æŸã€‚å› æ¤å¯ä»¥è¿›ç¨‹æ± é‡Œä¸‹æ ‡ç¼–å·è¾ƒå¤§ä½ç½®çš„进程先结æŸï¼Œä¸‹æ ‡ç¼–å·è¾ƒå°çš„进程åŽç»“æŸï¼Œé‚£ä¹ˆæ–°äº§ç”Ÿçš„进程就会放在é å‰çš„ä½ç½®ï¼Œå°±ä¼šå…ˆæ‰§è¡Œã€‚ + +而在stride算法ä¸ï¼Œåˆšäº§ç”Ÿçš„进程stride=0ï¼Œå› æ¤ä¸€å®šæ˜¯åœ¨äº§ç”Ÿè¿›ç¨‹åŽçš„下一次切æ¢è¿›ç¨‹æ‰§è¡ŒçŠ¶æ€æ—¶å°±ä¼šé©¬ä¸Šæ‰§è¡Œï¼ˆé™¤éžä¸€æ¬¡äº§ç”Ÿå¾ˆå¤šä¸ªè¿›ç¨‹ï¼‰ã€‚ + +### 问题3 + +#### 1.实际情况是轮到P1执行å—? + +并䏿˜¯ï¼Œå½“使用8个bitçš„æ— ç¬¦å·æ•´æ•°å˜å‚¨æ—¶ï¼Œèƒ½è¡¨ç¤ºçš„范围是0~255。在P2执行一个时间片åŽï¼Œä¼šå‘生溢出,导致P2çš„strideåœ¨æ‰§è¡ŒåŽæœ¬æ¥åº”该比P1大,å´ç”±äºŽæº¢å‡ºè€Œå˜å¾—比P1å°äº†ã€‚ + +#### 2.为何能åšåˆ° STRIDE_MAX – STRIDE_MIN <= BigStride / 2? + +æ•°å¦å½’纳法: + +å‡è®¾åœ¨ç¬¬næ¥æ»¡è¶³ `STRIDE_MAX(n) – STRIDE_MIN(n) <= BigStride / 2`,那么在第n+1æ¥ï¼Œä¼šå¢žåŠ çš„ä¸€å®šæ˜¯ `STRIDE_MIN(n)` ï¼Œå¢žåŠ çš„æ¥é•¿ä¸º `PASS(n)`, `STRIDE_MIN(n+1)= min{STRIDE_MIN(n)+PASS(n),STRIDE_MIN2(n)(å³ï¼šç¬¬næ¥æ—¶çš„倒数第2å°çš„stride)}` + +如果 `STRIDE(n)+PASS(n)` 是第n+1æ¥æœ€å°çš„stride, +那么 `STRIDE_MAX(n+1)=STRIDE_MAX(n)` , +å› æ¤ ` STRIDE_MAX(n+1) – STRIDE_MIN(n+1) <=STRIDE_MAX(n) – STRIDE_MIN(n) <= BigStride / 2 ` ä»ç„¶æˆç«‹ + +如果 `STRIDE_MIN2(n)` 是第n+1æ¥æœ€å°çš„stride,那么 `STRIDE_MAX(n+1)=max{STRIDE_MAX(n),STRIDE_MIN(n)+PASS(n)}` 。 +而 `STRIDE_MAX(n)-STRIDE_MIN2(n)<=STRIDE_MAX(n) – STRIDE_MIN(n) <= BigStride / 2 ` , +且 `STRIDE_MIN(n)+PASS(n)-STRIDE_MIN2(n)<=PASS(n)<= BigStride / 2 ` , +å› æ¤ `STRIDE_MAX(n+1)-STRIDE_MIN(n+1) <= BigStride/2` ä»ç„¶æˆç«‹ã€‚ + +综上当第næ¥æ»¡è¶³æ—¶ï¼Œç¬¬n+1æ¥ä»ç„¶æ»¡è¶³ã€‚ + +在åˆå§‹æ¡ä»¶ä¸‹ï¼Œæ‰€æœ‰è¿›ç¨‹çš„Stride都为0,自然满足æ¡ä»¶ã€‚由数å¦å½’纳å¯çŸ¥ï¼Œæ¯ä¸€æ¥éƒ½å¯ä»¥æ»¡è¶³ `STRIDE_MAX – STRIDE_MIN <= BigStride / 2` 。 + +#### 3. 请补全如下 `partial_cmp` 函数(å‡è®¾æ°¸è¿œä¸ä¼šç›¸ç‰ï¼‰ã€‚ + +```rust +use core::cmp::Ordering; +use crate::config::BIG_STRIDE; + +struct Stride(u64); + +impl PartialOrd for Stride { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + if self.0 < other.0{ + if other.0 - self.0 < BigStride as u64 { + return Some(Ordering::Less); + }else{ + return Some(Ordering::Greater); + } + }else { + if self.0 - other.0 < BigStride as u64 { + return Some(Ordering::Less); + }else{ + return Some(Ordering::Greater); + } + } + } +} + +impl PartialEq for Person { + fn eq(&self, other: &Self) -> bool { + false + } +} +``` + +## ä½ å¯¹æœ¬æ¬¡å®žéªŒè®¾è®¡åŠéš¾åº¦/工作é‡çš„çœ‹æ³•ï¼Œä»¥åŠæœ‰å“ªäº›éœ€è¦æ”¹è¿›çš„地方 + +我åšçš„æ—¶å€™è§‰å¾—æ€è·¯æ¯”较清楚,工作é‡ä¹Ÿå¾ˆåˆé€‚,总体æ¥è¯´éš¾åº¦å±žäºŽä¸ç‰å下å§ï½žå‰ä¸¤æ¬¡æ˜¯ä¸æ˜¯æœ‰ç‚¹å¤ªç®€å•了,åªèƒ½å½“æˆç†Ÿæ‚‰Rustè¯æ³•&&代ç 结构了······ + +éœ€è¦æ”¹è¿›çš„地方······å¯èƒ½æ˜¯ç”±äºŽå’Œch2相比架构的改å˜ï¼Œå¯¼è‡´éœ€è¦24K纯手工merge代ç (约ç‰äºŽé‡å†™ï¼‰ï¼Œç¡®å®žæ˜¯æœ‰ç‚¹æƒŠå–œOrz。 \ No newline at end of file diff --git a/reports/lab3/stride.png b/reports/lab3/stride.png new file mode 100644 index 0000000000000000000000000000000000000000..63f834f4ef80e8a38b9d9e75af5036498b96c7b1 Binary files /dev/null and b/reports/lab3/stride.png differ diff --git a/reports/lab4.md b/reports/lab4.md new file mode 100644 index 0000000000000000000000000000000000000000..656ba01a402c10397e31c096a4505b01ae5430d8 --- /dev/null +++ b/reports/lab4.md @@ -0,0 +1,162 @@ +# RustOS-lab4 实验报告 + +é™ˆå¼ èŒ 2017013678 计74 + +[TOC] + +## æœ¬æ¬¡å®žéªŒå¢žåŠ äº†ä»€ä¹ˆï¼Ÿ + +1. å¢žåŠ äº†ç‰©ç†å†…å˜åЍæ€åˆ†é…。在OSå¯åŠ¨æ—¶å¯¹ç‰©ç†å†…å˜åˆ†é…器进行åˆå§‹åŒ–,使得OSä¸çš„物ç†å†…å˜åˆ†é…机制使用我们æä¾›çš„stack分é…ç–略。 +2. å¢žåŠ äº†åˆ†é¡µæœºåˆ¶ï¼Œä¸ºæ¯ä¸ªè¿›ç¨‹æä¾›è™šæ‹Ÿåœ°å€ç©ºé—´å’Œé¡µè¡¨ï¼Œä¸ºæ¯ä¸ªç‰©ç†åœ°å€å»ºç«‹åˆ°è‡ªå·±çš„ä¸€ä¸€æ˜ å°„ä»¥ä¾¿OS在开å¯åˆ†é¡µåŽä»ç„¶èƒ½æ–¹ä¾¿åœ°è®¿é—®ç‰©ç†åœ°å€ã€‚ +3. å¢žåŠ äº†mmapå’Œmunmap系统调用。事实上åªè¦è°ƒç”¨ä»£ç 框架ä¸å·²ç»å†™å¥½çš„函数就å¯ä»¥äº†ï¼Œéœ€è¦è‡ªå·±å®Œæˆçš„函数是对map/unmap的失败情况进行检查。 +4. 修改了get_time系统调用。需è¦ä¿®å¤çš„åŽŸå› æ˜¯ï¼Œè¿™ä¸ªç³»ç»Ÿè°ƒç”¨æ˜¯åœ¨ç”¨æˆ·æ€ä¼ æ¥äº†TimeVal类的地å€ï¼Œåœ¨OS内实现系统调用的时候è¦ä½¿ç”¨å®ƒçš„裸指针访问这个数æ®ã€‚但是用户程åºä¼ æ¥çš„åœ°å€æ˜¯åœ¨è¯¥ä»»åŠ¡ä½¿ç”¨çš„é¡µè¡¨ä¸‹çš„è™šæ‹Ÿåœ°å€ï¼Œä½†æ˜¯æ‰§è¡Œç³»ç»Ÿè°ƒç”¨ä¼šä½¿å¾—OSè¿›å…¥å†…æ ¸æ€ï¼Œ åŒæ—¶ä¹Ÿåˆ‡æ¢åˆ°å†…æ ¸é¡µè¡¨ï¼Œå› æ¤åœ¨å†…æ ¸æ€ä¸‹è®¿é—®åŒæ ·çš„虚拟地å€ï¼Œè‡ªç„¶ä¼šå‘生错误。è¦è¿›è¡Œçš„ä¿®å¤å·¥ä½œæ˜¯ï¼Œå°†è¯¥è™šæ‹Ÿåœ°å€å¯¹åº”的物ç†åœ°å€å–出æ¥ï¼Œç›´æŽ¥é€šè¿‡ç‰©ç†åœ°å€å¯¹åº”的裸指针修改TimeValçš„å€¼ã€‚å› ä¸ºè™½ç„¶è¿›å…¥å†…æ ¸æ€ä¹‹åŽä¹Ÿä»ç„¶ä½¿ç”¨é¡µè¡¨æ˜ 射,但是OS在页表机制å¯åŠ¨çš„æ—¶å€™ï¼Œå°±ä¸ºç‰©ç†é¡µé¢å»ºç«‹äº†ä¸€ä¸€è‡ªæ˜ å°„ï¼Œå› æ¤è¾“入物ç†åœ°å€åœ¨é¡µè¡¨æ˜ 射下就会访问对应的物ç†åœ°å€ã€‚ + +实验结果如下: + + + +è¿è¡Œæµ‹ä¾‹ï¼Œè¾“出结果如下: + + + +## 简ç”作业 + +### 问题1ã€é¡µè¡¨é¡¹ + +> 请列举 SV39 页表页表项的组æˆï¼Œç»“åˆè¯¾å ‚内容,æè¿°å…¶ä¸çš„æ ‡å¿—使œ‰ä½•ä½œç”¨ï¼æ½œåœ¨ä½œç”¨ï¼Ÿ + +页表项的高44ä½è¡¨ç¤ºppn,å³ç‰©ç†é¡µå·ï¼›é¡µè¡¨é¡¹çš„低8使˜¯æ ‡å¿—ä½ï¼šV(表示次页表有效),R(å¯è¯»ï¼‰,W(å¯å†™ï¼‰,Xï¼ˆå¯æ‰§è¡Œï¼‰,U(用户æ€å¯è®¿é—®ï¼‰,GAD本次实验没有用到。 + +åˆ©ç”¨æ ‡å¿—ä½ï¼Œå¯ä»¥å’ŒCPUååŒå·¥ä½œï¼Œæä¾›è®¿é—®æƒé™æŽ§åˆ¶ã€åœ°å€ä¿æŠ¤ç‰åŠŸèƒ½ã€‚ä¾‹å¦‚å½“ä¸€ä¸ªé¡µåœ¨Uæ€å¯è®¿é—®æ—¶å¯ä»¥å°†æ ‡å¿—ä½U置为1ï¼Œè¿™æ ·CPU在执行时就知é“如果一个用户程åºçš„虚拟地å€å¯¹åº”çš„é¡µè¡¨æ ‡å¿—ä½ä¸ºUï¼Œå› æ¤å°±å¯ä»¥å…许其进行地å€è½¬æ¢ï¼Œè¿›è€Œå…许访问。 + +还å¯ä»¥å¸®åŠ©OS进行修改页表的工作。例如在进行map时,å¯ä»¥ç”¨è™šæ‹Ÿåœ°å€æ‰¾åˆ°å¯¹åº”的页表项并检查validä½ï¼Œæ®æ¤åˆ¤æ–这是新分é…的页表项还是已ç»map过的页表项。 + +### 问题2ã€ç¼ºé¡µ + +> ç¼ºé¡µæŒ‡çš„æ˜¯è¿›ç¨‹è®¿é—®é¡µé¢æ—¶é¡µé¢ä¸åœ¨é¡µè¡¨ä¸æˆ–åœ¨é¡µè¡¨ä¸æ— æ•ˆçš„çŽ°è±¡ï¼Œæ¤æ—¶ MMU å°†ä¼šè¿”å›žä¸€ä¸ªä¸æ–,告知 os 进程内å˜è®¿é—®å‡ºäº†é—®é¢˜ã€‚os é€‰æ‹©å¡«è¡¥é¡µè¡¨å¹¶é‡æ–°æ‰§è¡Œå¼‚å¸¸æŒ‡ä»¤æˆ–è€…æ€æ»è¿›ç¨‹ã€‚ + +#### (2-1-1) 请问哪些异常å¯èƒ½æ˜¯ç¼ºé¡µå¯¼è‡´çš„? + + + +RISC-Vä¸çš„异常ç§ç±»å¦‚上表所示。其ä¸ï¼Œæœ‰å¯èƒ½ç”±äºŽç¼ºé¡µäº§ç”Ÿçš„异常类型是: + +- 12,13,15三ç§ç±»åž‹çš„pagefault + +#### (2-1-2)å‘生缺页时,æè¿°ç›¸å…³çš„é‡è¦å¯„å˜å™¨çš„值(lab2ä¸æè¿°è¿‡çš„å¯ä»¥ç®€å•点) + +é™·å…¥å†…æ ¸æ—¶çš„é‡è¦å¯„å˜å™¨ï¼š + +| 寄å˜å™¨ | 功能 | +| -------- | ------------------------------------------------------------ | +| ssstatus | ä¿å˜ä¸æ–/异常å±è”½ä½ã€è¿”回åŽçš„特æƒçº§ã€ä¸æ–模å¼ï¼ˆdirect or vector)ç‰ä¿¡æ¯ | +| scause | ä¿å˜ä¸æ–/异常编å·ï¼Œäº§ç”Ÿpage fault时,scause为12ã€13或15 | +| sepc | 记录å‘ç”Ÿä¸æ–å‰çš„æŒ‡ä»¤çš„è™šæ‹Ÿåœ°å€ | +| sscratch | é™·å…¥å†…æ ¸å‰ä¿å˜çš„æ˜¯å†…æ ¸æ ˆåœ°å€ï¼Œé™·å…¥å†…æ ¸åŽä¿å˜ç”¨æˆ·æ ˆåœ°å€ | + +(以上内容å‚考:The RISC-V Instruction Set Manual) + + + +> 缺页有两个常è§çš„åŽŸå› ï¼Œå…¶ä¸€æ˜¯ Lazy ç–略,也就是直到内å˜é¡µé¢è¢«è®¿é—®æ‰å®žé™…进行页表æ“作。比如,一个程åºè¢«æ‰§è¡Œæ—¶ï¼Œè¿›ç¨‹çš„ä»£ç æ®µç†è®ºä¸Šéœ€è¦ä»Žç£ç›˜åŠ è½½åˆ°å†…å˜ã€‚但是 os å¹¶ä¸ä¼šé©¬ä¸Šè¿™æ ·åšï¼Œè€Œæ˜¯ä¼šä¿å˜ .text 段在ç£ç›˜çš„ä½ç½®ä¿¡æ¯ï¼Œåœ¨è¿™äº›ä»£ç 第一次被执行时æ‰å®Œæˆä»Žç£ç›˜çš„åŠ è½½æ“作。 + +#### (2-2)è¿™æ ·åšæœ‰å“ªäº›å¥½å¤„? + +è¿™æ ·åšå¯ä»¥èŠ‚çœå¼€é”€ã€‚例如一个æžç«¯æƒ…况是,一个程åºå†™äº†é•¿è¾¾å‡ 个G的代ç ,但是在main函数å´é‡Œé¢ç›´æŽ¥return 0ï¼Œå¦‚æžœæŠŠæ•´ä¸ªå‡½æ•°éƒ½ä¸€æ¬¡æ€§åŠ è½½è¿›å†…å˜ä¸ï¼Œå¼€é”€å¤ªå¤§äº†ã€‚ + +> æ¤å¤– COW(Copy On Write) 也是常è§çš„容易导致缺页的 Lazy ç–略,这个之åŽå†è¯´ã€‚其实,我们的 mmap 也å¯ä»¥é‡‡å– Lazy ç–略,比如:一个用户进程先åŽç”³è¯·äº† 10G 的内å˜ç©ºé—´ï¼Œç„¶åŽç”¨äº†å…¶ä¸ 1M å°±ç›´æŽ¥é€€å‡ºäº†ã€‚æŒ‰ç…§çŽ°åœ¨çš„åšæ³•,我们显然äºå¤§äº†ï¼Œè¿›è¡Œäº†å¾ˆå¤šæ²¡æœ‰æ„义的页表æ“作。 + +#### (2-3-1)è¯·é—®å¤„ç† 10G 连ç»çš„内å˜é¡µé¢ï¼Œéœ€è¦æ“作的页表实际大致å 用多少内å˜(给出数é‡çº§å³å¯)? + +按照实验所用的页表进行估计,æ¯ä¸€é¡µæœ‰4096Byteï¼Œä¹Ÿå³æ¯ä¸€é¡µçš„大尿˜¯4KByte。$10GByte=10 * 2^{10}MByte=10 * 2^{20}KByte=2.5 * 2^{20}$æ¡é¡µè¡¨ã€‚æ¯æ¡é¡µè¡¨å æ®8Byte,总共å 用空间为$8*2.5*2^{20}=20MByte$。 + +#### (2-3-2)è¯·ç®€å•æ€è€ƒå¦‚何æ‰èƒ½åœ¨çŽ°æœ‰æ¡†æž¶åŸºç¡€ä¸Šå®žçŽ° Lazy ç–略,缺页时åˆå¦‚何处ç†ï¼Ÿæè¿°åˆç†å³å¯ï¼Œä¸éœ€è¦è€ƒè™‘实现。 + +现有框架将find_pte_create函数放在MapAreaçš„map函数里é¢è¿›è¡Œè°ƒç”¨ï¼Œç¼ºé¡µæ—¶ç›´æŽ¥é€€å‡ºæ£åœ¨è¿è¡Œçš„用户进程,或者panic退出。 + +如果使用lazyç–略,å¯ä»¥å°†find_pte_create函数放在缺页处ç†å‡½æ•°é‡Œé¢ï¼Œå½“缺页时先寻找/创建pte,如果是å¯ç”¨çš„pte则å¯ä»¥ç»§ç»æ‰§è¡Œï¼›å¦åˆ™è¯´æ˜Žçš„ç¡®äº§ç”Ÿäº†éžæ³•访问,会退出æ£åœ¨è¿è¡Œçš„用户进程。 + +> 缺页的å¦ä¸€ä¸ªå¸¸è§åŽŸå› æ˜¯ swap ç–略,也就是内å˜é¡µé¢å¯èƒ½è¢«æ¢åˆ°ç£ç›˜ä¸Šäº†ï¼Œå¯¼è‡´å¯¹åº”页é¢å¤±æ•ˆã€‚ + +#### (2-4)æ¤æ—¶é¡µé¢å¤±æ•ˆå¦‚何表现在页表项(PTE)上? + +在swap使得页é¢å¤±æ•ˆä¹‹åŽï¼ŒPTE会将Validä½ç½®1。 + +### 问题3ã€åŒé¡µè¡¨ä¸Žå•页表 + +> ä¸ºäº†é˜²èŒƒä¾§ä¿¡é“æ”»å‡»ï¼Œæˆ‘们的 os 使用了åŒé¡µè¡¨ã€‚ä½†æ˜¯ä¼ ç»Ÿçš„è®¾è®¡ä¸€ç›´æ˜¯å•é¡µè¡¨çš„ï¼Œä¹Ÿå°±æ˜¯è¯´ï¼Œç”¨æˆ·çº¿ç¨‹å’Œå¯¹åº”çš„å†…æ ¸çº¿ç¨‹å…±ç”¨åŒä¸€å¼ 页表,åªä¸è¿‡å†…æ ¸å¯¹åº”çš„åœ°å€åªå…è®¸åœ¨å†…æ ¸æ€è®¿é—®ã€‚ + +#### 1.如何更æ¢é¡µè¡¨ï¼Ÿ + +对CPUæ¥è¯´ï¼Œè¿›è¡Œè™šæ‹Ÿåœ°å€åˆ°å®žé™…地å€ä¹‹é—´çš„转æ¢éƒ½æ˜¯ä»Žsatp寄å˜å™¨å–出第一级页表的地å€ï¼Œå†æ®æ¤è®¿é—®äºŒã€ä¸‰çº§é¡µè¡¨ã€‚å› æ¤æ›´æ¢é¡µè¡¨åªéœ€è¦æŠŠæ–°é¡µè¡¨çš„地å€å†™å…¥satp寄å˜å™¨å³å¯ã€‚ + +#### 2.å•é¡µè¡¨æƒ…å†µä¸‹ï¼Œå¦‚ä½•æŽ§åˆ¶ç”¨æˆ·æ€æ— æ³•è®¿é—®å†…æ ¸é¡µé¢ï¼Ÿ + +é¡µè¡¨é¡¹ä¸æœ‰Uä½è¡¨ç¤ºæ˜¯å¦å…许用户æ€è®¿é—®ï¼Œåªéœ€è¦å°†Uä½ç½®0。 + +#### 3. å•页表有何优势?(回ç”åˆç†å³å¯ï¼‰ + +å•é¡µè¡¨æœ€å¤§çš„ä¼˜åŠ¿å°±æ˜¯èŠ‚çœæ›´æ¢é¡µè¡¨çš„开销。在更æ¢é¡µè¡¨æ—¶ï¼Œéœ€è¦ä½¿ç”¨sfence指令æé†’CPU,之å‰åœ¨CPU内缓å˜çš„é¡µè¡¨é¡¹éƒ½å¤±æ•ˆäº†ã€‚è¯»å–æ–°çš„页表就è¦å†æ¬¡æ”¾å˜ï¼Œä»¥sv39为例,一个没有缓å˜è¿‡çš„页表项需è¦è®¿å˜4次,开销éžå¸¸å¤§ï¼Œè€Œé¢‘ç¹æ›´æ¢é¡µè¡¨å°±ä¼šæžå¤§åœ°å¢žåŠ æ”¾å˜æ¬¡æ•°ï¼Œå½±å“性能。 + +#### 4. åŒé¡µè¡¨å®žçŽ°ä¸‹ï¼Œä½•æ—¶éœ€è¦æ›´æ¢é¡µè¡¨ï¼Ÿå‡è®¾ä½ 写一个å•页表æ“ä½œç³»ç»Ÿï¼Œä½ ä¼šé€‰æ‹©ä½•æ—¶æ›´æ¢é¡µè¡¨ï¼ˆå›žç”åˆç†å³å¯ï¼‰ï¼Ÿ + +å•页表和åŒé¡µè¡¨éƒ½éœ€è¦åœ¨åˆ‡æ¢è¿›ç¨‹çš„æ—¶å€™æ›´æ¢é¡µè¡¨ï¼Œå› 为OS为æ¯ä¸€ä¸ªapp都æä¾›ä¸€ä¸ªè™šæ‹Ÿåœ°å€ç©ºé—´ï¼Œè¿™å°±å¯¹åº”ä¸€å¼ é¡µè¡¨ã€‚å•页表æ“作系统在切æ¢è¿›ç¨‹æ—¶æ›´æ¢é¡µè¡¨å³å¯ï¼Œå¹¶æé†’CPU之å‰ç¼“å˜çš„TLBå¯èƒ½å¤±æ•ˆã€‚ + +对于åŒé¡µè¡¨ç³»ç»Ÿï¼Œåœ¨æ‰§è¡Œç”¨æˆ·ç¨‹åºæ—¶è¦ä½¿ç”¨ç”¨æˆ·æ€çš„é¡µè¡¨ï¼Œæ‰§è¡Œå†…æ ¸ç¨‹åºæ—¶è¦ä½¿ç”¨å†…æ ¸çš„é¡µè¡¨ã€‚å› æ¤ï¼Œå¯¹äºŽæœ¬æ¬¡å®žéªŒæ¥è¯´ï¼Œåˆ‡æ¢è¿›ç¨‹çš„æ—¶å€™ä¼štrapè¿›å…¥å†…æ ¸æ€ï¼ŒæŠŠé¡µè¡¨æ›´æ¢æˆkernel的页表,trap处ç†å®Œæ¯•è¿”å›žæ—¶è¦æ›´æ¢æˆæ–°çš„进程的用户æ€é¡µè¡¨ã€‚也就是说切æ¢ä¸€æ¬¡è¿›ç¨‹å°±éœ€è¦æ›´æ¢2次页表。两次切æ¢åˆ†åˆ«åœ¨ä»£ç ä¸å¯¹åº”: + +```rust +//为æ¯ä¸ªapp都ä¿å˜äº†kernel使用的页表,并且在进入trap的时候更新页表 +impl TrapContext { + pub fn set_sp(&mut self, sp: usize) { self.x[2] = sp; } + pub fn app_init_context( + entry: usize, + sp: usize, + kernel_satp: usize, + kernel_sp: usize, + trap_handler: usize, + ) -> Self { + let mut sstatus = sstatus::read(); + sstatus.set_spp(SPP::User); + let mut cx = Self { + x: [0; 32], + sstatus, + sepc: entry, + kernel_satp, + //å°±ä¿å˜åœ¨è¿™é‡Œï¼Œä¸ºæ¯ä¸€ä¸ªè¿›ç¨‹éƒ½ä¿å˜äº†ä¸€ä»½ + kernel_sp, + trap_handler, + }; + cx.set_sp(sp); + cx + } +} +``` + +```rust +//trapæ‰§è¡Œå®Œæ¯•è¿”å›žç”¨æˆ·æ€æ—¶ +#[no_mangle] +pub fn trap_return() -> ! { + set_user_trap_entry(); + let trap_cx_ptr = TRAP_CONTEXT; + let user_satp = current_user_token(); + extern "C" { + fn __alltraps(); + fn __restore(); + } + let restore_va = __restore as usize - __alltraps as usize + TRAMPOLINE; + unsafe { + llvm_asm!("fence.i" :::: "volatile"); + llvm_asm!("jr $0" :: "r"(restore_va), "{a0}"(trap_cx_ptr), "{a1}"(user_satp) :: "volatile"); + } + //trap执行完毕,返回用户æ€ï¼Œæ›´æ¢é¡µè¡¨ï¼Œå¹¶ä¸”刷新TLB + panic!("Unreachable in back_to_user!"); +} +``` + +## ä½ å¯¹æœ¬æ¬¡å®žéªŒè®¾è®¡åŠéš¾åº¦/工作é‡çš„çœ‹æ³•ï¼Œä»¥åŠæœ‰å“ªäº›éœ€è¦æ”¹è¿›çš„地方 + +我觉得这部分还有一些å¯ä»¥æ”¹è¿›çš„地方。 + +第一是å¯ä»¥å‚考去年实验,物ç†å†…å˜åЍæ€åˆ†é…ã€è™šæ‹Ÿåœ°å€1ã€è™šæ‹Ÿåœ°å€2一共分了3次实验进行。这部分相对æ¥è¯´æ˜¯ä¸å¤ªå®¹æ˜“ç†è§£çš„知识点,所以多åšå‡ 次实验总是好的。今年一次性æžå®šæ„Ÿè§‰ç¡®å®žéœ€è¦å¤šç‚¹æ—¶é—´æ¶ˆåŒ–~ + +第二是,实验内容还有改进空间。就是如果自己写的è¯ï¼Œä»£ç 釿¯”è¾ƒå°‘ï¼Œå‡ ä¹Žå”¯ä¸€åšçš„事情就是调用了å„ç§å„æ ·çš„å‡½æ•°ï¼Œåšå®Œæ„Ÿè§‰åƒä»€ä¹ˆéƒ½æ²¡å¹²ä¸€æ ·ã€‚我觉得å¯ä»¥æ”¹æˆå¢žåŠ ä¸€äº›æ›´åŠ æ ¸å¿ƒçš„åŠŸèƒ½çš„ä»£ç 似乎会更好一些。 \ No newline at end of file diff --git a/reports/lab4/result.png b/reports/lab4/result.png new file mode 100644 index 0000000000000000000000000000000000000000..b6815956f2d3bd6aef0cd938d1602a393df56f19 Binary files /dev/null and b/reports/lab4/result.png differ diff --git a/reports/lab4/result2.png b/reports/lab4/result2.png new file mode 100644 index 0000000000000000000000000000000000000000..2857d2df1a2e78017fff171670dc4f5d901a3f3e Binary files /dev/null and b/reports/lab4/result2.png differ diff --git a/reports/lab4/scause.png b/reports/lab4/scause.png new file mode 100644 index 0000000000000000000000000000000000000000..921924a0500aa4cd196855ea3ba4d3e8f8fed9dd Binary files /dev/null and b/reports/lab4/scause.png differ diff --git a/reports/lab5.md b/reports/lab5.md new file mode 100644 index 0000000000000000000000000000000000000000..416223e027dc09ed1b3082af852f94f9de026600 --- /dev/null +++ b/reports/lab5.md @@ -0,0 +1,74 @@ +# RustOS-lab5 实验报告 + +é™ˆå¼ èŒ 2017013678 计74 + +[TOC] + +## æœ¬æ¬¡å®žéªŒå¢žåŠ äº†ä»€ä¹ˆï¼Ÿ + +1. spawn系统调用。和新建一个进程控制å—å‡ ä¹Žä¸€æ ·ï¼Œå”¯ä¸€çš„åŒºåˆ«åœ¨äºŽæ–°å»ºæ—¶éœ€è¦ï¼š + 1. 使用类似exec系统调用的方å¼ï¼Œä»Žæ–‡ä»¶ä¸å°†memory_setç‰åŠ è½½è¿›æ¥ + 2. 新建的进程和当å‰è¿›ç¨‹ä¹‹é—´å»ºç«‹çˆ¶å关系 + 3. æ–°å»ºè¿›ç¨‹åŠ å…¥åˆ°è°ƒåº¦é˜Ÿåˆ—ä¸ + +è¿è¡Œæµ‹ä¾‹ï¼Œè¾“出结果如下: + + + + + +## 简ç”作业 + +### 问题1 + +> fork + exec 的一个比较大的问题是 fork 之åŽçš„内å˜é¡µ/文件ç‰èµ„æºå®Œå…¨æ²¡æœ‰ä½¿ç”¨å°±åºŸå¼ƒäº†ï¼Œé’ˆå¯¹è¿™ä¸€ç‚¹ï¼Œæœ‰ä»€ä¹ˆæ”¹è¿›ç–略? + +改进ç–ç•¥å°±æ˜¯å¢žåŠ äº†spawnç³»ç»Ÿè°ƒç”¨ï¼Œæ–°å»ºä¸€ä¸ªè¿›ç¨‹æŽ§åˆ¶å—æ—¶å°±ç›´æŽ¥ä½¿ç”¨æ–‡ä»¶å¯¹memory_set进行åˆå§‹åŒ–。 + +### 问题2 + +> 其实使用了题(1)çš„ç–略之åŽï¼Œfork + exec 所带æ¥çš„æ— 效资æºçš„问题已ç»åŸºæœ¬è¢«è§£å†³äº†ï¼Œä½†æ˜¯ä»Šå¹´æ¥ fork è¿˜æ˜¯åœ¨è¢«ä¸æ–的批判,那么到底是什么æ£åœ¨â€æ€æ»â€fork?å¯ä»¥å‚考 [论文](https://www.microsoft.com/en-us/research/uploads/prod/2019/04/fork-hotos19.pdf) ,**注æ„**ï¼šå›žç”æ— æ˜Žæ˜¾é”™è¯¯å°±ç»™æ»¡åˆ†ï¼Œå‡ºè¿™é¢˜åªæ˜¯æƒ³å¼•å‘大家的æ€è€ƒï¼Œå®Œå…¨ä¸è¦æ±‚看论文,çƒçƒäº†ï¼Œåˆ«å·äº†ã€‚ + +- éžçº¿ç¨‹å®‰å…¨ã€‚例如æŸä¸€ä¸ªè¿›ç¨‹æ£åœ¨è¿›è¡Œåœ°å€æ˜ å°„ï¼Œå› æ¤æ‹¿ç€heapçš„é”ï¼Œæ¤æ—¶å¦ä¸€ä¸ªè¿›ç¨‹åœ¨æ‰§è¡Œforkæ“ä½œã€‚æ¤æ—¶å¦‚果在å进程ä¸åˆ†é…内å˜ï¼Œå°±ä¼šå‡ºçްæ»é”。 +- 效率ä¸é«˜ï¼Œä¾‹å¦‚问题1ä¸è¯´åˆ°çš„问题。 +- 还会å˜åœ¨ä¸å®‰å…¨çš„问题, + +### 问题3 + +> fork 当年被设计并称é“肯定是有其好处的。请使用 **带åˆå§‹å‚æ•°** çš„ spawn é‡å†™å¦‚下 fork 程åºï¼Œç„¶åŽæè¿° fork 有那些好处。注æ„:使用â€ä¼ªä»£ç â€ä¼ è¾¾æ„æ€å³å¯ï¼Œspawn 接å£å¯ä»¥è‡ªå®šä¹‰ã€‚å¯ä»¥å†™å¤šä¸ªæ–‡ä»¶ã€‚ + +如果直接使用已ç»å®žçŽ°çš„spawn替æ¢åŽŸæ¥ä»£ç ä¸çš„fork,会é‡åˆ°è¿™äº›é—®é¢˜ï¼š + +- 需è¦åœ¨å†™ä»£ç 的时候就知é“è‡ªå·±çš„æ–‡ä»¶åæ˜¯ä»€ä¹ˆï¼Œä¸å¤Ÿçµæ´» +- spawnç›®å‰åªæ”¯æŒä»Žæ–‡ä»¶æ–°å»ºè¿›ç¨‹æŽ§åˆ¶å—,新建出æ¥çš„进程控制å—会从头开始执行。也就是说,新建进程这件事会进入一个æ»å¾ªçŽ¯ï¼Œä¸æ–地新建å进程。 + +改写æ€è·¯ä¸ºï¼š + +- æ€è·¯1:为spawnå¢žåŠ é»˜è®¤æž„é€ é€‰é¡¹ï¼Œå¦‚æžœè¾“å…¥å—符串为空则使用和将父程åºçš„进程控制å—å¤åˆ¶ä¸€ä»½ç»™å程åºï¼Œä¸”执行状æ€ä¹Ÿä¿æŒä¸€è‡´ï¼Œè¿”回值为-2。这ç§ä¿®æ”¹æ–¹å¼å®žé™…上实现的功能和forkæ˜¯ä¸€æ ·çš„äº†ã€‚ +- æ€è·¯2:å°†if里é¢çš„函数内容å°è£…到å¦ä¸€ä¸ªæ–‡ä»¶ä¸ï¼Œä½¿ç”¨spawn执行。 + +fork的好处就是新建出æ¥çš„进程连执行状æ€ä¹Ÿæ˜¯å’Œçˆ¶è¿›ç¨‹ä¸€æ ·çš„。 + +### 问题4 + +>æè¿°è¿›ç¨‹æ‰§è¡Œçš„å‡ ç§çжæ€ï¼Œä»¥åŠ fork/exec/wait/exit 对于状æ€çš„å½±å“。 + +```rust +pub enum TaskStatus { + Ready,//表示进程准备就绪,å—到调度就å¯ä»¥æ‰§è¡Œ + Running,//表示这是æ£åœ¨æ‰§è¡Œçš„进程 + Zombie,//è¿›ç¨‹å·²ç»æ‰§è¡Œå®Œæ¯•,ç‰å¾…å›žæ”¶èµ„æº +} +``` + +fork:将当å‰è¿›ç¨‹å¤åˆ¶ä¸€ä»½ï¼Œæ–°çš„进程状æ€ä¸ºReadyï¼Œä¸æ”¹å˜å½“å‰è¿›ç¨‹æ‰§è¡ŒçŠ¶æ€ + +execï¼šä¸æ”¹å˜å½“å‰è¿›ç¨‹çš„æ‰§è¡Œçжæ€ï¼Œä½†æ˜¯ä½¿ç”¨å…¶ä»–çš„æ–‡ä»¶æ¥æ›´æ–°å½“å‰è¿›ç¨‹çš„memory_setç‰èµ„æº + +waitï¼šå°†å½“å‰æ£åœ¨Running的进程å˜ä¸ºReady + +exitï¼šå°†å½“å‰æ£åœ¨Running的进程改å˜ä¸ºZombie + +## ä½ å¯¹æœ¬æ¬¡å®žéªŒè®¾è®¡åŠéš¾åº¦/工作é‡çš„çœ‹æ³•ï¼Œä»¥åŠæœ‰å“ªäº›éœ€è¦æ”¹è¿›çš„地方 + +æˆ‘è§‰å¾—è¿™æ¬¡å®žéªŒä»£ç æœ‰äº›è¿‡äºŽç®€å•,åªè¦çœ‹æ‡‚了指导书就实在是简å•å¾—ä»¤äººå‘æŒ‡ã€‚ diff --git a/reports/lab5/fork-hotos19.pdf b/reports/lab5/fork-hotos19.pdf new file mode 100644 index 0000000000000000000000000000000000000000..abc89538c1ffd24fb00efc5f0212d70736b7e915 Binary files /dev/null and b/reports/lab5/fork-hotos19.pdf differ diff --git a/reports/lab5/result0.png b/reports/lab5/result0.png new file mode 100644 index 0000000000000000000000000000000000000000..ff7055966e0a99b7e45970f413f1251adb6a8839 Binary files /dev/null and b/reports/lab5/result0.png differ diff --git a/reports/lab5/result1.png b/reports/lab5/result1.png new file mode 100644 index 0000000000000000000000000000000000000000..001388896507e2d6f0cf335eb29fbd9a7dd0ceb0 Binary files /dev/null and b/reports/lab5/result1.png differ diff --git a/user/Cargo.lock b/user/Cargo.lock new file mode 100644 index 0000000000000000000000000000000000000000..1e1ea74e270f0f8b01a8bdf562edfb7f95752463 --- /dev/null +++ b/user/Cargo.lock @@ -0,0 +1,129 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +dependencies = [ + "memchr", +] + +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "bit_field" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4" + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "buddy_system_allocator" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4e85e760e105b46ae0bd1236578793c6c147ae7463fe95c8350296b8bfcb830" +dependencies = [ + "spin", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "memchr" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" + +[[package]] +name = "regex" +version = "1.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548" + +[[package]] +name = "riscv" +version = "0.6.0" +source = "git+https://github.com/rcore-os/riscv#21e32ee1dc786cc0d5006ceee0040ce4f8398575" +dependencies = [ + "bare-metal", + "bit_field", + "bitflags", + "riscv-target", +] + +[[package]] +name = "riscv-target" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88aa938cda42a0cf62a20cfe8d139ff1af20c2e681212b5b34adb5a58333f222" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "spin" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13287b4da9d1207a4f4929ac390916d64eacfe236a487e9a9f5b3be392be5162" + +[[package]] +name = "user_lib" +version = "0.1.0" +dependencies = [ + "bitflags", + "buddy_system_allocator", + "riscv", +] diff --git a/user/Cargo.toml b/user/Cargo.toml index d50a0ba07b1dceca3e6d7be9852bb242e3589c2f..d76ba49e4a3e62b29463a44cb41776fb4fabb338 100644 --- a/user/Cargo.toml +++ b/user/Cargo.toml @@ -8,4 +8,5 @@ edition = "2018" [dependencies] buddy_system_allocator = "0.6" -bitflags = "1.2.1" \ No newline at end of file +bitflags = "1.2.1" +riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] } \ No newline at end of file diff --git a/user/src/bin/ch5_getpid.rs b/user/src/bin/ch5_getpid.rs new file mode 100644 index 0000000000000000000000000000000000000000..b71f90570ca777198027de6e420ab786e31d5bb5 --- /dev/null +++ b/user/src/bin/ch5_getpid.rs @@ -0,0 +1,14 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; + +use user_lib::getpid; + +#[no_mangle] +pub fn main() -> i32 { + let pid = getpid(); + println!("Test getpid OK! pid = {}", pid); + 0 +} diff --git a/user/src/bin/ch5_spawn0.rs b/user/src/bin/ch5_spawn0.rs new file mode 100644 index 0000000000000000000000000000000000000000..a5c108239d755893f4750fbbc26a4e24ff16a165 --- /dev/null +++ b/user/src/bin/ch5_spawn0.rs @@ -0,0 +1,25 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; + +use user_lib::{spawn, wait}; +const MAX_CHILD: usize = 40; + +#[no_mangle] +pub fn main() -> i32 { + for _ in 0..MAX_CHILD { + let cpid = spawn("ch5_getpid\0"); + assert!(cpid >= 0, "child pid invalid"); + println!("new child {}", cpid); + } + let mut exit_code: i32 = 0; + for _ in 0..MAX_CHILD { + assert!(wait(&mut exit_code) > 0, "wait stopped early"); + assert_eq!(exit_code, 0, "error exit ocde {}", exit_code); + } + assert!(wait(&mut exit_code) <= 0, "wait got too many"); + println!("Test spawn0 OK!"); + 0 +} \ No newline at end of file diff --git a/user/src/bin/ch5_spawn1.rs b/user/src/bin/ch5_spawn1.rs new file mode 100644 index 0000000000000000000000000000000000000000..d4394cf997c17df928029aacac27bba2da7e9922 --- /dev/null +++ b/user/src/bin/ch5_spawn1.rs @@ -0,0 +1,28 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; + +use user_lib::{spawn, wait, waitpid}; + +#[no_mangle] +pub fn main() -> i32 { + let cpid = spawn("ch5_exit0\0"); + assert!(cpid >= 0, "child pid invalid"); + println!("new child {}", cpid); + let mut exit_code: i32 = 0; + let exit_pid = wait(&mut exit_code); + assert_eq!(exit_pid, cpid, "error exit pid"); + assert_eq!(exit_code, 66778, "error exit code"); + println!("Test wait OK!"); + let (cpid0, cpid1) = (spawn("ch5_exit0\0"), spawn("ch5_exit1\0")); + let exit_pid = waitpid(cpid1 as usize, &mut exit_code); + assert_eq!(exit_pid, cpid1, "error exit pid"); + assert_eq!(exit_code, -233, "error exit code"); + let exit_pid = wait(&mut exit_code); + assert_eq!(exit_pid, cpid0, "error exit pid"); + assert_eq!(exit_code, 66778, "error exit code"); + println!("Test waitpid OK!"); + 0 +} diff --git a/user/src/bin/ch5_usershell.rs b/user/src/bin/ch5_usershell.rs new file mode 100644 index 0000000000000000000000000000000000000000..f016103198d6d1db240d753d2a4aae7e32c32bdd --- /dev/null +++ b/user/src/bin/ch5_usershell.rs @@ -0,0 +1,65 @@ +#![no_std] +#![no_main] + +extern crate alloc; + +#[macro_use] +extern crate user_lib; + +const LF: u8 = 0x0au8; +const CR: u8 = 0x0du8; +const DL: u8 = 0x7fu8; +const BS: u8 = 0x08u8; + +use alloc::string::String; +use user_lib::console::getchar; +use user_lib::{spawn, waitpid, yield_}; + +#[no_mangle] +pub fn main() -> i32 { + println!("Rust user shell"); + let mut line: String = String::new(); + print!(">> "); + loop { + let c = getchar(); + match c { + LF | CR => { + println!(""); + if !line.is_empty() { + line.push('\0'); + let cpid = spawn(line.as_str()); + if cpid < 0 { + println!("invalid file name"); + continue; + } + let mut xstate: i32 = 0; + let mut exit_pid: isize; + loop { + exit_pid = waitpid(cpid as usize, &mut xstate); + if exit_pid == -1 { + yield_(); + } else { + assert_eq!(cpid, exit_pid); + println!("Shell: Process {} exited with code {}", cpid, xstate); + break; + } + } + line.clear(); + } + print!(">> "); + } + BS | DL => { + if !line.is_empty() { + print!("{}", BS as char); + print!(" "); + print!("{}", BS as char); + line.pop(); + } + } + _ => { + print!("{}", c as char); + line.push(c as char); + } + } + } +} diff --git a/user/src/bin/filetest_simple.rs b/user/src/bin/ch7_file0.rs similarity index 50% rename from user/src/bin/filetest_simple.rs rename to user/src/bin/ch7_file0.rs index 60fda6aa38bc3b1534444717001bdd708f44c13e..0b61fc929e24c184ab59f681cfddc2e13439ca2b 100644 --- a/user/src/bin/filetest_simple.rs +++ b/user/src/bin/ch7_file0.rs @@ -4,35 +4,28 @@ #[macro_use] extern crate user_lib; -use user_lib::{ - open, - close, - read, - write, - OpenFlags, -}; +use user_lib::{close, open, read, write, OpenFlags}; + +/// 测试文件基本读写,输出 Test file0 OK! 就算æ£ç¡®ã€‚ #[no_mangle] pub fn main() -> i32 { let test_str = "Hello, world!"; - let filea = "filea\0"; - let fd = open(filea, OpenFlags::CREATE | OpenFlags::WRONLY); + let fname = "fname\0"; + let fd = open(fname, 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); + let fd = open(fname, 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!"); + assert_eq!(test_str, core::str::from_utf8(&buffer[..read_len]).unwrap(),); + println!("Test file0 OK!"); 0 -} \ No newline at end of file +} diff --git a/user/src/bin/ch7_file1.rs b/user/src/bin/ch7_file1.rs new file mode 100644 index 0000000000000000000000000000000000000000..4b2b08a73bf905e2fe1478dce6692142af8715ba --- /dev/null +++ b/user/src/bin/ch7_file1.rs @@ -0,0 +1,24 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; +use user_lib::{close, fstat, open, OpenFlags, Stat, StatMode}; + +/// 测试 fstat,输出 Test fstat OK! 就算æ£ç¡®ã€‚ + +#[no_mangle] +pub fn main() -> i32 { + let fname = "fname1\0"; + let fd = open(fname, OpenFlags::CREATE | OpenFlags::WRONLY); + assert!(fd > 0); + let fd = fd as usize; + let stat: Stat = Stat::new(); + let ret = fstat(fd, &stat); + assert_eq!(ret, 0); + assert_eq!(stat.mode, StatMode::FILE); + assert_eq!(stat.nlink, 1); + close(fd); + println!("Test fstat OK!"); + 0 +} diff --git a/user/src/bin/ch7_file2.rs b/user/src/bin/ch7_file2.rs new file mode 100644 index 0000000000000000000000000000000000000000..ad20dea89e3cf2192c9588d9619b7cd40fbdc6e5 --- /dev/null +++ b/user/src/bin/ch7_file2.rs @@ -0,0 +1,44 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; +use user_lib::{close, fstat, link, open, read, unlink, write, OpenFlags, Stat}; + +/// 测试 link/unlink,输出 Test link OK! 就算æ£ç¡®ã€‚ + +#[no_mangle] +pub fn main() -> i32 { + let test_str = "Hello, world!"; + let fname = "fname2\0"; + let (lname0, lname1, lname2) = ("linkname0\0", "linkname1\0", "linkname2\0"); + let fd = open(fname, OpenFlags::CREATE | OpenFlags::WRONLY) as usize; + link(fname, lname0); + let stat = Stat::new(); + fstat(fd, &stat); + assert_eq!(stat.nlink, 2); + link(fname, lname1); + link(fname, lname2); + fstat(fd, &stat); + assert_eq!(stat.nlink, 4); + write(fd, test_str.as_bytes()); + close(fd); + + unlink(fname); + let fd = open(lname0, OpenFlags::RDONLY) as usize; + let stat2 = Stat::new(); + let mut buf = [0u8; 100]; + let read_len = read(fd, &mut buf) as usize; + assert_eq!(test_str, core::str::from_utf8(&buf[..read_len]).unwrap(),); + fstat(fd, &stat2); + assert_eq!(stat2.dev, stat.dev); + assert_eq!(stat2.ino, stat.ino); + assert_eq!(stat2.nlink, 3); + unlink(lname1); + unlink(lname2); + fstat(fd, &stat2); + assert_eq!(stat2.nlink, 1); + close(fd); + println!("Test link OK!"); + 0 +} diff --git a/user/src/bin/ch7_usertest.rs b/user/src/bin/ch7_usertest.rs new file mode 100644 index 0000000000000000000000000000000000000000..418dff3f652ce36c4a09c3162f6ffcc7999cea87 --- /dev/null +++ b/user/src/bin/ch7_usertest.rs @@ -0,0 +1,51 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; + +/// 辅助测例,è¿è¡Œæ‰€æœ‰å…¶ä»–测例。 + +static TESTS: &[&str] = &[ + "ch2_hello_world\0", + "ch2_power\0", + "ch2_write1\0", + "ch3_0_setprio\0", + "ch3_0_sleep\0", + "ch3_0_sleep1\0", + "ch4_mmap0\0", + "ch4_mmap1\0", + "ch4_mmap2\0", + "ch4_mmap3\0", + "ch4_unmap\0", + "ch4_unmap2\0", + "ch5_getpid\0", + "ch5_spawn0\0", + "ch5_spawn1\0", + "ch6_mail0\0", + "ch6_mail1\0", + "ch6_mail2\0", + "ch6_mail3\0", + "ch7_file0\0", + "ch7_file1\0", + "ch7_file2\0", +]; + +use user_lib::{spawn, waitpid}; + +#[no_mangle] +pub fn main() -> i32 { + for test in TESTS { + println!("Usertests: Running {}", test); + let pid = spawn(*test); + let mut xstate: i32 = Default::default(); + let wait_pid = waitpid(pid as usize, &mut xstate); + assert_eq!(pid, wait_pid); + println!( + "\x1b[32mUsertests: Test {} in Process {} exited with code {}\x1b[0m", + test, pid, xstate + ); + } + println!("ch7 Usertests passed!"); + 0 +} diff --git a/user/src/bin/fantastic_text.rs b/user/src/bin/fantastic_text.rs deleted file mode 100644 index bb51db305f0a8a19860e80ae67554d1b01dc77e0..0000000000000000000000000000000000000000 --- a/user/src/bin/fantastic_text.rs +++ /dev/null @@ -1,44 +0,0 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; - -macro_rules! color_text { - ($text:expr, $color:expr) => {{ - format_args!("\x1b[{}m{}\x1b[0m", $color, $text) - }}; -} - -#[no_mangle] -pub fn main() -> i32 { - println!( - "{}{}{}{}{} {}{}{}{} {}{}{}{}{}{}", - color_text!("H", 31), - color_text!("e", 32), - color_text!("l", 33), - color_text!("l", 34), - color_text!("o", 35), - color_text!("R", 36), - color_text!("u", 37), - color_text!("s", 90), - color_text!("t", 91), - color_text!("u", 92), - color_text!("C", 93), - color_text!("o", 94), - color_text!("r", 95), - color_text!("e", 96), - color_text!("!", 97), - ); - - let text = - "reguler \x1b[4munderline\x1b[24m \x1b[7mreverse\x1b[27m \x1b[9mstrikethrough\x1b[29m"; - println!("\x1b[47m{}\x1b[0m", color_text!(text, 30)); - for i in 31..38 { - println!("{}", color_text!(text, i)); - } - for i in 90..98 { - println!("{}", color_text!(text, i)); - } - 0 -} \ No newline at end of file diff --git a/user/src/bin/forktest.rs b/user/src/bin/forktest.rs deleted file mode 100644 index fea6967c412316a5dd6995306ad420e045f56f74..0000000000000000000000000000000000000000 --- a/user/src/bin/forktest.rs +++ /dev/null @@ -1,34 +0,0 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; - -use user_lib::{fork, wait, exit}; - -const MAX_CHILD: usize = 40; - -#[no_mangle] -pub fn main() -> i32 { - for i in 0..MAX_CHILD { - let pid = fork(); - if pid == 0 { - println!("I am child {}", i); - exit(0); - } else { - println!("forked child pid = {}", pid); - } - assert!(pid > 0); - } - let mut exit_code: i32 = 0; - for _ in 0..MAX_CHILD { - if wait(&mut exit_code) <= 0 { - panic!("wait stopped early"); - } - } - if wait(&mut exit_code) > 0 { - panic!("wait got too many"); - } - println!("forktest pass."); - 0 -} \ No newline at end of file diff --git a/user/src/bin/forktest2.rs b/user/src/bin/forktest2.rs deleted file mode 100644 index d08a412063d87238be7a2ff0120af12236d2a8ab..0000000000000000000000000000000000000000 --- a/user/src/bin/forktest2.rs +++ /dev/null @@ -1,33 +0,0 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; - -use user_lib::{fork, wait, getpid, exit, sleep, get_time}; - -static NUM: usize = 30; - -#[no_mangle] -pub fn main() -> i32 { - for _ in 0..NUM { - let pid = fork(); - if pid == 0 { - let current_time = get_time(); - let sleep_length = (current_time as i32 as isize) * (current_time as i32 as isize) % 1000 + 1000; - println!("pid {} sleep for {} ms", getpid(), sleep_length); - sleep(sleep_length as usize); - println!("pid {} OK!", getpid()); - exit(0); - } - } - - let mut exit_code: i32 = 0; - for _ in 0..NUM { - assert!(wait(&mut exit_code) > 0); - assert_eq!(exit_code, 0); - } - assert!(wait(&mut exit_code) < 0); - println!("forktest2 test passed!"); - 0 -} \ No newline at end of file diff --git a/user/src/bin/forktest_simple.rs b/user/src/bin/forktest_simple.rs deleted file mode 100644 index 821fba642fb22926df365187453fdea1cb761264..0000000000000000000000000000000000000000 --- a/user/src/bin/forktest_simple.rs +++ /dev/null @@ -1,28 +0,0 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; - -use user_lib::{fork, getpid, wait}; - -#[no_mangle] -pub fn main() -> i32 { - assert_eq!(wait(&mut 0i32), -1); - println!("sys_wait without child process test passed!"); - println!("parent start, pid = {}!", getpid()); - let pid = fork(); - if pid == 0 { - // child process - println!("hello child process!"); - 100 - } else { - // parent process - let mut exit_code: i32 = 0; - println!("ready waiting on parent process!"); - assert_eq!(pid, wait(&mut exit_code)); - assert_eq!(exit_code, 100); - println!("child process pid = {}, exit code = {}", pid, exit_code); - 0 - } -} \ No newline at end of file diff --git a/user/src/bin/forktree.rs b/user/src/bin/forktree.rs deleted file mode 100644 index 26954b7a6512980b3aee6357d3edfee1ad5ef0f0..0000000000000000000000000000000000000000 --- a/user/src/bin/forktree.rs +++ /dev/null @@ -1,37 +0,0 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; - -use user_lib::{sleep, getpid, fork, exit, yield_}; - -const DEPTH: usize = 4; - -fn fork_child(cur: &str, branch: char) { - let mut next = [0u8; DEPTH + 1]; - let l = cur.len(); - if l >= DEPTH { - return; - } - &mut next[..l].copy_from_slice(cur.as_bytes()); - next[l] = branch as u8; - if fork() == 0 { - fork_tree(core::str::from_utf8(&next[..l + 1]).unwrap()); - yield_(); - exit(0); - } -} - -fn fork_tree(cur: &str) { - println!("pid{}: {}", getpid(), cur); - fork_child(cur, '0'); - fork_child(cur, '1'); -} - -#[no_mangle] -pub fn main() -> i32 { - fork_tree(""); - sleep(3000); - 0 -} diff --git a/user/src/bin/matrix.rs b/user/src/bin/matrix.rs deleted file mode 100644 index 8ef2c044a2f83ceed1d49ff58888081e8e640920..0000000000000000000000000000000000000000 --- a/user/src/bin/matrix.rs +++ /dev/null @@ -1,68 +0,0 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; - -use user_lib::{fork, wait, yield_, exit, getpid, get_time}; - -static NUM: usize = 35; -const N: usize = 10; -static P: i32 = 10007; -type Arr = [[i32; N]; N]; - -fn work(times: isize) { - let mut a: Arr = Default::default(); - let mut b: Arr = Default::default(); - let mut c: Arr = Default::default(); - for i in 0..N { - for j in 0..N { - a[i][j] = 1; - b[i][j] = 1; - } - } - yield_(); - println!("pid {} is running ({} times)!.", getpid(), times); - for _ in 0..times { - for i in 0..N { - for j in 0..N { - c[i][j] = 0; - for k in 0..N { - c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % P; - } - } - } - for i in 0..N { - for j in 0..N { - a[i][j] = c[i][j]; - b[i][j] = c[i][j]; - } - } - } - println!("pid {} done!.", getpid()); - exit(0); -} - -#[no_mangle] -pub fn main() -> i32 { - for _ in 0..NUM { - let pid = fork(); - if pid == 0 { - let current_time = get_time(); - let times = (current_time as i32 as isize) * (current_time as i32 as isize) % 1000; - work(times * 10); - } - } - - println!("fork ok."); - - let mut exit_code: i32 = 0; - for _ in 0..NUM { - if wait(&mut exit_code) < 0 { - panic!("wait failed."); - } - } - assert!(wait(&mut exit_code) < 0); - println!("matrix passed."); - 0 -} \ No newline at end of file diff --git a/user/src/bin/pipe_large_test.rs b/user/src/bin/pipe_large_test.rs deleted file mode 100644 index 121987be346c50c1efec3a5f500f4c40f6405359..0000000000000000000000000000000000000000 --- a/user/src/bin/pipe_large_test.rs +++ /dev/null @@ -1,69 +0,0 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; - -extern crate alloc; - -use user_lib::{fork, close, pipe, read, write, wait, get_time}; -use alloc::format; - -const LENGTH: usize = 3000; -#[no_mangle] -pub fn main() -> i32 { - // create pipes - // parent write to child - let mut down_pipe_fd = [0usize; 2]; - // child write to parent - let mut up_pipe_fd = [0usize; 2]; - pipe(&mut down_pipe_fd); - pipe(&mut up_pipe_fd); - let mut random_str = [0u8; LENGTH]; - if fork() == 0 { - // close write end of down pipe - close(down_pipe_fd[1]); - // close read end of up pipe - close(up_pipe_fd[0]); - assert_eq!(read(down_pipe_fd[0], &mut random_str) as usize, LENGTH); - close(down_pipe_fd[0]); - let sum: usize = random_str.iter().map(|v| *v as usize).sum::<usize>(); - println!("sum = {}(child)", sum); - let sum_str = format!("{}", sum); - write(up_pipe_fd[1], sum_str.as_bytes()); - close(up_pipe_fd[1]); - println!("Child process exited!"); - 0 - } else { - // close read end of down pipe - close(down_pipe_fd[0]); - // close write end of up pipe - close(up_pipe_fd[1]); - // generate a long random string - for i in 0..LENGTH { - random_str[i] = get_time() as u8; - } - // send it - assert_eq!(write(down_pipe_fd[1], &random_str) as usize, random_str.len()); - // close write end of down pipe - close(down_pipe_fd[1]); - // calculate sum(parent) - let sum: usize = random_str.iter().map(|v| *v as usize).sum::<usize>(); - println!("sum = {}(parent)", sum); - // recv sum(child) - let mut child_result = [0u8; 32]; - let result_len = read(up_pipe_fd[0], &mut child_result) as usize; - close(up_pipe_fd[0]); - // check - assert_eq!( - sum, - str::parse::<usize>( - core::str::from_utf8(&child_result[..result_len]).unwrap() - ).unwrap() - ); - let mut _unused: i32 = 0; - wait(&mut _unused); - println!("pipe_large_test passed!"); - 0 - } -} \ No newline at end of file diff --git a/user/src/bin/sleep_simple.rs b/user/src/bin/sleep_simple.rs deleted file mode 100644 index 4c058f879d14214e059152f22f698a4eaa032746..0000000000000000000000000000000000000000 --- a/user/src/bin/sleep_simple.rs +++ /dev/null @@ -1,19 +0,0 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; - -use user_lib::{get_time, sleep}; - -#[no_mangle] -pub fn main() -> i32 { - println!("into sleep test!"); - let start = get_time(); - println!("current time_msec = {}", start); - sleep(100); - let end = get_time(); - println!("time_msec = {} after sleeping 100 ticks, delta = {}ms!", end, end - start); - println!("r_sleep passed!"); - 0 -} \ No newline at end of file diff --git a/user/src/bin/stack_overflow.rs b/user/src/bin/stack_overflow.rs deleted file mode 100644 index e0ea471d536ac0e53be65d112087c6c9ac2f9fd0..0000000000000000000000000000000000000000 --- a/user/src/bin/stack_overflow.rs +++ /dev/null @@ -1,17 +0,0 @@ -#![no_std] -#![no_main] - -#[macro_use] -extern crate user_lib; - -fn f(d: usize) { - println!("d = {}",d); - f(d + 1); -} - -#[no_mangle] -pub fn main() -> i32 { - println!("It should trigger segmentation fault!"); - f(0); - 0 -} \ No newline at end of file diff --git a/user/src/console.rs b/user/src/console.rs index 810ebba13a5ea2e4c6bf20f280e18fb5dc28b425..2257557baa3d47384fbc580e527d0a549f22bc53 100644 --- a/user/src/console.rs +++ b/user/src/console.rs @@ -1,7 +1,7 @@ use core::fmt::{self, Write}; -const STDIN: usize = 0; -const STDOUT: usize = 1; +pub const STDIN: usize = 0; +pub const STDOUT: usize = 1; use super::{read, write}; diff --git a/user/src/lib.rs b/user/src/lib.rs index 0ef03bfb78e91bdc70238f086ef02039a4ff7364..4cb9e9027fcc9ba80d7f86d101fb122fbe296160 100644 --- a/user/src/lib.rs +++ b/user/src/lib.rs @@ -15,8 +15,61 @@ extern crate bitflags; use syscall::*; use buddy_system_allocator::LockedHeap; +pub use console::{STDIN, STDOUT}; use alloc::vec::Vec; +#[repr(C)] +#[derive(Debug)] +pub struct TimeVal { + pub sec: usize, + pub usec: usize, +} + +impl TimeVal { + pub fn new() -> Self { + TimeVal { sec: 0, usec: 0 } + } +} + +#[repr(C)] +#[derive(Debug)] +pub struct Stat { + /// ID of device containing file + pub dev: u64, + /// inode number + pub ino: u64, + /// file type and mode + pub mode: StatMode, + /// number of hard links + pub nlink: u32, + /// unused pad + pad: [u64; 7], +} + +impl Stat { + pub fn new() -> Self { + Stat { + dev: 0, + ino: 0, + mode: StatMode::NULL, + nlink: 0, + pad: [0; 7], + } + } +} + +bitflags! { + pub struct StatMode: u32 { + const NULL = 0; + /// directory + const DIR = 0o040000; + /// ordinary regular file + const FILE = 0o100000; + } +} + +const AT_FDCWD: isize = -100; + const USER_HEAP_SIZE: usize = 32768; static mut HEAP_SPACE: [u8; USER_HEAP_SIZE] = [0; USER_HEAP_SIZE]; @@ -77,10 +130,21 @@ pub fn read(fd: usize, buf: &mut [u8]) -> isize { sys_read(fd, buf) } pub fn write(fd: usize, buf: &[u8]) -> isize { sys_write(fd, buf) } pub fn exit(exit_code: i32) -> ! { sys_exit(exit_code); } pub fn yield_() -> isize { sys_yield() } -pub fn get_time() -> isize { sys_get_time() } +// pub fn get_time() -> isize { sys_get_time() } +pub fn get_time() -> isize { + let time = TimeVal::new(); + match sys_get_time(&time, 0) { + 0 => { + return ((time.sec & 0xffff) * 1000 + time.usec / 1000) as isize; + }, + _ => -1 + } +} pub fn getpid() -> isize { sys_getpid() } pub fn fork() -> isize { sys_fork() } -pub fn exec(path: &str, args: &[*const u8]) -> isize { sys_exec(path, args) } +pub fn exec(path: &str, args: &[*const u8]) -> isize { + sys_exec(path, args) +} pub fn wait(exit_code: &mut i32) -> isize { loop { match sys_waitpid(-1, exit_code as *mut _) { @@ -101,8 +165,53 @@ pub fn waitpid(pid: usize, exit_code: &mut i32) -> isize { } } pub fn sleep(period_ms: usize) { - let start = sys_get_time(); - while sys_get_time() < start + period_ms as isize { + let start = get_time(); + while get_time() < start + period_ms as isize { sys_yield(); } +} +//=====================lab3=============================== +pub fn set_priority(prio: isize) -> isize { + sys_set_priority(prio) +} + + +//=====================lab4=============================== +pub fn mmap(start: usize, len: usize, prot: usize) -> isize { + sys_mmap(start, len, prot) +} + +pub fn munmap(start: usize, len: usize) -> isize { + sys_munmap(start, len) +} + + +//=====================lab5=============================== +pub fn spawn(path: &str) -> isize { + sys_spawn(path) +} +// pub fn exec(path: &str, args: &[*const u8]) -> isize { +// sys_exec(path, args) +// } + +//=====================lab6=============================== +pub fn mail_read(buf: &mut [u8]) -> isize { + sys_mail_read(buf) +} + +pub fn mail_write(pid: usize, buf: &[u8]) -> isize { + sys_mail_write(pid, buf) +} + +//=====================lab6=============================== +pub fn link(old_path: &str, new_path: &str) -> isize { + sys_linkat(AT_FDCWD as usize, old_path, AT_FDCWD as usize, new_path, 0) +} + +pub fn unlink(path: &str) -> isize { + sys_unlinkat(AT_FDCWD as usize, path, 0) +} + +pub fn fstat(fd: usize, st: &Stat) -> isize { + sys_fstat(fd, st) } \ No newline at end of file diff --git a/user/src/linker.ld b/user/src/linker.ld index e05a98ba75dd800b4afb37f737ff648d9070ad89..7273618c9f6b2cb497b34e1ffae692b79fcce40a 100644 --- a/user/src/linker.ld +++ b/user/src/linker.ld @@ -14,13 +14,16 @@ SECTIONS . = ALIGN(4K); .rodata : { *(.rodata .rodata.*) + *(.srodata .srodata.*) } . = ALIGN(4K); .data : { *(.data .data.*) + *(.sdata .sdata.*) } .bss : { *(.bss .bss.*) + *(.sbss .sbss.*) } /DISCARD/ : { *(.eh_frame) diff --git a/user/src/syscall.rs b/user/src/syscall.rs index 1cd30f8459fe6bfceff0e858628d909da0e192d7..9ae58561644f0b2220f5d62f0d2bdab1ce5d6e4b 100644 --- a/user/src/syscall.rs +++ b/user/src/syscall.rs @@ -1,9 +1,11 @@ +use super::{Stat, TimeVal}; const SYSCALL_DUP: usize = 24; -const SYSCALL_OPEN: usize = 56; +const SYSCALL_OPENAT: usize = 56; const SYSCALL_CLOSE: usize = 57; const SYSCALL_PIPE: usize = 59; const SYSCALL_READ: usize = 63; const SYSCALL_WRITE: usize = 64; + const SYSCALL_EXIT: usize = 93; const SYSCALL_YIELD: usize = 124; const SYSCALL_GET_TIME: usize = 169; @@ -11,6 +13,17 @@ const SYSCALL_GETPID: usize = 172; const SYSCALL_FORK: usize = 220; const SYSCALL_EXEC: usize = 221; const SYSCALL_WAITPID: usize = 260; +const SYSCALL_SET_PRIORITY: usize = 140; +const SYSCALL_MUNMAP: usize = 215; +const SYSCALL_MMAP: usize = 222; +const SYSCALL_SPAWN: usize = 400; +//=====================lab6=============================== +const SYSCALL_MAIL_READ: usize = 401; +const SYSCALL_MAIL_WRITE: usize = 402; +//=====================lab7=============================== +const SYSCALL_UNLINKAT: usize = 35; +const SYSCALL_LINKAT: usize = 37; +const SYSCALL_FSTAT: usize = 80; fn syscall(id: usize, args: [usize; 3]) -> isize { let mut ret: isize; @@ -25,12 +38,26 @@ fn syscall(id: usize, args: [usize; 3]) -> isize { ret } +fn syscall5(id: usize, args: [usize; 5]) -> isize { + let mut ret: isize; + unsafe { + llvm_asm!("ecall" + : "={x10}" (ret) + : "{x10}" (args[0]), "{x11}" (args[1]), "{x12}" (args[2]), "{x13}" (args[3]), + "{x14}" (args[4]), "{x17}" (id) + : "memory" + : "volatile" + ); + } + ret +} + pub fn sys_dup(fd: usize) -> isize { syscall(SYSCALL_DUP, [fd, 0, 0]) } pub fn sys_open(path: &str, flags: u32) -> isize { - syscall(SYSCALL_OPEN, [path.as_ptr() as usize, flags as usize, 0]) + syscall(SYSCALL_OPENAT, [path.as_ptr() as usize, flags as usize, 0]) } pub fn sys_close(fd: usize) -> isize { @@ -58,8 +85,11 @@ pub fn sys_yield() -> isize { syscall(SYSCALL_YIELD, [0, 0, 0]) } -pub fn sys_get_time() -> isize { - syscall(SYSCALL_GET_TIME, [0, 0, 0]) +// pub fn sys_get_time() -> isize { +// syscall(SYSCALL_GET_TIME, [0, 0, 0]) +// } +pub fn sys_get_time(time: &TimeVal, tz: usize) -> isize { + syscall(SYSCALL_GET_TIME, [time as *const _ as usize, tz, 0]) } pub fn sys_getpid() -> isize { @@ -76,4 +106,67 @@ pub fn sys_exec(path: &str, args: &[*const u8]) -> isize { pub fn sys_waitpid(pid: isize, exit_code: *mut i32) -> isize { syscall(SYSCALL_WAITPID, [pid as usize, exit_code as usize, 0]) +} +//=====================lab3=============================== +pub fn sys_set_priority(prio: isize) -> isize { + syscall(SYSCALL_SET_PRIORITY, [prio as usize, 0, 0]) +} + +//=====================lab4=============================== +pub fn sys_mmap(start: usize, len: usize, prot: usize) -> isize { + syscall(SYSCALL_MMAP, [start, len, prot]) +} + +pub fn sys_munmap(start: usize, len: usize) -> isize { + syscall(SYSCALL_MUNMAP, [start, len, 0]) +} + +//=====================lab5=============================== + +pub fn sys_spawn(path: &str) -> isize { + syscall(SYSCALL_SPAWN, [path.as_ptr() as usize, 0, 0]) +} + + +//=====================lab6=============================== +pub fn sys_mail_read(buffer: &mut [u8]) -> isize { + syscall( + SYSCALL_MAIL_READ, + [buffer.as_ptr() as usize, buffer.len(), 0], + ) +} + +pub fn sys_mail_write(pid: usize, buffer: &[u8]) -> isize { + syscall( + SYSCALL_MAIL_WRITE, + [pid, buffer.as_ptr() as usize, buffer.len()], + ) +} + +//=====================lab7=============================== +pub fn sys_linkat( + old_dirfd: usize, + old_path: &str, + new_dirfd: usize, + new_path: &str, + flags: usize, +) -> isize { + syscall5( + SYSCALL_LINKAT, + [ + old_dirfd, + old_path.as_ptr() as usize, + new_dirfd, + new_path.as_ptr() as usize, + flags, + ], + ) +} + +pub fn sys_unlinkat(dirfd: usize, path: &str, flags: usize) -> isize { + syscall(SYSCALL_UNLINKAT, [dirfd, path.as_ptr() as usize, flags]) +} + +pub fn sys_fstat(fd: usize, st: &Stat) -> isize { + syscall(SYSCALL_FSTAT, [fd, st as *const _ as usize, 0]) } \ No newline at end of file diff --git a/user/target/.rustc_info.json b/user/target/.rustc_info.json new file mode 100644 index 0000000000000000000000000000000000000000..2b9684e525a718993f55e9a0f8ccbe3b5ff6e22f --- /dev/null +++ b/user/target/.rustc_info.json @@ -0,0 +1 @@ +{"rustc_fingerprint":11314787443920216368,"outputs":{"17103856195547239926":["___\nlib___.rlib\nlib___.a\n/home/user/.rustup/toolchains/nightly-2021-01-30-x86_64-unknown-linux-gnu\ndebug_assertions\npanic=\"abort\"\nproc_macro\ntarget_arch=\"riscv64\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_feature=\"a\"\ntarget_feature=\"c\"\ntarget_feature=\"d\"\ntarget_feature=\"f\"\ntarget_feature=\"m\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_has_atomic_equal_alignment=\"16\"\ntarget_has_atomic_equal_alignment=\"32\"\ntarget_has_atomic_equal_alignment=\"64\"\ntarget_has_atomic_equal_alignment=\"8\"\ntarget_has_atomic_equal_alignment=\"ptr\"\ntarget_has_atomic_load_store=\"16\"\ntarget_has_atomic_load_store=\"32\"\ntarget_has_atomic_load_store=\"64\"\ntarget_has_atomic_load_store=\"8\"\ntarget_has_atomic_load_store=\"ptr\"\ntarget_os=\"none\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\n","warning: dropping unsupported crate type `dylib` for target `riscv64gc-unknown-none-elf`\n\nwarning: dropping unsupported crate type `cdylib` for target `riscv64gc-unknown-none-elf`\n\nwarning: dropping unsupported crate type `proc-macro` for target `riscv64gc-unknown-none-elf`\n\nwarning: 3 warnings emitted\n\n"],"1164083562126845933":["rustc 1.51.0-nightly (b12290861 2021-01-29)\nbinary: rustc\ncommit-hash: b122908617436af187252572ed5db96850551380\ncommit-date: 2021-01-29\nhost: x86_64-unknown-linux-gnu\nrelease: 1.51.0-nightly\nLLVM version: 11.0.1\n",""],"4476964694761187371":["___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/user/.rustup/toolchains/nightly-2021-01-30-x86_64-unknown-linux-gnu\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_has_atomic_equal_alignment=\"16\"\ntarget_has_atomic_equal_alignment=\"32\"\ntarget_has_atomic_equal_alignment=\"64\"\ntarget_has_atomic_equal_alignment=\"8\"\ntarget_has_atomic_equal_alignment=\"ptr\"\ntarget_has_atomic_load_store=\"16\"\ntarget_has_atomic_load_store=\"32\"\ntarget_has_atomic_load_store=\"64\"\ntarget_has_atomic_load_store=\"8\"\ntarget_has_atomic_load_store=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_thread_local\ntarget_vendor=\"unknown\"\nunix\n",""]},"successes":{}} \ No newline at end of file diff --git a/user/target/CACHEDIR.TAG b/user/target/CACHEDIR.TAG new file mode 100644 index 0000000000000000000000000000000000000000..20d7c319cda945dc07729797750a49b232206ab5 --- /dev/null +++ b/user/target/CACHEDIR.TAG @@ -0,0 +1,3 @@ +Signature: 8a477f597d28d172789f06886806bc55 +# This file is a cache directory tag created by cargo. +# For information about cache directory tags see https://bford.info/cachedir/ diff --git a/user/target/release/.cargo-lock b/user/target/release/.cargo-lock new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/user/target/riscv64gc-unknown-none-elf/CACHEDIR.TAG b/user/target/riscv64gc-unknown-none-elf/CACHEDIR.TAG new file mode 100644 index 0000000000000000000000000000000000000000..20d7c319cda945dc07729797750a49b232206ab5 --- /dev/null +++ b/user/target/riscv64gc-unknown-none-elf/CACHEDIR.TAG @@ -0,0 +1,3 @@ +Signature: 8a477f597d28d172789f06886806bc55 +# This file is a cache directory tag created by cargo. +# For information about cache directory tags see https://bford.info/cachedir/ diff --git a/user/target/riscv64gc-unknown-none-elf/release/.cargo-lock b/user/target/riscv64gc-unknown-none-elf/release/.cargo-lock new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/user/target/riscv64gc-unknown-none-elf/release/libuser_lib.d b/user/target/riscv64gc-unknown-none-elf/release/libuser_lib.d new file mode 100644 index 0000000000000000000000000000000000000000..feaeb4ff4bf61346bba1e6e570c3f7fefe3e3005 --- /dev/null +++ b/user/target/riscv64gc-unknown-none-elf/release/libuser_lib.d @@ -0,0 +1 @@ +/home/user/OS/rCore-Tutorial-v3/user/target/riscv64gc-unknown-none-elf/release/libuser_lib.rlib: /home/user/OS/rCore-Tutorial-v3/user/src/console.rs /home/user/OS/rCore-Tutorial-v3/user/src/lang_items.rs /home/user/OS/rCore-Tutorial-v3/user/src/lib.rs /home/user/OS/rCore-Tutorial-v3/user/src/syscall.rs diff --git a/user/target/riscv64gc-unknown-none-elf/release/libuser_lib.rlib b/user/target/riscv64gc-unknown-none-elf/release/libuser_lib.rlib new file mode 100644 index 0000000000000000000000000000000000000000..8747d477cced1834b5bf0eb7b4c3b1befa9aaf9f Binary files /dev/null and b/user/target/riscv64gc-unknown-none-elf/release/libuser_lib.rlib differ