From 34e6d6c80f36494088db3284f85d1a2c63aa18a8 Mon Sep 17 00:00:00 2001 From: yuyi2439 <68320855+yuyi2439@users.noreply.github.com> Date: Sun, 8 Oct 2023 14:26:17 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0free=E6=8C=87=E4=BB=A4+?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20mountfs=E7=9A=84=E5=86=85=E5=AD=98?= =?UTF-8?q?=E6=B3=84=E9=9C=B2=E9=97=AE=E9=A2=98(#394)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 实现meminfo文件 * 成功实现free指令,添加了一些string有关函数,并进行一些无影响的小改动 * 解决内存泄露的问题:mountfs inode的wrap方法使用了Arc::into_raw而没有from_raw,导致inode始终无法释放 --------- Co-authored-by: LoGin Co-authored-by: longjin --- docs/userland/libc/apis/api-list/string.md | 33 ++-- kernel/src/arch/x86_64/mm/mod.rs | 27 +-- kernel/src/filesystem/devfs/mod.rs | 2 +- kernel/src/filesystem/procfs/mod.rs | 78 +++++++-- kernel/src/filesystem/vfs/file.rs | 2 +- kernel/src/filesystem/vfs/mount.rs | 6 +- kernel/src/filesystem/vfs/syscall.rs | 10 +- kernel/src/mm/allocator/buddy.rs | 19 ++- kernel/src/mm/allocator/page_frame.rs | 2 +- kernel/src/syscall/mod.rs | 8 +- user/apps/shell/cmd.c | 10 +- user/libs/libc/src/include/export/string.h | 82 +++++++++- user/libs/libc/src/include/export/sys/stat.h | 2 +- user/libs/libc/src/string.c | 163 ++++++++++++++++--- user/libs/libc/src/sys/stat.c | 43 ++++- user/libs/libsystem/syscall.h | 3 +- 16 files changed, 401 insertions(+), 89 deletions(-) diff --git a/docs/userland/libc/apis/api-list/string.md b/docs/userland/libc/apis/api-list/string.md index 88b137b5..19e85dfa 100644 --- a/docs/userland/libc/apis/api-list/string.md +++ b/docs/userland/libc/apis/api-list/string.md @@ -6,20 +6,33 @@ ## 函数列表: - ``size_t strlen(const char *s)`` : 返回字符串长度 - - ``int strcmp(const char *a,const char *b)`` 比较字符串的字典序 + ``size_t strlen(const char *s)`` : 获取字符串的长度 - ``char* strncpy(char *dst,const char *src,size_t count)`` + ``int strcmp(const char *a,const char *b)`` : 比较字符串的字典序 + + ``char *strncpy(char *dst, const char *src, size_t count)`` 拷贝制定字节数的字符串 - dst: 目标地址 - src: 原字符串 - count: 字节数 - - ``char* strcpy(char *dst,const char *src)`` : 复制整个字符串 - ``char* strcat(char *dest,const char* src)`` : 拼接两个字符串 \ No newline at end of file + ``char *strcpy(char *dst,const char *src)`` : 复制整个字符串 + + ``char *strcat(char *dest,const char* src)`` : 拼接两个字符串 + + ``char *strtok(char *str, const char *delim)`` : 分割字符串 + + ``char *strtok_r(char *str, const char *delim, char **saveptr)`` : 分割字符串 + +**以下函数没有经过检验,不确保正常工作** + + ``size_t strspn(const char *str1, const char *str2)`` : 检索字符串 str1 中第一个不在字符串 str2 中出现的字符下标 + + ``size_t strcspn(const char *str1, const char *str2)`` : 检索字符串 str1 开头连续有几个字符都不含字符串 str2 中的字符 + + ``char *strpbrk(const char *str1, const char *str2)`` : 检索字符串 str1 中第一个匹配字符串 str2 中字符的字符 + + ``char *strchr(const char *str, int c)`` : 在字符串中查找第一次出现的字符 + + ``char *strrchr(const char *str, int c)`` : 在字符串中查找最后一次出现的字符 \ No newline at end of file diff --git a/kernel/src/arch/x86_64/mm/mod.rs b/kernel/src/arch/x86_64/mm/mod.rs index 612571dc..70fd95b0 100644 --- a/kernel/src/arch/x86_64/mm/mod.rs +++ b/kernel/src/arch/x86_64/mm/mod.rs @@ -14,7 +14,7 @@ use crate::libs::lib_ui::screen_manager::scm_disable_put_to_window; use crate::libs::printk::PrintkWriter; use crate::libs::spinlock::SpinLock; -use crate::mm::allocator::page_frame::{FrameAllocator, PageFrameCount}; +use crate::mm::allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage}; use crate::mm::mmio_buddy::mmio_init; use crate::{ arch::MMArch, @@ -512,10 +512,7 @@ pub fn test_buddy() { pub struct LockedFrameAllocator; impl FrameAllocator for LockedFrameAllocator { - unsafe fn allocate( - &mut self, - count: crate::mm::allocator::page_frame::PageFrameCount, - ) -> Option<(PhysAddr, PageFrameCount)> { + unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> { if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() { return allocator.allocate(count); } else { @@ -523,19 +520,25 @@ impl FrameAllocator for LockedFrameAllocator { } } - unsafe fn free( - &mut self, - address: crate::mm::PhysAddr, - count: crate::mm::allocator::page_frame::PageFrameCount, - ) { + unsafe fn free(&mut self, address: crate::mm::PhysAddr, count: PageFrameCount) { assert!(count.data().is_power_of_two()); if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() { return allocator.free(address, count); } } - unsafe fn usage(&self) -> crate::mm::allocator::page_frame::PageFrameUsage { - todo!() + unsafe fn usage(&self) -> PageFrameUsage { + if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() { + return allocator.usage(); + } else { + panic!("usage error"); + } + } +} + +impl LockedFrameAllocator { + pub fn get_usage(&self) -> PageFrameUsage { + unsafe { self.usage() } } } diff --git a/kernel/src/filesystem/devfs/mod.rs b/kernel/src/filesystem/devfs/mod.rs index dae7d6e6..89be49fd 100644 --- a/kernel/src/filesystem/devfs/mod.rs +++ b/kernel/src/filesystem/devfs/mod.rs @@ -562,7 +562,7 @@ pub fn devfs_init() -> Result<(), SystemError> { static INIT: Once = Once::new(); let mut result = None; INIT.call_once(|| { - kinfo!("Initializing ProcFS..."); + kinfo!("Initializing DevFS..."); // 创建 devfs 实例 let devfs: Arc = DevFS::new(); // devfs 挂载 diff --git a/kernel/src/filesystem/procfs/mod.rs b/kernel/src/filesystem/procfs/mod.rs index 3c7a822f..59736267 100644 --- a/kernel/src/filesystem/procfs/mod.rs +++ b/kernel/src/filesystem/procfs/mod.rs @@ -10,6 +10,7 @@ use alloc::{ }; use crate::{ + arch::mm::LockedFrameAllocator, filesystem::vfs::{ core::{generate_inode_id, ROOT_INODE}, FileType, @@ -37,6 +38,8 @@ use super::vfs::{ pub enum ProcFileType { ///展示进程状态信息 ProcStatus = 0, + /// meminfo + ProcMeminfo = 1, //todo: 其他文件类型 ///默认文件类型 Default, @@ -46,6 +49,7 @@ impl From for ProcFileType { fn from(value: u8) -> Self { match value { 0 => ProcFileType::ProcStatus, + 1 => ProcFileType::ProcMeminfo, _ => ProcFileType::Default, } } @@ -204,8 +208,34 @@ impl ProcFSInode { return Ok((pdata.len() * size_of::()) as i64); } - /// status文件读取函数 - fn read_status( + /// 打开 meminfo 文件 + fn open_meminfo(&self, pdata: &mut ProcfsFilePrivateData) -> Result { + // 获取内存信息 + let usage = LockedFrameAllocator.get_usage(); + + // 传入数据 + let data: &mut Vec = &mut pdata.data; + + data.append( + &mut format!("MemTotal:\t{} kB\n", usage.total().bytes() >> 10) + .as_bytes() + .to_owned(), + ); + + data.append( + &mut format!("MemFree:\t{} kB\n", usage.free().bytes() >> 10) + .as_bytes() + .to_owned(), + ); + + // 去除多余的\0 + self.trim_string(data); + + return Ok((data.len() * size_of::()) as i64); + } + + /// proc文件系统读取函数 + fn proc_read( &self, offset: usize, len: usize, @@ -263,7 +293,7 @@ impl ProcFS { mtime: TimeSpec::default(), ctime: TimeSpec::default(), file_type: FileType::Dir, - mode: ModeType::from_bits_truncate(0o777), + mode: ModeType::from_bits_truncate(0o555), nlinks: 1, uid: 0, gid: 0, @@ -286,6 +316,24 @@ impl ProcFS { // 释放锁 drop(root_guard); + // 创建meminfo文件 + let inode = result.root_inode(); + let binding = inode.create( + "meminfo", + FileType::File, + ModeType::from_bits_truncate(0o444), + ); + if let Ok(meminfo) = binding { + let meminfo_file = meminfo + .as_any_ref() + .downcast_ref::() + .unwrap(); + meminfo_file.0.lock().fdata.pid = Pid::new(0); + meminfo_file.0.lock().fdata.ftype = ProcFileType::ProcMeminfo; + } else { + panic!("create meminfo error"); + } + return result; } @@ -293,26 +341,26 @@ impl ProcFS { /// @usage 在进程中调用并创建进程对应文件 pub fn register_pid(&self, pid: Pid) -> Result<(), SystemError> { // 获取当前inode - let proc: Arc = self.root_inode(); + let inode: Arc = self.root_inode(); // 创建对应进程文件夹 - let _pf: Arc = proc.create( + let pid_dir: Arc = inode.create( &pid.to_string(), FileType::Dir, - ModeType::from_bits_truncate(0o777), + ModeType::from_bits_truncate(0o555), )?; // 创建相关文件 // status文件 - let binding: Arc = _pf.create( + let binding: Arc = pid_dir.create( "status", FileType::File, - ModeType::from_bits_truncate(0o777), + ModeType::from_bits_truncate(0o444), )?; - let _sf: &LockedProcFSInode = binding + let status_file: &LockedProcFSInode = binding .as_any_ref() .downcast_ref::() .unwrap(); - _sf.0.lock().fdata.pid = pid; - _sf.0.lock().fdata.ftype = ProcFileType::ProcStatus; + status_file.0.lock().fdata.pid = pid; + status_file.0.lock().fdata.ftype = ProcFileType::ProcStatus; //todo: 创建其他文件 @@ -352,6 +400,7 @@ impl IndexNode for LockedProcFSInode { // 根据文件类型获取相应数据 let file_size = match inode.fdata.ftype { ProcFileType::ProcStatus => inode.open_status(&mut private_data)?, + ProcFileType::ProcMeminfo => inode.open_meminfo(&mut private_data)?, _ => { todo!() } @@ -409,7 +458,8 @@ impl IndexNode for LockedProcFSInode { // 根据文件类型读取相应数据 match inode.fdata.ftype { - ProcFileType::ProcStatus => return inode.read_status(offset, len, buf, private_data), + ProcFileType::ProcStatus => return inode.proc_read(offset, len, buf, private_data), + ProcFileType::ProcMeminfo => return inode.proc_read(offset, len, buf, private_data), ProcFileType::Default => (), }; @@ -720,10 +770,10 @@ pub fn procfs_init() -> Result<(), SystemError> { let mut result = None; INIT.call_once(|| { kinfo!("Initializing ProcFS..."); - // 创建 sysfs 实例 + // 创建 procfs 实例 let procfs: Arc = ProcFS::new(); - // sysfs 挂载 + // procfs 挂载 let _t = ROOT_INODE() .find("proc") .expect("Cannot find /proc") diff --git a/kernel/src/filesystem/vfs/file.rs b/kernel/src/filesystem/vfs/file.rs index 68186027..e56aec28 100644 --- a/kernel/src/filesystem/vfs/file.rs +++ b/kernel/src/filesystem/vfs/file.rs @@ -261,7 +261,6 @@ impl File { self.readdir_subdirs_name = inode.list()?; self.readdir_subdirs_name.sort(); } - // kdebug!("sub_entries={sub_entries:?}"); if self.readdir_subdirs_name.is_empty() { self.offset = 0; @@ -513,6 +512,7 @@ impl FileDescriptorVec { // 把文件描述符数组对应位置设置为空 let file = self.fds[fd as usize].take().unwrap(); + assert!(Arc::strong_count(&file) == 1); return Ok(()); } diff --git a/kernel/src/filesystem/vfs/mount.rs b/kernel/src/filesystem/vfs/mount.rs index ffa84d65..47843115 100644 --- a/kernel/src/filesystem/vfs/mount.rs +++ b/kernel/src/filesystem/vfs/mount.rs @@ -63,11 +63,11 @@ impl MountFS { let weak: Weak = Arc::downgrade(&mount_fs); // 将Arc指针转为Raw指针并对其内部的self_ref字段赋值 - let ptr: *mut MountFS = Arc::into_raw(mount_fs) as *mut Self; + let ptr: *mut MountFS = mount_fs.as_ref() as *const Self as *mut Self; unsafe { (*ptr).self_ref = weak; // 返回初始化好的MountFS对象 - return Arc::from_raw(ptr); + return mount_fs; } } @@ -97,7 +97,7 @@ impl MountFSInode { let weak: Weak = Arc::downgrade(&inode); // 将Arc指针转为Raw指针并对其内部的self_ref字段赋值 compiler_fence(Ordering::SeqCst); - let ptr: *mut MountFSInode = Arc::into_raw(inode.clone()) as *mut Self; + let ptr: *mut MountFSInode = inode.as_ref() as *const Self as *mut Self; compiler_fence(Ordering::SeqCst); unsafe { (*ptr).self_ref = weak; diff --git a/kernel/src/filesystem/vfs/syscall.rs b/kernel/src/filesystem/vfs/syscall.rs index 985f3f4a..9c383817 100644 --- a/kernel/src/filesystem/vfs/syscall.rs +++ b/kernel/src/filesystem/vfs/syscall.rs @@ -184,6 +184,7 @@ impl Syscall { } // 创建文件对象 + let mut file: File = File::new(inode, mode)?; // 打开模式为“追加” @@ -210,7 +211,9 @@ impl Syscall { let binding = ProcessManager::current_pcb().fd_table(); let mut fd_table_guard = binding.write(); - return fd_table_guard.drop_fd(fd as i32).map(|_| 0); + let res = fd_table_guard.drop_fd(fd as i32).map(|_| 0); + + return res; } /// @brief 根据文件描述符,读取文件数据。尝试读取的数据长度与buf的长度相同。 @@ -389,7 +392,10 @@ impl Syscall { // drop guard 以避免无法调度的问题 drop(fd_table_guard); - return file.lock_no_preempt().readdir(dirent).map(|x| x as usize); + + let res = file.lock_no_preempt().readdir(dirent).map(|x| x as usize); + + return res; } /// @brief 创建文件夹 diff --git a/kernel/src/mm/allocator/buddy.rs b/kernel/src/mm/allocator/buddy.rs index b4cfde15..f56c6177 100644 --- a/kernel/src/mm/allocator/buddy.rs +++ b/kernel/src/mm/allocator/buddy.rs @@ -65,6 +65,8 @@ impl PageList { pub struct BuddyAllocator { // 存放每个阶的空闲“链表”的头部地址 free_area: [PhysAddr; (MAX_ORDER - MIN_ORDER) as usize], + /// 总页数 + total: PageFrameCount, phantom: PhantomData, } @@ -227,9 +229,9 @@ impl BuddyAllocator { assert!(remain_bytes == 0); assert!(paddr == initial_bump_offset + pages_to_buddy.data() * A::PAGE_SIZE); - // Self::print_free_area(free_area); let allocator = Self { free_area, + total: pages_to_buddy, phantom: PhantomData, }; @@ -357,7 +359,6 @@ impl BuddyAllocator { } return None; }; - let result: Option = alloc_in_specific_order(order as u8); // kdebug!("result={:?}", result); if result.is_some() { @@ -662,7 +663,19 @@ impl FrameAllocator for BuddyAllocator { } unsafe fn usage(&self) -> PageFrameUsage { - todo!("BuddyAllocator::usage") + let mut free_page_num: usize = 0; + for index in 0..(MAX_ORDER - MIN_ORDER) { + let mut pagelist: PageList = Self::read_page(self.free_area[index]); + loop { + free_page_num += pagelist.entry_num << index; + if pagelist.next_page.is_null() { + break; + } + pagelist = Self::read_page(pagelist.next_page); + } + } + let free = PageFrameCount::new(free_page_num); + PageFrameUsage::new(self.total - free, self.total) } } diff --git a/kernel/src/mm/allocator/page_frame.rs b/kernel/src/mm/allocator/page_frame.rs index 9be4538e..db8ba699 100644 --- a/kernel/src/mm/allocator/page_frame.rs +++ b/kernel/src/mm/allocator/page_frame.rs @@ -273,7 +273,7 @@ impl PageFrameUsage { } // @brief 获取空闲的页帧数量 pub fn free(&self) -> PageFrameCount { - return PageFrameCount(self.total.0 - self.used.0); + return self.total - self.used; } // @brief 获取总的页帧数量 pub fn total(&self) -> PageFrameCount { diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index bb5f7c6b..1c1bafd0 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -417,9 +417,9 @@ impl Syscall { Err(SystemError::EINVAL) } else { let path: &str = path.unwrap(); + let flags = args[1]; let open_flags: FileMode = FileMode::from_bits_truncate(flags as u32); - Self::open(path, open_flags) }; @@ -427,7 +427,10 @@ impl Syscall { } SYS_CLOSE => { let fd = args[0]; - Self::close(fd) + + let res = Self::close(fd); + + res } SYS_READ => { let fd = args[0] as i32; @@ -545,6 +548,7 @@ impl Syscall { SYS_GET_DENTS => { let fd = args[0] as i32; + let buf_vaddr = args[1]; let len = args[2]; let virt_addr: VirtAddr = VirtAddr::new(buf_vaddr); diff --git a/user/apps/shell/cmd.c b/user/apps/shell/cmd.c index 564dcdb8..8b5ea8f8 100644 --- a/user/apps/shell/cmd.c +++ b/user/apps/shell/cmd.c @@ -320,7 +320,7 @@ int shell_cmd_cat(int argc, char **argv) char *file_path = get_target_filepath(argv[1], &path_len); // 打开文件 - int fd = open(file_path, 0); + int fd = open(file_path, O_RDONLY); if (fd <= 0) { printf("ERROR: Cannot open file: %s, fd=%d\n", file_path, fd); @@ -593,13 +593,13 @@ int shell_cmd_free(int argc, char **argv) printf("Mem:\t"); if (argc == 1) // 按照kb显示 { - printf("%ld\t%ld\t%ld\t%ld\t%ld\t%ld\t\n", mst.total >> 10, mst.used >> 10, mst.free >> 10, mst.shared >> 10, - mst.cache_used >> 10, mst.available >> 10); + printf("%ld\t%ld\t%ld\t%ld\t%ld\t%ld\t\n", mst.total, mst.used, mst.free, mst.shared, + mst.cache_used, mst.available); } else // 按照MB显示 { - printf("%ld\t%ld\t%ld\t%ld\t%ld\t%ld\t\n", mst.total >> 20, mst.used >> 20, mst.free >> 20, mst.shared >> 20, - mst.cache_used >> 20, mst.available >> 20); + printf("%ld\t%ld\t%ld\t%ld\t%ld\t%ld\t\n", mst.total >> 10, mst.used >> 10, mst.free >> 10, mst.shared >> 10, + mst.cache_used >> 10, mst.available >> 10); } done:; diff --git a/user/libs/libc/src/include/export/string.h b/user/libs/libc/src/include/export/string.h index 5bf64e9a..cd2f9880 100644 --- a/user/libs/libc/src/include/export/string.h +++ b/user/libs/libc/src/include/export/string.h @@ -7,21 +7,21 @@ extern "C" { #endif void *memset(void *dst, unsigned char C, uint64_t size); + /** - * @brief 获取字符串的大小 + * @brief 获取字符串的长度 * * @param s 字符串 - * @return size_t 大小 + * @return size_t 长度 */ size_t strlen(const char *s); /* - 比较字符串 FirstPart and SecondPart - FirstPart = SecondPart => 0 - FirstPart > SecondPart => 1 - FirstPart < SecondPart => -1 + 比较字符串 FirstPart and SecondPart + FirstPart = SecondPart => 0 + FirstPart > SecondPart => 1 + FirstPart < SecondPart => -1 */ - int strcmp(const char *FirstPart, const char *SecondPart); /** @@ -32,7 +32,7 @@ int strcmp(const char *FirstPart, const char *SecondPart); * @param Count 字节数 * @return char* */ -char *strncpy(char *dst, const char *src, size_t Count); +char *strncpy(char *dst, const char *src, size_t count); /** * @brief 拷贝整个字符串 @@ -82,6 +82,72 @@ static void *memcpy(void *dst, const void *src, long Num) return dst; } +/** + * @brief 分割字符串 + * + * @param str 要被分解成一组小字符串的字符串 + * @param delim 包含分隔符的字符串 + * @return 分割结果 + */ +char *strtok(char *str, const char *delim); + +/** + * @brief 分割字符串 + * + * @param str 要被分解成一组小字符串的字符串 + * @param delim 包含分隔符的字符串 + * @param saveptr 用于存储当前操作的字符串 + * @return 分割结果 + */ +char *strtok_r(char *str, const char *delim, char **saveptr); + +//! 以下函数没有经过检验,不确保正常工作 + +/** + * @brief 检索字符串 str1 中第一个不在字符串 str2 中出现的字符下标 + * + * @param str1 被检索的字符串 + * @param str2 进行匹配的字符列表 + * @return str1 中第一个不在字符串 str2 中出现的字符下标 + */ +size_t strspn(const char *str1, const char *str2); + +/** + * @brief 检索字符串 str1 开头连续有几个字符都不含字符串 str2 中的字符 + * + * @param str1 被检索的字符串 + * @param str2 进行匹配的字符列表 + * @return str1 开头连续都不含字符串 str2 中字符的字符数 + */ +size_t strcspn(const char *str1, const char *str2); + +/** + * @brief 检索字符串 str1 中第一个匹配字符串 str2 中字符的字符 + * + * @param str1 被检索的字符串 + * @param str2 进行匹配的字符列表 + * @return str1 中第一个匹配字符串 str2 中字符的指针,如果未找到字符则返回 NULL + */ +char *strpbrk(const char *str1, const char *str2); + +/** + * @brief 在字符串中查找第一次出现的字符 + * + * @param str 被查找的字符串 + * @param c 要查找的字符 + * @return 指向找到的字符的指针,如果未找到该字符则返回 NULL + */ +char *strchr(const char *str, int c); + +/** + * @brief 在字符串中查找最后一次出现的字符 + * + * @param str 被查找的字符串 + * @param c 要查找的字符 + * @return 指向找到的字符的指针,如果未找到该字符则返回 NULL + */ +char *strrchr(const char *str, int c); + #if defined(__cplusplus) } /* extern "C" */ #endif diff --git a/user/libs/libc/src/include/export/sys/stat.h b/user/libs/libc/src/include/export/sys/stat.h index 7af491c3..452a4e54 100644 --- a/user/libs/libc/src/include/export/sys/stat.h +++ b/user/libs/libc/src/include/export/sys/stat.h @@ -2,7 +2,7 @@ #include /** - * @brief 系统内存信息结构体(单位:字节) + * @brief 系统内存信息结构体(单位:kB) * */ struct mstat_t diff --git a/user/libs/libc/src/string.c b/user/libs/libc/src/string.c index 69698054..948295fc 100644 --- a/user/libs/libc/src/string.c +++ b/user/libs/libc/src/string.c @@ -1,4 +1,5 @@ #include +#include size_t strlen(const char *s) { @@ -57,15 +58,7 @@ void *memset(void *dst, unsigned char C, uint64_t size) return dst; } -/** - * @brief 拷贝指定字节数的字符串 - * - * @param dst 目标地址 - * @param src 源字符串 - * @param Count 字节数 - * @return char* - */ -char *strncpy(char *dst, const char *src, size_t Count) +char *strncpy(char *dst, const char *src, size_t count) { __asm__ __volatile__("cld \n\t" "1: \n\t" @@ -79,31 +72,17 @@ char *strncpy(char *dst, const char *src, size_t Count) "stosb \n\t" "2: \n\t" : - : "S"(src), "D"(dst), "c"(Count) + : "S"(src), "D"(dst), "c"(count) : "ax", "memory"); return dst; } -/** - * @brief 拼接两个字符串(将src接到dest末尾) - * - * @param dest 目标串 - * @param src 源串 - * @return char* - */ char *strcat(char *dest, const char *src) { strcpy(dest + strlen(dest), src); return dest; } -/** - * @brief 拷贝整个字符串 - * - * @param dst 目标地址 - * @param src 源地址 - * @return char* 目标字符串 - */ char *strcpy(char *dst, const char *src) { while (*src) @@ -113,4 +92,140 @@ char *strcpy(char *dst, const char *src) *dst = 0; return dst; +} + +char *strtok(char *str, const char *delim) +{ + static char *saveptr; + return strtok_r(str, delim, &saveptr); +} + +char *strtok_r(char *str, const char *delim, char **saveptr) +{ + char *end; + if (str == NULL) + str = *saveptr; + if (*str == '\0') + { + *saveptr = str; + return NULL; + } + str += strspn(str, delim); + if (*str == '\0') + { + *saveptr = str; + return NULL; + } + end = str + strcspn(str, delim); + if (*end == '\0') + { + *saveptr = end; + return str; + } + *end = '\0'; + *saveptr = end + 1; + return str; +} + +size_t strspn(const char *str1, const char *str2) +{ + if (str1 == NULL || str2 == NULL) + return 0; + bool cset[256] = {0}; + while ((*str2) != '\0') + { + cset[*str2] = 1; + ++str2; + } + int index = 0; + while (str1[index] != '\0') + { + if (cset[str1[index]]) + index++; + else + break; + } + return index; +} + +size_t strcspn(const char *str1, const char *str2) +{ + if (str1 == NULL || str2 == NULL) + return 0; + bool cset[256] = {0}; + while ((*str2) != '\0') + { + cset[*str2] = 1; + ++str2; + } + int len = 0; + while (str1[len] != '\0') + { + if (!cset[str1[len]]) + len++; + else + break; + } + return len; +} + +char *strpbrk(const char *str1, const char *str2) +{ + typedef unsigned char uchar; + + if (str1 == NULL || str2 == NULL) + return NULL; + uchar cset[32] = {0}; + while ((*str2) != '\0') + { + uchar t = (uchar)*str2++; + cset[t % 32] |= 1 << (t / 32); + } + while ((*str1) != '\0') + { + uchar t = (uchar)*str1; + if (cset[t % 32] & (1 << (t / 32))) + { + return (char *)str1; + } + else + { + ++str1; + } + } + return NULL; +} + +char *strchr(const char *str, int c) +{ + if (str == NULL) + return NULL; + + while (*str != '\0') + { + if (*str == c) + { + return str; + } + str++; + } + return NULL; +} + +char *strrchr(const char *str, int c) +{ + if (str == NULL) + return NULL; + + char *p_char = NULL; + while (*str != '\0') + { + if (*str == (char)c) + { + p_char = (char *)str; + } + str++; + } + + return p_char; } \ No newline at end of file diff --git a/user/libs/libc/src/sys/stat.c b/user/libs/libc/src/sys/stat.c index 4eca1461..ff112679 100644 --- a/user/libs/libc/src/sys/stat.c +++ b/user/libs/libc/src/sys/stat.c @@ -1,5 +1,10 @@ #include #include +#include +#include +#include +#include +#include int mkdir(const char *path, mode_t mode) { @@ -14,5 +19,41 @@ int mkdir(const char *path, mode_t mode) */ int mstat(struct mstat_t *stat) { - return syscall_invoke(SYS_MSTAT, (uint64_t)stat, 0, 0, 0, 0, 0, 0, 0); + char *buf = (char *)malloc(128); + memset(buf, 0, 128); + int fd = open("/proc/meminfo", O_RDONLY); + if (fd <= 0) + { + printf("ERROR: Cannot open file: /proc/meminfo, fd=%d\n", fd); + return -1; + } + read(fd, buf, 127); + close(fd); + char *str = strtok(buf, "\n\t"); + char *value = (char *)malloc(strlen(str) - 3); + int count = 0; + while (str != NULL) + { + // printf("%d: %s\n", count, str); + switch (count) + { + case 1: + strncpy(value, str, strlen(str) - 3); + stat->total = atoi(value); + break; + case 3: + strncpy(value, str, strlen(str) - 3); + stat->free = atoi(value); + break; + default: + break; + } + str = strtok(NULL, "\n\t"); + count++; + } + stat->used = stat->total - stat->free; + + free(buf); + free(value); + return 0; } diff --git a/user/libs/libsystem/syscall.h b/user/libs/libsystem/syscall.h index 268f6df8..d5ba276d 100644 --- a/user/libs/libsystem/syscall.h +++ b/user/libs/libsystem/syscall.h @@ -26,7 +26,8 @@ #define SYS_CLOCK 19 // 获取当前cpu时间 #define SYS_PIPE 20 -#define SYS_MSTAT 21 // 获取系统的内存状态信息 +// 现在已经废弃 +// #define SYS_MSTAT 21 // 获取系统的内存状态信息 #define SYS_UNLINK_AT 22 // 删除文件夹/删除文件链接 #define SYS_KILL 23 // kill一个进程(向这个进程发出信号) #define SYS_SIGACTION 24 // 设置进程的信号处理动作