// Only support rename, NOT move. fn rename_file(src: &str, dst: &str) -> io::Result<()> { println!("Rename '{}' to '{}' ...", src, dst); fs::rename(src, dst) }
fn print_file(fname: &str) -> io::Result<()> { let mut buf = [0; 1024]; let mut file = File::open(fname)?; loop { let n = file.read(&mut buf)?; if n > 0 { print!("Read '{}' content: [", fname); io::stdout().write_all(&buf[..n])?; println!("] ok!"); } else { return Ok(()); } } }
fn process() -> io::Result<()> { create_file("/tmp/f1", "hello")?; // Just rename, NOT move. // So this must happen in the same directory. rename_file("/tmp/f1", "/tmp/f2")?; print_file("/tmp/f2") }
fn test_hashmap() { const N: u32 = 50_000; let mut m = BTreeMap::new(); for value in 0..N { let key = format!("key_{value}"); m.insert(key, value); } for (k, v) in m.iter() { if let Some(k) = k.strip_prefix("key_") { assert_eq!(k.parse::<u32>().unwrap(), *v); } } println!("test_hashmap() OK!"); }
#[allow(unused_variables)] fn sys_mmap( addr: *mut usize, length: usize, prot: i32, flags: i32, fd: i32, _offset: isize, ) -> isize { syscall_body!(sys_mmap, { // Get the user space address space let curr = current(); let task_ext = curr.task_ext(); let mut aspace = task_ext.aspace.lock();
// Parse flags let mmap_flags = MmapFlags::from_bits_truncate(flags); let mmap_prot = MmapProt::from_bits_truncate(prot);
// Align address and size to page boundaries first let aligned_length = (length + PAGE_SIZE_4K - 1) & !(PAGE_SIZE_4K - 1);
// Allocate virtual address if addr is NULL let aligned_vaddr = if !addr.is_null() { VirtAddr::from(addr as usize).align_down_4k() } else { // Find a suitable virtual address below stack // Stack is at [aspace.end() - USER_STACK_SIZE, aspace.end()) // So we place mmap at aspace.end() - USER_STACK_SIZE - aligned_length (aspace.end() - USER_STACK_SIZE - aligned_length).align_down_4k() };
// Map the memory let mapping_flags = MappingFlags::from(mmap_prot) | MappingFlags::USER; aspace.map_alloc(aligned_vaddr, aligned_length, mapping_flags, true)?;
// If it's a file mapping, read the file and write to the mapped memory if !mmap_flags.contains(MmapFlags::MAP_ANONYMOUS) && fd >= 0 { // Read from file let mut data = vec![0u8; aligned_length]; let mut read_count = 0; while read_count < length { let buf = &mut data[read_count..]; let n = api::sys_read(fd, buf.as_mut_ptr() as *mut c_void, buf.len()); if n <= 0 { break; } read_count += n as usize; }
// Write to mapped memory aspace.write(aligned_vaddr, &data[..read_count])?; }
/// Translate a user pointer to a mutable reference pubfntranslate_user_ptr<T>(ptr: *mut T) -> Option<&'staticmut T> { TASK_MANAGER.translate_user_ptr(ptr) }
/// Translate a user pointer to a reference pubfntranslate_user_ptr_readonly<T>(ptr: *const T) -> Option<&'static T> { TASK_MANAGER.translate_user_ptr_readonly(ptr) }
/// Prints to the standard output, with a newline. #[macro_export] macro_rules! println { () => { $crate::print!("\n") }; ($($arg:tt)*) => { $crate::io::__print_impl(format_args!("\u{1B}[92m{}\u{1B}[m\n", format_args!($($arg)*))); } }
ramfs就是一个最基础的文件系统,不需要回写,不需要驱动,基本上意思就是在内存里进行书写,关机后不会存下来,这个rename也不会再下次开机后保存下来。 学习正常的rename,以前从没看过底层的inode操作,都是直接调用ext_rename()就完工了,所以这次对照着加抄袭整了个版本。 明确这个操作是在ramfs模块下的就简单了,这是个结点操作,所以要在两个地方添加操作(这是我的做法),一个是impl VfsNodeOps for DirNode,一个是DirNode内部。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/// Renames a node from `src_name` to `dst_name` in this directory. pubfnrename_node(&self, src_name: &str, dst_name: &str) -> VfsResult { letmut children = self.children.write();
let node = children.get(src_name).ok_or(VfsError::NotFound)?.clone();
if children.contains_key(dst_name) { returnErr(VfsError::AlreadyExists); } // Remove from old name and insert with new name children.remove(src_name); children.insert(dst_name.into(), node); Ok(()) }
let start_addr = if addr.is_null() { // Use find_free_area to find a suitable address let hint = VirtAddr::from(0x10000000usize); let limit = VirtAddrRange::from_start_size(aspace.base(), aspace.size()); aspace.find_free_area(hint, aligned_length, limit) .ok_or(LinuxError::ENOMEM)? } else { VirtAddr::from(addr asusize) };
// Map memory in user address space aspace.map_alloc(start_addr, aligned_length, mapping_flags, true) .map_err(|_| LinuxError::ENOMEM)?;