实现free指令+修复 mountfs的内存泄露问题(#394)

* 实现meminfo文件

* 成功实现free指令,添加了一些string有关函数,并进行一些无影响的小改动


* 解决内存泄露的问题:mountfs inode的wrap方法使用了Arc::into_raw而没有from_raw,导致inode始终无法释放

---------

Co-authored-by: LoGin <longjin@DragonOS.org>
Co-authored-by: longjin <longjin@RinGoTek.cn>
This commit is contained in:
yuyi2439 2023-10-08 14:26:17 +08:00 committed by GitHub
parent afc95d5c25
commit 34e6d6c80f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 401 additions and 89 deletions

View File

@ -6,20 +6,33 @@
## 函数列表: ## 函数列表:
``size_t strlen(const char *s)`` : 返回字符串长度 ``size_t strlen(const char *s)`` : 获取字符串的长度
``int strcmp(const char *a,const char *b)`` 比较字符串的字典序
``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: 目标地址 dst: 目标地址
src 原字符串 src 原字符串
count: 字节数 count: 字节数
``char* strcpy(char *dst,const char *src)`` : 复制整个字符串
``char* strcat(char *dest,const char* src)`` : 拼接两个字符串 ``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)`` : 在字符串中查找最后一次出现的字符

View File

@ -14,7 +14,7 @@ use crate::libs::lib_ui::screen_manager::scm_disable_put_to_window;
use crate::libs::printk::PrintkWriter; use crate::libs::printk::PrintkWriter;
use crate::libs::spinlock::SpinLock; 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::mm::mmio_buddy::mmio_init;
use crate::{ use crate::{
arch::MMArch, arch::MMArch,
@ -512,10 +512,7 @@ pub fn test_buddy() {
pub struct LockedFrameAllocator; pub struct LockedFrameAllocator;
impl FrameAllocator for LockedFrameAllocator { impl FrameAllocator for LockedFrameAllocator {
unsafe fn allocate( unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
&mut self,
count: crate::mm::allocator::page_frame::PageFrameCount,
) -> Option<(PhysAddr, PageFrameCount)> {
if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() { if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() {
return allocator.allocate(count); return allocator.allocate(count);
} else { } else {
@ -523,19 +520,25 @@ impl FrameAllocator for LockedFrameAllocator {
} }
} }
unsafe fn free( unsafe fn free(&mut self, address: crate::mm::PhysAddr, count: PageFrameCount) {
&mut self,
address: crate::mm::PhysAddr,
count: crate::mm::allocator::page_frame::PageFrameCount,
) {
assert!(count.data().is_power_of_two()); assert!(count.data().is_power_of_two());
if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() { if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() {
return allocator.free(address, count); return allocator.free(address, count);
} }
} }
unsafe fn usage(&self) -> crate::mm::allocator::page_frame::PageFrameUsage { unsafe fn usage(&self) -> PageFrameUsage {
todo!() 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() }
} }
} }

View File

@ -562,7 +562,7 @@ pub fn devfs_init() -> Result<(), SystemError> {
static INIT: Once = Once::new(); static INIT: Once = Once::new();
let mut result = None; let mut result = None;
INIT.call_once(|| { INIT.call_once(|| {
kinfo!("Initializing ProcFS..."); kinfo!("Initializing DevFS...");
// 创建 devfs 实例 // 创建 devfs 实例
let devfs: Arc<DevFS> = DevFS::new(); let devfs: Arc<DevFS> = DevFS::new();
// devfs 挂载 // devfs 挂载

View File

@ -10,6 +10,7 @@ use alloc::{
}; };
use crate::{ use crate::{
arch::mm::LockedFrameAllocator,
filesystem::vfs::{ filesystem::vfs::{
core::{generate_inode_id, ROOT_INODE}, core::{generate_inode_id, ROOT_INODE},
FileType, FileType,
@ -37,6 +38,8 @@ use super::vfs::{
pub enum ProcFileType { pub enum ProcFileType {
///展示进程状态信息 ///展示进程状态信息
ProcStatus = 0, ProcStatus = 0,
/// meminfo
ProcMeminfo = 1,
//todo: 其他文件类型 //todo: 其他文件类型
///默认文件类型 ///默认文件类型
Default, Default,
@ -46,6 +49,7 @@ impl From<u8> for ProcFileType {
fn from(value: u8) -> Self { fn from(value: u8) -> Self {
match value { match value {
0 => ProcFileType::ProcStatus, 0 => ProcFileType::ProcStatus,
1 => ProcFileType::ProcMeminfo,
_ => ProcFileType::Default, _ => ProcFileType::Default,
} }
} }
@ -204,8 +208,34 @@ impl ProcFSInode {
return Ok((pdata.len() * size_of::<u8>()) as i64); return Ok((pdata.len() * size_of::<u8>()) as i64);
} }
/// status文件读取函数 /// 打开 meminfo 文件
fn read_status( fn open_meminfo(&self, pdata: &mut ProcfsFilePrivateData) -> Result<i64, SystemError> {
// 获取内存信息
let usage = LockedFrameAllocator.get_usage();
// 传入数据
let data: &mut Vec<u8> = &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::<u8>()) as i64);
}
/// proc文件系统读取函数
fn proc_read(
&self, &self,
offset: usize, offset: usize,
len: usize, len: usize,
@ -263,7 +293,7 @@ impl ProcFS {
mtime: TimeSpec::default(), mtime: TimeSpec::default(),
ctime: TimeSpec::default(), ctime: TimeSpec::default(),
file_type: FileType::Dir, file_type: FileType::Dir,
mode: ModeType::from_bits_truncate(0o777), mode: ModeType::from_bits_truncate(0o555),
nlinks: 1, nlinks: 1,
uid: 0, uid: 0,
gid: 0, gid: 0,
@ -286,6 +316,24 @@ impl ProcFS {
// 释放锁 // 释放锁
drop(root_guard); 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::<LockedProcFSInode>()
.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; return result;
} }
@ -293,26 +341,26 @@ impl ProcFS {
/// @usage 在进程中调用并创建进程对应文件 /// @usage 在进程中调用并创建进程对应文件
pub fn register_pid(&self, pid: Pid) -> Result<(), SystemError> { pub fn register_pid(&self, pid: Pid) -> Result<(), SystemError> {
// 获取当前inode // 获取当前inode
let proc: Arc<dyn IndexNode> = self.root_inode(); let inode: Arc<dyn IndexNode> = self.root_inode();
// 创建对应进程文件夹 // 创建对应进程文件夹
let _pf: Arc<dyn IndexNode> = proc.create( let pid_dir: Arc<dyn IndexNode> = inode.create(
&pid.to_string(), &pid.to_string(),
FileType::Dir, FileType::Dir,
ModeType::from_bits_truncate(0o777), ModeType::from_bits_truncate(0o555),
)?; )?;
// 创建相关文件 // 创建相关文件
// status文件 // status文件
let binding: Arc<dyn IndexNode> = _pf.create( let binding: Arc<dyn IndexNode> = pid_dir.create(
"status", "status",
FileType::File, FileType::File,
ModeType::from_bits_truncate(0o777), ModeType::from_bits_truncate(0o444),
)?; )?;
let _sf: &LockedProcFSInode = binding let status_file: &LockedProcFSInode = binding
.as_any_ref() .as_any_ref()
.downcast_ref::<LockedProcFSInode>() .downcast_ref::<LockedProcFSInode>()
.unwrap(); .unwrap();
_sf.0.lock().fdata.pid = pid; status_file.0.lock().fdata.pid = pid;
_sf.0.lock().fdata.ftype = ProcFileType::ProcStatus; status_file.0.lock().fdata.ftype = ProcFileType::ProcStatus;
//todo: 创建其他文件 //todo: 创建其他文件
@ -352,6 +400,7 @@ impl IndexNode for LockedProcFSInode {
// 根据文件类型获取相应数据 // 根据文件类型获取相应数据
let file_size = match inode.fdata.ftype { let file_size = match inode.fdata.ftype {
ProcFileType::ProcStatus => inode.open_status(&mut private_data)?, ProcFileType::ProcStatus => inode.open_status(&mut private_data)?,
ProcFileType::ProcMeminfo => inode.open_meminfo(&mut private_data)?,
_ => { _ => {
todo!() todo!()
} }
@ -409,7 +458,8 @@ impl IndexNode for LockedProcFSInode {
// 根据文件类型读取相应数据 // 根据文件类型读取相应数据
match inode.fdata.ftype { 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 => (), ProcFileType::Default => (),
}; };
@ -720,10 +770,10 @@ pub fn procfs_init() -> Result<(), SystemError> {
let mut result = None; let mut result = None;
INIT.call_once(|| { INIT.call_once(|| {
kinfo!("Initializing ProcFS..."); kinfo!("Initializing ProcFS...");
// 创建 sysfs 实例 // 创建 procfs 实例
let procfs: Arc<ProcFS> = ProcFS::new(); let procfs: Arc<ProcFS> = ProcFS::new();
// sysfs 挂载 // procfs 挂载
let _t = ROOT_INODE() let _t = ROOT_INODE()
.find("proc") .find("proc")
.expect("Cannot find /proc") .expect("Cannot find /proc")

View File

@ -261,7 +261,6 @@ impl File {
self.readdir_subdirs_name = inode.list()?; self.readdir_subdirs_name = inode.list()?;
self.readdir_subdirs_name.sort(); self.readdir_subdirs_name.sort();
} }
// kdebug!("sub_entries={sub_entries:?}"); // kdebug!("sub_entries={sub_entries:?}");
if self.readdir_subdirs_name.is_empty() { if self.readdir_subdirs_name.is_empty() {
self.offset = 0; self.offset = 0;
@ -513,6 +512,7 @@ impl FileDescriptorVec {
// 把文件描述符数组对应位置设置为空 // 把文件描述符数组对应位置设置为空
let file = self.fds[fd as usize].take().unwrap(); let file = self.fds[fd as usize].take().unwrap();
assert!(Arc::strong_count(&file) == 1); assert!(Arc::strong_count(&file) == 1);
return Ok(()); return Ok(());
} }

View File

@ -63,11 +63,11 @@ impl MountFS {
let weak: Weak<MountFS> = Arc::downgrade(&mount_fs); let weak: Weak<MountFS> = Arc::downgrade(&mount_fs);
// 将Arc指针转为Raw指针并对其内部的self_ref字段赋值 // 将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 { unsafe {
(*ptr).self_ref = weak; (*ptr).self_ref = weak;
// 返回初始化好的MountFS对象 // 返回初始化好的MountFS对象
return Arc::from_raw(ptr); return mount_fs;
} }
} }
@ -97,7 +97,7 @@ impl MountFSInode {
let weak: Weak<MountFSInode> = Arc::downgrade(&inode); let weak: Weak<MountFSInode> = Arc::downgrade(&inode);
// 将Arc指针转为Raw指针并对其内部的self_ref字段赋值 // 将Arc指针转为Raw指针并对其内部的self_ref字段赋值
compiler_fence(Ordering::SeqCst); 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); compiler_fence(Ordering::SeqCst);
unsafe { unsafe {
(*ptr).self_ref = weak; (*ptr).self_ref = weak;

View File

@ -184,6 +184,7 @@ impl Syscall {
} }
// 创建文件对象 // 创建文件对象
let mut file: File = File::new(inode, mode)?; let mut file: File = File::new(inode, mode)?;
// 打开模式为“追加” // 打开模式为“追加”
@ -210,7 +211,9 @@ impl Syscall {
let binding = ProcessManager::current_pcb().fd_table(); let binding = ProcessManager::current_pcb().fd_table();
let mut fd_table_guard = binding.write(); 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的长度相同。 /// @brief 根据文件描述符读取文件数据。尝试读取的数据长度与buf的长度相同。
@ -389,7 +392,10 @@ impl Syscall {
// drop guard 以避免无法调度的问题 // drop guard 以避免无法调度的问题
drop(fd_table_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 创建文件夹 /// @brief 创建文件夹

View File

@ -65,6 +65,8 @@ impl<A> PageList<A> {
pub struct BuddyAllocator<A> { pub struct BuddyAllocator<A> {
// 存放每个阶的空闲“链表”的头部地址 // 存放每个阶的空闲“链表”的头部地址
free_area: [PhysAddr; (MAX_ORDER - MIN_ORDER) as usize], free_area: [PhysAddr; (MAX_ORDER - MIN_ORDER) as usize],
/// 总页数
total: PageFrameCount,
phantom: PhantomData<A>, phantom: PhantomData<A>,
} }
@ -227,9 +229,9 @@ impl<A: MemoryManagementArch> BuddyAllocator<A> {
assert!(remain_bytes == 0); assert!(remain_bytes == 0);
assert!(paddr == initial_bump_offset + pages_to_buddy.data() * A::PAGE_SIZE); assert!(paddr == initial_bump_offset + pages_to_buddy.data() * A::PAGE_SIZE);
// Self::print_free_area(free_area);
let allocator = Self { let allocator = Self {
free_area, free_area,
total: pages_to_buddy,
phantom: PhantomData, phantom: PhantomData,
}; };
@ -357,7 +359,6 @@ impl<A: MemoryManagementArch> BuddyAllocator<A> {
} }
return None; return None;
}; };
let result: Option<PhysAddr> = alloc_in_specific_order(order as u8); let result: Option<PhysAddr> = alloc_in_specific_order(order as u8);
// kdebug!("result={:?}", result); // kdebug!("result={:?}", result);
if result.is_some() { if result.is_some() {
@ -662,7 +663,19 @@ impl<A: MemoryManagementArch> FrameAllocator for BuddyAllocator<A> {
} }
unsafe fn usage(&self) -> PageFrameUsage { 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<A> = 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)
} }
} }

View File

@ -273,7 +273,7 @@ impl PageFrameUsage {
} }
// @brief 获取空闲的页帧数量 // @brief 获取空闲的页帧数量
pub fn free(&self) -> PageFrameCount { pub fn free(&self) -> PageFrameCount {
return PageFrameCount(self.total.0 - self.used.0); return self.total - self.used;
} }
// @brief 获取总的页帧数量 // @brief 获取总的页帧数量
pub fn total(&self) -> PageFrameCount { pub fn total(&self) -> PageFrameCount {

View File

@ -417,9 +417,9 @@ impl Syscall {
Err(SystemError::EINVAL) Err(SystemError::EINVAL)
} else { } else {
let path: &str = path.unwrap(); let path: &str = path.unwrap();
let flags = args[1]; let flags = args[1];
let open_flags: FileMode = FileMode::from_bits_truncate(flags as u32); let open_flags: FileMode = FileMode::from_bits_truncate(flags as u32);
Self::open(path, open_flags) Self::open(path, open_flags)
}; };
@ -427,7 +427,10 @@ impl Syscall {
} }
SYS_CLOSE => { SYS_CLOSE => {
let fd = args[0]; let fd = args[0];
Self::close(fd)
let res = Self::close(fd);
res
} }
SYS_READ => { SYS_READ => {
let fd = args[0] as i32; let fd = args[0] as i32;
@ -545,6 +548,7 @@ impl Syscall {
SYS_GET_DENTS => { SYS_GET_DENTS => {
let fd = args[0] as i32; let fd = args[0] as i32;
let buf_vaddr = args[1]; let buf_vaddr = args[1];
let len = args[2]; let len = args[2];
let virt_addr: VirtAddr = VirtAddr::new(buf_vaddr); let virt_addr: VirtAddr = VirtAddr::new(buf_vaddr);

View File

@ -320,7 +320,7 @@ int shell_cmd_cat(int argc, char **argv)
char *file_path = get_target_filepath(argv[1], &path_len); 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) if (fd <= 0)
{ {
printf("ERROR: Cannot open file: %s, fd=%d\n", file_path, fd); 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"); printf("Mem:\t");
if (argc == 1) // 按照kb显示 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, 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 >> 10, mst.available >> 10); mst.cache_used, mst.available);
} }
else // 按照MB显示 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, 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 >> 20, mst.available >> 20); mst.cache_used >> 10, mst.available >> 10);
} }
done:; done:;

View File

@ -7,21 +7,21 @@ extern "C" {
#endif #endif
void *memset(void *dst, unsigned char C, uint64_t size); void *memset(void *dst, unsigned char C, uint64_t size);
/** /**
* @brief * @brief
* *
* @param s * @param s
* @return size_t * @return size_t
*/ */
size_t strlen(const char *s); size_t strlen(const char *s);
/* /*
FirstPart and SecondPart FirstPart and SecondPart
FirstPart = SecondPart => 0 FirstPart = SecondPart => 0
FirstPart > SecondPart => 1 FirstPart > SecondPart => 1
FirstPart < SecondPart => -1 FirstPart < SecondPart => -1
*/ */
int strcmp(const char *FirstPart, const char *SecondPart); int strcmp(const char *FirstPart, const char *SecondPart);
/** /**
@ -32,7 +32,7 @@ int strcmp(const char *FirstPart, const char *SecondPart);
* @param Count * @param Count
* @return char* * @return char*
*/ */
char *strncpy(char *dst, const char *src, size_t Count); char *strncpy(char *dst, const char *src, size_t count);
/** /**
* @brief * @brief
@ -82,6 +82,72 @@ static void *memcpy(void *dst, const void *src, long Num)
return dst; 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) #if defined(__cplusplus)
} /* extern "C" */ } /* extern "C" */
#endif #endif

View File

@ -2,7 +2,7 @@
#include <sys/types.h> #include <sys/types.h>
/** /**
* @brief * @brief kB
* *
*/ */
struct mstat_t struct mstat_t

View File

@ -1,4 +1,5 @@
#include <string.h> #include <string.h>
#include <stddef.h>
size_t strlen(const char *s) size_t strlen(const char *s)
{ {
@ -57,15 +58,7 @@ void *memset(void *dst, unsigned char C, uint64_t size)
return dst; return dst;
} }
/** char *strncpy(char *dst, const char *src, size_t count)
* @brief
*
* @param dst
* @param src
* @param Count
* @return char*
*/
char *strncpy(char *dst, const char *src, size_t Count)
{ {
__asm__ __volatile__("cld \n\t" __asm__ __volatile__("cld \n\t"
"1: \n\t" "1: \n\t"
@ -79,31 +72,17 @@ char *strncpy(char *dst, const char *src, size_t Count)
"stosb \n\t" "stosb \n\t"
"2: \n\t" "2: \n\t"
: :
: "S"(src), "D"(dst), "c"(Count) : "S"(src), "D"(dst), "c"(count)
: "ax", "memory"); : "ax", "memory");
return dst; return dst;
} }
/**
* @brief src接到dest末尾
*
* @param dest
* @param src
* @return char*
*/
char *strcat(char *dest, const char *src) char *strcat(char *dest, const char *src)
{ {
strcpy(dest + strlen(dest), src); strcpy(dest + strlen(dest), src);
return dest; return dest;
} }
/**
* @brief
*
* @param dst
* @param src
* @return char*
*/
char *strcpy(char *dst, const char *src) char *strcpy(char *dst, const char *src)
{ {
while (*src) while (*src)
@ -113,4 +92,140 @@ char *strcpy(char *dst, const char *src)
*dst = 0; *dst = 0;
return dst; 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;
} }

View File

@ -1,5 +1,10 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <libsystem/syscall.h> #include <libsystem/syscall.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
int mkdir(const char *path, mode_t mode) 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) 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;
} }

View File

@ -26,7 +26,8 @@
#define SYS_CLOCK 19 // 获取当前cpu时间 #define SYS_CLOCK 19 // 获取当前cpu时间
#define SYS_PIPE 20 #define SYS_PIPE 20
#define SYS_MSTAT 21 // 获取系统的内存状态信息 // 现在已经废弃
// #define SYS_MSTAT 21 // 获取系统的内存状态信息
#define SYS_UNLINK_AT 22 // 删除文件夹/删除文件链接 #define SYS_UNLINK_AT 22 // 删除文件夹/删除文件链接
#define SYS_KILL 23 // kill一个进程(向这个进程发出信号) #define SYS_KILL 23 // kill一个进程(向这个进程发出信号)
#define SYS_SIGACTION 24 // 设置进程的信号处理动作 #define SYS_SIGACTION 24 // 设置进程的信号处理动作