mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 18:26:48 +00:00
实现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:
parent
afc95d5c25
commit
34e6d6c80f
@ -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)`` : 在字符串中查找最后一次出现的字符
|
@ -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() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 挂载
|
||||||
|
@ -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")
|
||||||
|
@ -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(());
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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 创建文件夹
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
|
@ -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:;
|
||||||
|
@ -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
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 系统内存信息结构体(单位:字节)
|
* @brief 系统内存信息结构体(单位:kB)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct mstat_t
|
struct mstat_t
|
||||||
|
@ -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;
|
||||||
}
|
}
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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 // 设置进程的信号处理动作
|
||||||
|
Loading…
x
Reference in New Issue
Block a user