diff --git a/ch4/os/src/main.rs b/ch4/os/src/main.rs index 4f0f622..6f65348 100644 --- a/ch4/os/src/main.rs +++ b/ch4/os/src/main.rs @@ -50,13 +50,9 @@ pub fn rust_main(){ // 初始化动态内存分配器, 使我们能在内核中使用动态大小数据类型 mm::init(); - println!("main 0"); trap::init(); - println!("main 1"); trap::enable_timer_interrupt(); // 允许定时器中断 - println!("main 2"); timer::set_next_trigger(); // 在进入用户态之前, 设置一个时钟中断, 防止第一个用户任务死循环 - println!("main 3"); task::run_first_task(); panic!("Disable run here") diff --git a/ch4/os/src/mm/frame_allocator.rs b/ch4/os/src/mm/frame_allocator.rs index 3a87d30..8241509 100644 --- a/ch4/os/src/mm/frame_allocator.rs +++ b/ch4/os/src/mm/frame_allocator.rs @@ -106,13 +106,13 @@ pub fn frame_allocator_test() { let mut v: Vec = Vec::new(); for i in 0..5 { let frame = frame_alloc().unwrap(); - println!("{:?}", frame.ppn.0); + println!("frame_allocator_test {:?}", frame.ppn.0); v.push(frame); } v.clear(); for i in 0..5 { let frame = frame_alloc().unwrap(); - println!("{:?}", frame.ppn.0); + println!("frame_allocator_test {:?}", frame.ppn.0); v.push(frame); } drop(v); diff --git a/ch4/os/src/mm/memory_set.rs b/ch4/os/src/mm/memory_set.rs index 0c8b54d..937ff32 100644 --- a/ch4/os/src/mm/memory_set.rs +++ b/ch4/os/src/mm/memory_set.rs @@ -66,7 +66,7 @@ impl MapArea { // 截取抛弃内存碎片 let start_vpn: VirtPageNum = start_va.floor(); let end_vpn: VirtPageNum = end_va.ceil(); - println!("start va: {} start vpn {}", start_va.0, start_vpn.0); + Self { vpn_range: VPNRange {l:start_vpn, r: end_vpn}, data_frames: BTreeMap::new(), @@ -111,9 +111,8 @@ impl MapArea { // 映射 当前逻辑段中的每一个虚拟页, 到页表中 pub fn map(&mut self, page_table: &mut PageTable) { - println!("self.vpn_range.get_start {} {}", self.vpn_range.l.0, self.vpn_range.r.0); + for vpn in self.vpn_range { - println!("range vpn :{}", vpn.0); self.map_one(page_table, vpn); } } @@ -178,7 +177,6 @@ impl MemorySet { memory_set.map_trampoline(); // map program headers of elf, with U flag // 分析外部传进来的 elf文件数据 - println!("enf len: {}", elf_data.len()); let elf = xmas_elf::ElfFile::new(elf_data).unwrap(); let elf_header = elf.header; let magic = elf_header.pt1.magic; @@ -196,7 +194,7 @@ impl MemorySet { let start_va: VirtAddr = (ph.virtual_addr() as usize).into(); // 当前段结束位置 (开始位置+大小) let end_va: VirtAddr = ((ph.virtual_addr() + ph.mem_size()) as usize).into(); - println!("start_va {} end_va {}", start_va.0, end_va.0); + // 当前段权限 let mut map_perm = MapPermission::U; let ph_flags = ph.flags(); @@ -260,7 +258,6 @@ impl MemorySet { // 设置 TrapContext为统一的虚拟地址 // 将 虚拟地址的 次高页添加到用户空间, 后面会被内核强行找到物理地址并修改为 trap context - println!("TRAP_CONTEXT: {}, TRAMPOLINE: {}", TRAP_CONTEXT, TRAMPOLINE); memory_set.push( MapArea::from( TRAP_CONTEXT.into(), @@ -270,7 +267,7 @@ impl MemorySet { ), None, ); - println!(3); + ( memory_set, // 地址空间 user_stack_top, // 用户栈底和当前的栈顶, 他在地址空间各个逻辑段的上面, 同时 diff --git a/ch4/os/src/mm/page_table.rs b/ch4/os/src/mm/page_table.rs index 54d6723..fce9cf9 100644 --- a/ch4/os/src/mm/page_table.rs +++ b/ch4/os/src/mm/page_table.rs @@ -158,9 +158,6 @@ impl PageTable { pub fn map(&mut self, vpn: VirtPageNum, ppn: PhysPageNum, flags: PTEFlags) { // 查找vpn 没有中间节点就创建出来 let pte = self.find_pte_create(vpn).unwrap(); - // let a = self.get_pte(vpn).unwrap().ppn().0; - println!("is_valid: {}", pte.is_valid()); - println!("vpn: {:?} pte.ppn:{}", vpn.0, pte.ppn().0); assert!(!pte.is_valid(), "vpn {:?} is mapped before mapping", vpn.0); *pte = PageTableEntry::from(ppn, flags | PTEFlags::V); } @@ -178,4 +175,44 @@ impl PageTable { } } +// 根据token得到用户应用的页表, 并根据ptr 和len 在页表中找到指定的数据 +pub fn translated_byte_buffer(token: usize, ptr: *const u8, len: usize) -> Vec<&'static mut [u8]> { + // 根据寄存器token, 得到用户页表 + let page_table = PageTable::from_token(token); + + // 用户空间指定数据 的 逻辑起始位置 + let mut start = ptr as usize; + // 用户空间指定数据的 逻辑结束位置 + let end = start + len; + + // 循环 逻辑的起始和结束位置, 根据页表,在物理页中寻找数据 + // 可能 start 和end 跨了很多页, 需要找到每一页并偏移 + let mut v = Vec::new(); + while start < end { + // 逻辑起始位置对应实际的物理页帧 + let start_va = VirtAddr::from(start); + let mut vpn = start_va.floor(); + let ppn = page_table.get_pte(vpn).unwrap().ppn(); + + // 当前start页 的结束页 就是下一个逻辑页 start+1 的位置 + vpn = (vpn.0+1).into(); + let mut end_va: VirtAddr = vpn.into(); + + // 找到 比较小的结束位置 + end_va = end_va.min(VirtAddr::from(end)); + + // 如果 不是最后一页, 就找到当前物理页的所有4096字节 进行拷贝 + 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(); + } + v +} + diff --git a/ch4/os/src/syscall/fs.rs b/ch4/os/src/syscall/fs.rs index f50d860..26ea702 100644 --- a/ch4/os/src/syscall/fs.rs +++ b/ch4/os/src/syscall/fs.rs @@ -1,6 +1,8 @@ //! File and filesystem-related syscalls +use crate::mm::page_table::translated_byte_buffer; use crate::print; +use crate::task::TASK_MANAGER; const FD_STDOUT: usize = 1; @@ -8,9 +10,12 @@ const FD_STDOUT: usize = 1; pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize { match fd { FD_STDOUT => { - // let slice = unsafe { core::slice::from_raw_parts(buf, len) }; - // let str = core::str::from_utf8(slice).unwrap(); - // print!("{}", str); + // 根据当前页表 找到物理内存基地址 + // 这里需要从应用的地址空间里面寻找数据 + let buffers = translated_byte_buffer(TASK_MANAGER.get_current_token(), buf, len); + for buffer in buffers { + print!("{}", core::str::from_utf8(buffer).unwrap()); + } len as isize } _ => { diff --git a/ch4/os/src/syscall/mod.rs b/ch4/os/src/syscall/mod.rs index 9d4c66d..d2fb9e6 100644 --- a/ch4/os/src/syscall/mod.rs +++ b/ch4/os/src/syscall/mod.rs @@ -12,7 +12,6 @@ use crate::println; /// 根据syscall_id 进行分发 pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { - println!("syscall_id......{} {:?}", syscall_id, args); match syscall_id { SYSCALL_WRITE => sys_write(args[0], args[1] as *const u8, args[2]), diff --git a/ch4/os/src/trap/mod.rs b/ch4/os/src/trap/mod.rs index 7542e8c..24ab220 100644 --- a/ch4/os/src/trap/mod.rs +++ b/ch4/os/src/trap/mod.rs @@ -32,7 +32,6 @@ pub fn enable_timer_interrupt() { #[no_mangle] pub fn trap_handler() -> ! { // 已经进入内核, 如果再发生中断我们进行的设置, 目前是直接跳转到一个引发panic 的函数 - println!("trap_handler......"); set_kernel_trap_entry(); // 进入到了内核态, 需要把之前的用户消耗时间统计在用户时间上 @@ -40,9 +39,9 @@ pub fn trap_handler() -> ! { // 得到当前用户应用 的 trap context, 需要调用一个函数, 因为用户应用的trap context 不再内核空间, 他是在用户空间的次高地址 let cx = TASK_MANAGER.get_current_trap_cx(); + let scause = scause::read(); // trap 发生的原因 let stval = stval::read(); // trap的附加信息 - println!("trap_handler......1"); // 根据发生的原因判断是那种类别 match scause.cause() { // 用户态发出的系统调用 @@ -108,9 +107,6 @@ pub fn trap_return() -> ! { // TRAMPOLINE + (__restore - __alltraps), 得到的就是用户空间中 虚拟地址跳板的位置, 增加一个 (__alltraps低地址 到 __restore高地址的偏移值), 就得到了 strampoline -> __restore 的虚拟地址 let restore_va = __restore as usize - __alltraps as usize + TRAMPOLINE; - println!("restore_va: {:?}", restore_va); - println!("trap_cx_ptr :{:?}", trap_cx_ptr); - println!("user_satp :{:?}", user_satp); unsafe { asm!( @@ -129,7 +125,6 @@ fn set_kernel_trap_entry() { // 设置内核法中 trap 的处理 // 当前我们直接panic unsafe { - println!("set_kernel_trap_entry"); stvec::write(trap_from_kernel as usize, TrapMode::Direct); } } @@ -137,7 +132,6 @@ fn set_kernel_trap_entry() { fn set_user_trap_entry() { // 设置 用户态的中断处理函数, 为我们的跳板, 这个跳板在用户空间的虚拟地址最高页, 虚拟地址最高页被映射在了十几物理内存的trap 处理函数所在的段执行__alltraps unsafe { - println!("set_user_trap_entry"); stvec::write(TRAMPOLINE as usize, TrapMode::Direct); } }