mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-19 00:46:31 +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:
@ -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() }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 挂载
|
||||
|
@ -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")
|
||||
|
@ -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(());
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 创建文件夹
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
Reference in New Issue
Block a user