mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-20 01:46:31 +00:00
增加内存分配日志监视器 (#424)
* 完成内存日志监视,并输出日志到文件 * 修复进程退出后,procfs查看进程status文件会崩溃的问题 * 修复signal唤醒进程的判断条件问题
This commit is contained in:
@ -11,7 +11,7 @@ use alloc::{
|
||||
vec::Vec,
|
||||
};
|
||||
|
||||
use memoffset::offset_of;
|
||||
use kdepends::memoffset::offset_of;
|
||||
use x86::{controlregs::Cr4, segmentation::SegmentSelector};
|
||||
|
||||
use crate::{
|
||||
|
@ -4,7 +4,7 @@ use core::{
|
||||
sync::atomic::{compiler_fence, AtomicBool, Ordering},
|
||||
};
|
||||
|
||||
use memoffset::offset_of;
|
||||
use kdepends::memoffset::offset_of;
|
||||
|
||||
use crate::{
|
||||
arch::process::table::TSSManager, exception::InterruptArch,
|
||||
|
78
kernel/src/debug/klog/mm.rs
Normal file
78
kernel/src/debug/klog/mm.rs
Normal file
@ -0,0 +1,78 @@
|
||||
extern crate klog_types;
|
||||
|
||||
use core::intrinsics::unlikely;
|
||||
|
||||
use klog_types::{AllocatorLog, AllocatorLogType, LogSource, MMLogChannel};
|
||||
|
||||
use crate::{
|
||||
arch::CurrentTimeArch,
|
||||
process::{Pid, ProcessManager},
|
||||
time::TimeArch,
|
||||
};
|
||||
|
||||
/// 全局的内存分配器日志通道
|
||||
///
|
||||
/// 标记为`no_mangle`是为了让调试器能够找到这个变量
|
||||
#[no_mangle]
|
||||
static __MM_ALLOCATOR_LOG_CHANNEL: MMLogChannel<{ MMDebugLogManager::MAX_ALLOC_LOG_NUM }> =
|
||||
MMLogChannel::new(MMDebugLogManager::MAX_ALLOC_LOG_NUM);
|
||||
|
||||
/// 全局的内存分配器日志id分配器
|
||||
///
|
||||
/// id从1开始, 因为0是无效的id
|
||||
static __MM_DEBUG_LOG_IDA: ida::IdAllocator = ida::IdAllocator::new(1, usize::MAX);
|
||||
|
||||
/// 记录内存分配器的日志
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `log_type`:日志类型
|
||||
/// - `source`:日志来源
|
||||
pub fn mm_debug_log(log_type: AllocatorLogType, source: LogSource) {
|
||||
let pid = if unlikely(!ProcessManager::initialized()) {
|
||||
Some(Pid::new(0))
|
||||
} else {
|
||||
Some(ProcessManager::current_pcb().pid())
|
||||
};
|
||||
MMDebugLogManager::log(log_type, source, pid);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct MMDebugLogManager;
|
||||
|
||||
impl MMDebugLogManager {
|
||||
/// 最大的内存分配器日志数量
|
||||
pub const MAX_ALLOC_LOG_NUM: usize = 100000;
|
||||
|
||||
/// 记录内存分配器的日志
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `log_type`:日志类型
|
||||
/// - `source`:日志来源
|
||||
/// - `pid`:日志来源的pid
|
||||
pub fn log(log_type: AllocatorLogType, source: LogSource, pid: Option<Pid>) {
|
||||
let id = __MM_DEBUG_LOG_IDA.alloc().unwrap();
|
||||
let log = AllocatorLog::new(
|
||||
id as u64,
|
||||
log_type,
|
||||
source,
|
||||
pid.map(|p| p.data()),
|
||||
CurrentTimeArch::get_cycles() as u64,
|
||||
);
|
||||
|
||||
let mut log = log;
|
||||
loop {
|
||||
let r = __MM_ALLOCATOR_LOG_CHANNEL.buf.push(log);
|
||||
if let Err(r) = r {
|
||||
// 如果日志通道满了,就把最早的日志丢弃
|
||||
if __MM_ALLOCATOR_LOG_CHANNEL.buf.remaining() == 0 {
|
||||
__MM_ALLOCATOR_LOG_CHANNEL.buf.pop();
|
||||
}
|
||||
log = r.into_inner();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1
kernel/src/debug/klog/mod.rs
Normal file
1
kernel/src/debug/klog/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod mm;
|
1
kernel/src/debug/mod.rs
Normal file
1
kernel/src/debug/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod klog;
|
@ -26,7 +26,7 @@ use crate::{
|
||||
use super::{super::device::DeviceState, platform_bus, platform_bus_device, CompatibleTable};
|
||||
|
||||
/// 平台设备id分配器
|
||||
static PLATFORM_DEVID_IDA: IdAllocator = IdAllocator::new(i32::MAX as usize);
|
||||
static PLATFORM_DEVID_IDA: IdAllocator = IdAllocator::new(0, i32::MAX as usize);
|
||||
|
||||
#[inline(always)]
|
||||
pub fn platform_device_manager() -> &'static PlatformDeviceManager {
|
||||
|
@ -2,7 +2,7 @@ use core::intrinsics::unlikely;
|
||||
|
||||
use alloc::string::String;
|
||||
|
||||
use thingbuf::mpsc::{
|
||||
use kdepends::thingbuf::mpsc::{
|
||||
self,
|
||||
errors::{TryRecvError, TrySendError},
|
||||
};
|
||||
|
@ -179,23 +179,24 @@ impl ProcFSInode {
|
||||
);
|
||||
pdata.append(&mut format!("\nvrtime:\t{}", vrtime).as_bytes().to_owned());
|
||||
|
||||
let binding = pcb.basic().user_vm().unwrap();
|
||||
let address_space_guard = binding.read();
|
||||
// todo: 当前进程运行过程中占用内存的峰值
|
||||
let hiwater_vm: u64 = 0;
|
||||
// 进程代码段的大小
|
||||
let text = (address_space_guard.end_code - address_space_guard.start_code) / 1024;
|
||||
// 进程数据段的大小
|
||||
let data = (address_space_guard.end_data - address_space_guard.start_data) / 1024;
|
||||
drop(address_space_guard);
|
||||
if let Some(user_vm) = pcb.basic().user_vm() {
|
||||
let address_space_guard = user_vm.read();
|
||||
// todo: 当前进程运行过程中占用内存的峰值
|
||||
let hiwater_vm: u64 = 0;
|
||||
// 进程代码段的大小
|
||||
let text = (address_space_guard.end_code - address_space_guard.start_code) / 1024;
|
||||
// 进程数据段的大小
|
||||
let data = (address_space_guard.end_data - address_space_guard.start_data) / 1024;
|
||||
drop(address_space_guard);
|
||||
pdata.append(
|
||||
&mut format!("\nVmPeak:\t{} kB", hiwater_vm)
|
||||
.as_bytes()
|
||||
.to_owned(),
|
||||
);
|
||||
pdata.append(&mut format!("\nVmData:\t{} kB", data).as_bytes().to_owned());
|
||||
pdata.append(&mut format!("\nVmExe:\t{} kB", text).as_bytes().to_owned());
|
||||
}
|
||||
|
||||
pdata.append(
|
||||
&mut format!("\nVmPeak:\t{} kB", hiwater_vm)
|
||||
.as_bytes()
|
||||
.to_owned(),
|
||||
);
|
||||
pdata.append(&mut format!("\nVmData:\t{} kB", data).as_bytes().to_owned());
|
||||
pdata.append(&mut format!("\nVmExe:\t{} kB", text).as_bytes().to_owned());
|
||||
pdata.append(
|
||||
&mut format!("\nflags: {:?}\n", pcb.flags().clone())
|
||||
.as_bytes()
|
||||
|
@ -50,10 +50,13 @@ impl Signal {
|
||||
kwarn!("No such process.");
|
||||
return retval;
|
||||
}
|
||||
|
||||
let pcb = pcb.unwrap();
|
||||
// println!("Target pcb = {:?}", pcb.as_ref().unwrap());
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
// 发送信号
|
||||
retval = self.send_signal(info, pcb.unwrap(), PidType::PID);
|
||||
retval = self.send_signal(info, pcb.clone(), PidType::PID);
|
||||
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
return retval;
|
||||
}
|
||||
@ -282,8 +285,33 @@ fn signal_wake_up(pcb: Arc<ProcessControlBlock>, _guard: SpinLockGuard<SignalStr
|
||||
// 如果不是 fatal 的就只唤醒 stop 的进程来响应
|
||||
// kdebug!("signal_wake_up");
|
||||
// 如果目标进程已经在运行,则发起一个ipi,使得它陷入内核
|
||||
let r = ProcessManager::wakeup_stop(&pcb);
|
||||
if r.is_ok() {
|
||||
let state = pcb.sched_info().state();
|
||||
let mut wakeup_ok = true;
|
||||
if state.is_blocked_interruptable() {
|
||||
ProcessManager::wakeup(&pcb).unwrap_or_else(|e| {
|
||||
wakeup_ok = false;
|
||||
kwarn!(
|
||||
"Current pid: {:?}, signal_wake_up target {:?} error: {:?}",
|
||||
ProcessManager::current_pcb().pid(),
|
||||
pcb.pid(),
|
||||
e
|
||||
);
|
||||
});
|
||||
} else if state.is_stopped() {
|
||||
ProcessManager::wakeup_stop(&pcb).unwrap_or_else(|e| {
|
||||
wakeup_ok = false;
|
||||
kwarn!(
|
||||
"Current pid: {:?}, signal_wake_up target {:?} error: {:?}",
|
||||
ProcessManager::current_pcb().pid(),
|
||||
pcb.pid(),
|
||||
e
|
||||
);
|
||||
});
|
||||
} else {
|
||||
wakeup_ok = false;
|
||||
}
|
||||
|
||||
if wakeup_ok {
|
||||
ProcessManager::kick(&pcb);
|
||||
} else {
|
||||
if fatal {
|
||||
|
@ -39,6 +39,7 @@ mod arch;
|
||||
mod libs;
|
||||
#[macro_use]
|
||||
mod include;
|
||||
mod debug;
|
||||
mod driver; // 如果driver依赖了libs,应该在libs后面导出
|
||||
mod exception;
|
||||
mod filesystem;
|
||||
@ -60,17 +61,17 @@ extern crate bitflags;
|
||||
extern crate elf;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
extern crate memoffset;
|
||||
extern crate num;
|
||||
#[macro_use]
|
||||
extern crate num_derive;
|
||||
extern crate smoltcp;
|
||||
extern crate thingbuf;
|
||||
#[macro_use]
|
||||
extern crate intertrait;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
extern crate x86;
|
||||
|
||||
extern crate klog_types;
|
||||
|
||||
use crate::mm::allocator::kernel_allocator::KernelAllocator;
|
||||
|
||||
use crate::process::ProcessManager;
|
||||
|
@ -16,9 +16,9 @@ pub struct IdAllocator {
|
||||
|
||||
impl IdAllocator {
|
||||
/// 创建一个新的id分配器
|
||||
pub const fn new(max_id: usize) -> Self {
|
||||
pub const fn new(initial_id: usize, max_id: usize) -> Self {
|
||||
Self {
|
||||
current_id: AtomicUsize::new(0),
|
||||
current_id: AtomicUsize::new(initial_id),
|
||||
max_id,
|
||||
dead: AtomicBool::new(false),
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
use klog_types::AllocLogItem;
|
||||
|
||||
use crate::{
|
||||
arch::mm::LockedFrameAllocator,
|
||||
debug::klog::mm::mm_debug_log,
|
||||
libs::align::page_align_up,
|
||||
mm::{MMArch, MemoryManagementArch, VirtAddr},
|
||||
};
|
||||
@ -81,15 +84,46 @@ impl LocalAlloc for KernelAllocator {
|
||||
/// 为内核slab分配器实现GlobalAlloc特性
|
||||
unsafe impl GlobalAlloc for KernelAllocator {
|
||||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||
return self.local_alloc(layout);
|
||||
let r = self.local_alloc(layout);
|
||||
mm_debug_log(
|
||||
klog_types::AllocatorLogType::Alloc(AllocLogItem::new(
|
||||
layout.clone(),
|
||||
Some(r as usize),
|
||||
None,
|
||||
)),
|
||||
klog_types::LogSource::Buddy,
|
||||
);
|
||||
|
||||
return r;
|
||||
|
||||
// self.local_alloc_zeroed(layout, 0)
|
||||
}
|
||||
|
||||
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
|
||||
self.local_alloc_zeroed(layout)
|
||||
let r = self.local_alloc_zeroed(layout);
|
||||
|
||||
mm_debug_log(
|
||||
klog_types::AllocatorLogType::AllocZeroed(AllocLogItem::new(
|
||||
layout.clone(),
|
||||
Some(r as usize),
|
||||
None,
|
||||
)),
|
||||
klog_types::LogSource::Buddy,
|
||||
);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
||||
mm_debug_log(
|
||||
klog_types::AllocatorLogType::Free(AllocLogItem::new(
|
||||
layout.clone(),
|
||||
Some(ptr as usize),
|
||||
None,
|
||||
)),
|
||||
klog_types::LogSource::Buddy,
|
||||
);
|
||||
|
||||
self.local_dealloc(ptr, layout);
|
||||
}
|
||||
}
|
||||
|
@ -121,6 +121,11 @@ impl ProcessManager {
|
||||
kinfo!("Process Manager initialized.");
|
||||
}
|
||||
|
||||
/// 判断进程管理器是否已经初始化完成
|
||||
pub fn initialized() -> bool {
|
||||
unsafe { __PROCESS_MANAGEMENT_INIT_DONE }
|
||||
}
|
||||
|
||||
/// 获取当前进程的pcb
|
||||
pub fn current_pcb() -> Arc<ProcessControlBlock> {
|
||||
if unlikely(unsafe { !__PROCESS_MANAGEMENT_INIT_DONE }) {
|
||||
@ -461,6 +466,11 @@ impl ProcessState {
|
||||
return matches!(self, ProcessState::Blocked(_));
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn is_blocked_interruptable(&self) -> bool {
|
||||
return matches!(self, ProcessState::Blocked(true));
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn is_exited(&self) -> bool {
|
||||
return matches!(self, ProcessState::Exited(_));
|
||||
|
Reference in New Issue
Block a user