实现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
16 changed files with 401 additions and 89 deletions

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::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() }
}
}

View File

@ -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> = DevFS::new();
// devfs 挂载

View File

@ -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<u8> 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::<u8>()) as i64);
}
/// status文件读取函数
fn read_status(
/// 打开 meminfo 文件
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,
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::<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;
}
@ -293,26 +341,26 @@ impl ProcFS {
/// @usage 在进程中调用并创建进程对应文件
pub fn register_pid(&self, pid: Pid) -> Result<(), SystemError> {
// 获取当前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(),
FileType::Dir,
ModeType::from_bits_truncate(0o777),
ModeType::from_bits_truncate(0o555),
)?;
// 创建相关文件
// status文件
let binding: Arc<dyn IndexNode> = _pf.create(
let binding: Arc<dyn IndexNode> = 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::<LockedProcFSInode>()
.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> = ProcFS::new();
// sysfs 挂载
// procfs 挂载
let _t = ROOT_INODE()
.find("proc")
.expect("Cannot find /proc")

View File

@ -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(());
}

View File

@ -63,11 +63,11 @@ impl MountFS {
let weak: Weak<MountFS> = 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<MountFSInode> = 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;

View File

@ -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 创建文件夹

View File

@ -65,6 +65,8 @@ impl<A> PageList<A> {
pub struct BuddyAllocator<A> {
// 存放每个阶的空闲“链表”的头部地址
free_area: [PhysAddr; (MAX_ORDER - MIN_ORDER) as usize],
/// 总页数
total: PageFrameCount,
phantom: PhantomData<A>,
}
@ -227,9 +229,9 @@ impl<A: MemoryManagementArch> BuddyAllocator<A> {
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<A: MemoryManagementArch> BuddyAllocator<A> {
}
return None;
};
let result: Option<PhysAddr> = alloc_in_specific_order(order as u8);
// kdebug!("result={:?}", result);
if result.is_some() {
@ -662,7 +663,19 @@ impl<A: MemoryManagementArch> FrameAllocator for BuddyAllocator<A> {
}
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 获取空闲的页帧数量
pub fn free(&self) -> PageFrameCount {
return PageFrameCount(self.total.0 - self.used.0);
return self.total - self.used;
}
// @brief 获取总的页帧数量
pub fn total(&self) -> PageFrameCount {

View File

@ -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);