mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-18 12:16:31 +00:00
实现内核日志系统 (#489)
* 实现写日志和读取日志,并且能够在用户态下执行dmesg命令查看日志 * 通过klogctl实现dmesg * 改用ConstGenericRingBuffer作内核缓冲区 * 更改缓冲区容量 * 将能够输出到控制台的日志级别改为日志级别枚举类,使用SpinLock控制KMSG,使用枚举类定义SYSLOG_ACTION,将do_syslog系统调用接口放在syscall.rs * fix warning * 完善do_syslog注释 * 将KMSG接入kinfo、kdebug等 * fix warning * 修复显示的秒数不正确,·以及无法通过CI的问题
This commit is contained in:
@ -7,6 +7,7 @@ description = "需要导出的依赖项(为保持内核依赖版本与调试
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
ringbuffer = "0.15.0"
|
||||
memoffset = "0.9.0"
|
||||
crc = { path = "../crc" }
|
||||
|
||||
|
@ -6,4 +6,6 @@ pub extern crate thingbuf;
|
||||
|
||||
pub extern crate memoffset;
|
||||
|
||||
pub extern crate ringbuffer;
|
||||
|
||||
pub extern crate crc;
|
||||
|
@ -491,7 +491,7 @@ impl SignalArch for X86_64SignalArch {
|
||||
"Error occurred when handling signal: {}, pid={:?}, errcode={:?}",
|
||||
sig_number as i32,
|
||||
ProcessManager::current_pcb().pid(),
|
||||
res.unwrap_err()
|
||||
res.as_ref().unwrap_err()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ use x86::time::rdtsc;
|
||||
use x86_64::registers::model_specific::EferFlags;
|
||||
|
||||
use crate::driver::tty::serial::serial8250::send_to_default_serial8250_port;
|
||||
use crate::filesystem::procfs::kmsg::kmsg_init;
|
||||
use crate::include::bindings::bindings::{
|
||||
multiboot2_get_load_base, multiboot2_get_memory, multiboot2_iter, multiboot_mmap_entry_t,
|
||||
multiboot_tag_load_base_addr_t,
|
||||
@ -419,6 +420,8 @@ pub fn mm_init() {
|
||||
unsafe { allocator_init() };
|
||||
// enable mmio
|
||||
mmio_init();
|
||||
// enable KMSG
|
||||
kmsg_init();
|
||||
}
|
||||
|
||||
unsafe fn allocator_init() {
|
||||
|
@ -594,8 +594,12 @@ pub extern "C" fn rs_e1000e_init() {
|
||||
|
||||
pub fn e1000e_init() -> () {
|
||||
match e1000e_probe() {
|
||||
Ok(_code) => kinfo!("Successfully init e1000e device!"),
|
||||
Err(_error) => kinfo!("Error occurred!"),
|
||||
Ok(_code) => {
|
||||
kinfo!("Successfully init e1000e device!");
|
||||
}
|
||||
Err(_error) => {
|
||||
kinfo!("Error occurred!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1196,7 +1196,7 @@ impl Drop for FATFileSystem {
|
||||
if r.is_err() {
|
||||
kerror!(
|
||||
"Umount FAT filesystem failed: errno={:?}, FS detail:{self:?}",
|
||||
r.unwrap_err()
|
||||
r.as_ref().unwrap_err()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
151
kernel/src/filesystem/procfs/kmsg.rs
Normal file
151
kernel/src/filesystem/procfs/kmsg.rs
Normal file
@ -0,0 +1,151 @@
|
||||
use super::log::{LogLevel, LogMessage};
|
||||
|
||||
use crate::libs::spinlock::SpinLock;
|
||||
|
||||
use alloc::{borrow::ToOwned, string::ToString, vec::Vec};
|
||||
|
||||
use kdepends::ringbuffer::{AllocRingBuffer, RingBuffer};
|
||||
|
||||
use system_error::SystemError;
|
||||
|
||||
/// 缓冲区容量
|
||||
const KMSG_BUFFER_CAPACITY: usize = 1024;
|
||||
|
||||
/// 全局环形缓冲区
|
||||
pub static mut KMSG: Option<SpinLock<Kmsg>> = None;
|
||||
|
||||
/// 初始化KMSG
|
||||
pub fn kmsg_init() {
|
||||
let kmsg = SpinLock::new(Kmsg::new());
|
||||
unsafe { KMSG = Some(kmsg) };
|
||||
}
|
||||
|
||||
/// 日志
|
||||
pub struct Kmsg {
|
||||
/// 环形缓冲区
|
||||
buffer: AllocRingBuffer<LogMessage>,
|
||||
/// 缓冲区字节数组
|
||||
data: Vec<u8>,
|
||||
/// 能够输出到控制台的日志级别,当console_loglevel为DEFAULT时,表示可以打印所有级别的日志消息到控制台
|
||||
console_loglevel: LogLevel,
|
||||
/// 判断buffer在上一次转成字节数组之后是否发生变动
|
||||
is_changed: bool,
|
||||
}
|
||||
|
||||
impl Kmsg {
|
||||
pub fn new() -> Self {
|
||||
Kmsg {
|
||||
buffer: AllocRingBuffer::new(KMSG_BUFFER_CAPACITY),
|
||||
data: Vec::new(),
|
||||
console_loglevel: LogLevel::DEFAULT,
|
||||
is_changed: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// 添加日志消息
|
||||
pub fn push(&mut self, msg: LogMessage) {
|
||||
self.buffer.push(msg);
|
||||
self.is_changed = true;
|
||||
}
|
||||
|
||||
/// 读取缓冲区
|
||||
pub fn read(&mut self, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
self.tobytes();
|
||||
|
||||
match self.console_loglevel {
|
||||
LogLevel::DEFAULT => self.read_all(buf),
|
||||
_ => self.read_level(buf),
|
||||
}
|
||||
}
|
||||
|
||||
/// 读取缓冲区所有日志消息
|
||||
fn read_all(&mut self, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
let len = self.data.len().min(buf.len());
|
||||
|
||||
// 拷贝数据
|
||||
let src = &self.data[0..len];
|
||||
buf[0..src.len()].copy_from_slice(src);
|
||||
|
||||
return Ok(src.len());
|
||||
}
|
||||
|
||||
/// 读取缓冲区特定level的日志消息
|
||||
fn read_level(&mut self, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
let mut data_level: Vec<u8> = Vec::new();
|
||||
|
||||
for msg in self.buffer.iter() {
|
||||
if msg.level() == self.console_loglevel {
|
||||
data_level.append(&mut msg.to_string().as_bytes().to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
let len = data_level.len().min(buf.len());
|
||||
|
||||
// 拷贝数据
|
||||
let src = &data_level[0..len];
|
||||
buf[0..src.len()].copy_from_slice(src);
|
||||
|
||||
// 将控制台输出日志level改回默认,否则之后都是打印特定level的日志消息
|
||||
self.console_loglevel = LogLevel::DEFAULT;
|
||||
|
||||
return Ok(data_level.len());
|
||||
}
|
||||
|
||||
/// 读取并清空缓冲区
|
||||
pub fn read_clear(&mut self, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
let r = self.read_all(buf);
|
||||
self.clear()?;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/// 清空缓冲区
|
||||
pub fn clear(&mut self) -> Result<usize, SystemError> {
|
||||
self.buffer.clear();
|
||||
self.data.clear();
|
||||
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
/// 设置输出到控制台的日志级别
|
||||
pub fn set_level(&mut self, log_level: usize) -> Result<usize, SystemError> {
|
||||
let log_level = log_level - 1;
|
||||
|
||||
self.console_loglevel = match log_level {
|
||||
0 => LogLevel::EMERG,
|
||||
1 => LogLevel::ALERT,
|
||||
2 => LogLevel::CRIT,
|
||||
3 => LogLevel::ERR,
|
||||
4 => LogLevel::WARN,
|
||||
5 => LogLevel::NOTICE,
|
||||
6 => LogLevel::INFO,
|
||||
7 => LogLevel::DEBUG,
|
||||
8 => LogLevel::DEFAULT,
|
||||
_ => return Err(SystemError::EINVAL),
|
||||
};
|
||||
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
/// 将环形缓冲区的日志消息转成字节数组以拷入用户buf
|
||||
fn tobytes(&mut self) -> usize {
|
||||
if self.is_changed {
|
||||
self.data.clear();
|
||||
|
||||
if self.console_loglevel == LogLevel::DEFAULT {
|
||||
for msg in self.buffer.iter() {
|
||||
self.data.append(&mut msg.to_string().as_bytes().to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
self.is_changed = false;
|
||||
}
|
||||
|
||||
return self.data.len();
|
||||
}
|
||||
|
||||
// 返回内核缓冲区所占字节数
|
||||
pub fn data_size(&mut self) -> Result<usize, SystemError> {
|
||||
return Ok(self.tobytes());
|
||||
}
|
||||
}
|
107
kernel/src/filesystem/procfs/log.rs
Normal file
107
kernel/src/filesystem/procfs/log.rs
Normal file
@ -0,0 +1,107 @@
|
||||
use core::fmt::{Display, Formatter, Result};
|
||||
|
||||
use alloc::string::String;
|
||||
|
||||
use crate::time::TimeSpec;
|
||||
|
||||
// /// 日志类型
|
||||
// #[derive(Default, Clone, Debug)]
|
||||
// pub enum LogType {
|
||||
// /// 启动信息
|
||||
// Startup,
|
||||
// /// 驱动信息
|
||||
// Driver,
|
||||
// /// 系统信息
|
||||
// System,
|
||||
// /// 硬件信息
|
||||
// Hardware,
|
||||
// /// 内核模块信息
|
||||
// KernelModule,
|
||||
// /// 内核调试信息
|
||||
// KernelDebug,
|
||||
// #[default]
|
||||
// Default,
|
||||
// }
|
||||
|
||||
/// 日志级别
|
||||
#[derive(Default, Clone, PartialEq, Debug)]
|
||||
pub enum LogLevel {
|
||||
EMERG = 0,
|
||||
ALERT = 1,
|
||||
CRIT = 2,
|
||||
ERR = 3,
|
||||
WARN = 4,
|
||||
NOTICE = 5,
|
||||
INFO = 6,
|
||||
DEBUG = 7,
|
||||
#[default]
|
||||
DEFAULT = 8,
|
||||
}
|
||||
|
||||
impl From<usize> for LogLevel {
|
||||
fn from(value: usize) -> Self {
|
||||
match value {
|
||||
0 => LogLevel::EMERG,
|
||||
1 => LogLevel::ALERT,
|
||||
2 => LogLevel::CRIT,
|
||||
3 => LogLevel::ERR,
|
||||
4 => LogLevel::WARN,
|
||||
5 => LogLevel::NOTICE,
|
||||
6 => LogLevel::INFO,
|
||||
7 => LogLevel::DEBUG,
|
||||
_ => LogLevel::DEFAULT,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 日志消息
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct LogMessage {
|
||||
/// 时间戳
|
||||
timestamp: TimeSpec,
|
||||
/// 日志级别
|
||||
level: LogLevel,
|
||||
// /// 日志类型
|
||||
// log_type: LogType,
|
||||
/// 日志消息
|
||||
message: String,
|
||||
}
|
||||
|
||||
impl LogMessage {
|
||||
pub fn new(timestamp: TimeSpec, level: LogLevel, message: String) -> Self {
|
||||
LogMessage {
|
||||
timestamp,
|
||||
level,
|
||||
message,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn level(&self) -> LogLevel {
|
||||
self.level.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for LogMessage {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||
let timestamp = &self.timestamp;
|
||||
let level = match self.level {
|
||||
LogLevel::EMERG => "EMERG",
|
||||
LogLevel::ALERT => "ALERT",
|
||||
LogLevel::CRIT => "CRIT",
|
||||
LogLevel::ERR => "ERR",
|
||||
LogLevel::WARN => "WARNING",
|
||||
LogLevel::NOTICE => "NOTICE",
|
||||
LogLevel::INFO => "INFO",
|
||||
LogLevel::DEBUG => "DEBUG",
|
||||
LogLevel::DEFAULT => "Default",
|
||||
};
|
||||
|
||||
let message = &self.message;
|
||||
|
||||
let res = format!(
|
||||
"<{}>[{}.{}] : {}\n",
|
||||
level, timestamp.tv_sec, timestamp.tv_nsec, message
|
||||
);
|
||||
return write!(f, "{}", res);
|
||||
}
|
||||
}
|
@ -33,6 +33,10 @@ use super::vfs::{
|
||||
FileSystem, FsInfo, IndexNode, InodeId, Metadata,
|
||||
};
|
||||
|
||||
pub mod kmsg;
|
||||
pub mod log;
|
||||
mod syscall;
|
||||
|
||||
/// @brief 进程文件类型
|
||||
/// @usage 用于定义进程文件夹下的各类文件类型
|
||||
#[derive(Debug)]
|
||||
@ -42,6 +46,8 @@ pub enum ProcFileType {
|
||||
ProcStatus = 0,
|
||||
/// meminfo
|
||||
ProcMeminfo = 1,
|
||||
/// kmsg
|
||||
ProcKmsg = 2,
|
||||
//todo: 其他文件类型
|
||||
///默认文件类型
|
||||
Default,
|
||||
@ -52,6 +58,7 @@ impl From<u8> for ProcFileType {
|
||||
match value {
|
||||
0 => ProcFileType::ProcStatus,
|
||||
1 => ProcFileType::ProcMeminfo,
|
||||
2 => ProcFileType::ProcKmsg,
|
||||
_ => ProcFileType::Default,
|
||||
}
|
||||
}
|
||||
@ -336,6 +343,19 @@ impl ProcFS {
|
||||
panic!("create meminfo error");
|
||||
}
|
||||
|
||||
// 创建kmsg文件
|
||||
let binding = inode.create("kmsg", FileType::File, ModeType::from_bits_truncate(0o444));
|
||||
if let Ok(kmsg) = binding {
|
||||
let kmsg_file = kmsg
|
||||
.as_any_ref()
|
||||
.downcast_ref::<LockedProcFSInode>()
|
||||
.unwrap();
|
||||
kmsg_file.0.lock().fdata.pid = Pid::new(1);
|
||||
kmsg_file.0.lock().fdata.ftype = ProcFileType::ProcKmsg;
|
||||
} else {
|
||||
panic!("create ksmg error");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -456,6 +476,7 @@ impl IndexNode for LockedProcFSInode {
|
||||
match inode.fdata.ftype {
|
||||
ProcFileType::ProcStatus => return inode.proc_read(offset, len, buf, private_data),
|
||||
ProcFileType::ProcMeminfo => return inode.proc_read(offset, len, buf, private_data),
|
||||
ProcFileType::ProcKmsg => (),
|
||||
ProcFileType::Default => (),
|
||||
};
|
||||
|
||||
|
77
kernel/src/filesystem/procfs/syscall.rs
Normal file
77
kernel/src/filesystem/procfs/syscall.rs
Normal file
@ -0,0 +1,77 @@
|
||||
use core::usize;
|
||||
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::syscall::Syscall;
|
||||
|
||||
use super::kmsg::KMSG;
|
||||
|
||||
/// 操作内核环形缓冲区
|
||||
enum SyslogAction {
|
||||
/// Close the log. Currently a NOP.
|
||||
SyslogActionClose = 0,
|
||||
/// Open the log. Currently a NOP.
|
||||
SyslogActionOpen = 1,
|
||||
/// Read from the log.
|
||||
SyslogActionRead = 2,
|
||||
/// Read and clear all messages remaining in the ring buffer.
|
||||
SyslogActionReadClear = 4,
|
||||
/// Clear ring buffer.
|
||||
SyslogActionClear = 5,
|
||||
/// Set level of messages printed to console.
|
||||
SyslogActionConsoleLevel = 8,
|
||||
/// Return size of the log buffer.
|
||||
SyslogActionSizeBuffer = 10,
|
||||
/// Invalid SyslogAction
|
||||
SyslogActionInval,
|
||||
}
|
||||
|
||||
impl From<usize> for SyslogAction {
|
||||
fn from(value: usize) -> Self {
|
||||
match value {
|
||||
0 => SyslogAction::SyslogActionClose,
|
||||
1 => SyslogAction::SyslogActionOpen,
|
||||
2 => SyslogAction::SyslogActionRead,
|
||||
4 => SyslogAction::SyslogActionReadClear,
|
||||
5 => SyslogAction::SyslogActionClear,
|
||||
8 => SyslogAction::SyslogActionConsoleLevel,
|
||||
10 => SyslogAction::SyslogActionSizeBuffer,
|
||||
_ => SyslogAction::SyslogActionInval,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Syscall {
|
||||
/// # 操作内核环形缓冲区
|
||||
///
|
||||
/// ## 参数
|
||||
/// - syslog_action_type: 操作码
|
||||
/// - buf:用户缓冲区
|
||||
/// - len: 需要从内核环形缓冲区读取的字节数。如果操作码为8,即SyslogActionConsoleLevel,则len为待设置的日志级别
|
||||
///
|
||||
/// ## 返回值
|
||||
/// - 成功,Ok(usize)
|
||||
/// - 失败,Err(SystemError) 操作失败,返回posix错误码
|
||||
///
|
||||
|
||||
pub fn do_syslog(
|
||||
syslog_action_type: usize,
|
||||
buf: &mut [u8],
|
||||
len: usize,
|
||||
) -> Result<usize, SystemError> {
|
||||
let syslog_action = SyslogAction::from(syslog_action_type);
|
||||
|
||||
let mut kmsg_guard = unsafe { KMSG.as_ref().unwrap().lock_irqsave() };
|
||||
|
||||
match syslog_action {
|
||||
SyslogAction::SyslogActionClose => Ok(0),
|
||||
SyslogAction::SyslogActionOpen => Ok(0),
|
||||
SyslogAction::SyslogActionRead => kmsg_guard.read(buf),
|
||||
SyslogAction::SyslogActionReadClear => kmsg_guard.read_clear(buf),
|
||||
SyslogAction::SyslogActionClear => kmsg_guard.clear(),
|
||||
SyslogAction::SyslogActionSizeBuffer => kmsg_guard.data_size(),
|
||||
SyslogAction::SyslogActionConsoleLevel => kmsg_guard.set_level(len),
|
||||
SyslogAction::SyslogActionInval => return Err(SystemError::EINVAL),
|
||||
}
|
||||
}
|
||||
}
|
@ -462,7 +462,7 @@ impl Drop for File {
|
||||
"pid: {:?} failed to close file: {:?}, errno={:?}",
|
||||
ProcessManager::current_pcb().pid(),
|
||||
self,
|
||||
r.unwrap_err()
|
||||
r.as_ref().unwrap_err()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,17 @@
|
||||
use core::fmt::{self, Write};
|
||||
|
||||
use alloc::string::ToString;
|
||||
|
||||
use super::lib_ui::textui::{textui_putstr, FontColor};
|
||||
|
||||
use crate::{
|
||||
filesystem::procfs::{
|
||||
kmsg::KMSG,
|
||||
log::{LogLevel, LogMessage},
|
||||
},
|
||||
time::TimeSpec,
|
||||
};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! print {
|
||||
($($arg:tt)*) => ($crate::libs::printk::__printk(format_args!($($arg)*)));
|
||||
@ -30,14 +40,15 @@ macro_rules! printk_color {
|
||||
#[macro_export]
|
||||
macro_rules! kdebug {
|
||||
($($arg:tt)*) => {
|
||||
$crate::libs::printk::Logger.log(7,format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
|
||||
$crate::libs::printk::PrintkWriter.__write_fmt(format_args!("[ DEBUG ] ({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! kinfo {
|
||||
($($arg:tt)*) => {
|
||||
$crate::libs::printk::Logger.log(6,format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
|
||||
$crate::libs::printk::PrintkWriter.__write_fmt(format_args!("[ INFO ] ({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)))
|
||||
}
|
||||
}
|
||||
@ -45,6 +56,7 @@ macro_rules! kinfo {
|
||||
#[macro_export]
|
||||
macro_rules! kwarn {
|
||||
($($arg:tt)*) => {
|
||||
$crate::libs::printk::Logger.log(4,format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
|
||||
$crate::libs::printk::PrintkWriter.__write_string_color($crate::libs::lib_ui::textui::FontColor::YELLOW, $crate::libs::lib_ui::textui::FontColor::BLACK, "[ WARN ] ");
|
||||
$crate::libs::printk::PrintkWriter.__write_fmt(format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
|
||||
}
|
||||
@ -53,6 +65,7 @@ macro_rules! kwarn {
|
||||
#[macro_export]
|
||||
macro_rules! kerror {
|
||||
($($arg:tt)*) => {
|
||||
$crate::libs::printk::Logger.log(3,format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
|
||||
$crate::libs::printk::PrintkWriter.__write_string_color($crate::libs::lib_ui::textui::FontColor::RED, $crate::libs::lib_ui::textui::FontColor::BLACK, "[ ERROR ] ");
|
||||
$crate::libs::printk::PrintkWriter.__write_fmt(format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
|
||||
}
|
||||
@ -61,6 +74,7 @@ macro_rules! kerror {
|
||||
#[macro_export]
|
||||
macro_rules! kBUG {
|
||||
($($arg:tt)*) => {
|
||||
$crate::libs::printk::Logger.log(1,format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
|
||||
$crate::libs::printk::PrintkWriter.__write_string_color($crate::libs::lib_ui::textui::FontColor::RED, $crate::libs::lib_ui::textui::FontColor::BLACK, "[ BUG ] ");
|
||||
$crate::libs::printk::PrintkWriter.__write_fmt(format_args!("({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)));
|
||||
}
|
||||
@ -97,3 +111,17 @@ impl fmt::Write for PrintkWriter {
|
||||
pub fn __printk(args: fmt::Arguments) {
|
||||
PrintkWriter.write_fmt(args).unwrap();
|
||||
}
|
||||
|
||||
pub struct Logger;
|
||||
|
||||
impl Logger {
|
||||
pub fn log(&self, log_level: usize, message: fmt::Arguments) {
|
||||
if unsafe { !KMSG.is_none() } {
|
||||
let timestamp: TimeSpec = TimeSpec::now();
|
||||
let log_level = LogLevel::from(log_level.clone());
|
||||
let log_message = LogMessage::new(timestamp, log_level, message.to_string());
|
||||
|
||||
unsafe { KMSG.as_ref().unwrap().lock_irqsave().push(log_message) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -853,10 +853,20 @@ impl Syscall {
|
||||
}
|
||||
SYS_GETTID => Self::gettid().map(|tid| tid.into()),
|
||||
SYS_GETUID => Self::getuid().map(|uid| uid.into()),
|
||||
|
||||
SYS_SYSLOG => {
|
||||
kwarn!("SYS_SYSLOG has not yet been implemented");
|
||||
Ok(0)
|
||||
let syslog_action_type = args[0] as usize;
|
||||
let buf_vaddr = args[1];
|
||||
let len = args[2];
|
||||
let from_user = frame.from_user();
|
||||
let mut user_buffer_writer =
|
||||
UserBufferWriter::new(buf_vaddr as *mut u8, len, from_user)?;
|
||||
|
||||
let user_buf = user_buffer_writer.buffer(0)?;
|
||||
let res = Self::do_syslog(syslog_action_type, user_buf, len);
|
||||
res
|
||||
}
|
||||
|
||||
SYS_GETGID => Self::getgid().map(|gid| gid.into()),
|
||||
SYS_SETUID => {
|
||||
kwarn!("SYS_SETUID has not yet been implemented");
|
||||
|
@ -1,8 +1,11 @@
|
||||
use core::{
|
||||
fmt,
|
||||
intrinsics::unlikely,
|
||||
ops::{self, Sub},
|
||||
};
|
||||
|
||||
use crate::arch::CurrentTimeArch;
|
||||
|
||||
use self::timekeep::ktime_get_real_ns;
|
||||
|
||||
pub mod clocksource;
|
||||
@ -55,6 +58,27 @@ impl TimeSpec {
|
||||
tv_nsec: nsec,
|
||||
};
|
||||
}
|
||||
|
||||
/// 获取当前时间
|
||||
pub fn now() -> Self {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
use crate::arch::driver::tsc::TSCManager;
|
||||
let khz = TSCManager::cpu_khz();
|
||||
if unlikely(khz == 0) {
|
||||
return TimeSpec::default();
|
||||
} else {
|
||||
return Self::from(Duration::from_millis(
|
||||
CurrentTimeArch::get_cycles() as u64 / khz,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
{
|
||||
unimplemented!("TimeSpec::now()")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for TimeSpec {
|
||||
|
@ -129,7 +129,7 @@ impl Timer {
|
||||
if unlikely(r.is_err()) {
|
||||
kerror!(
|
||||
"Failed to run timer function: {self:?} {:?}",
|
||||
r.err().unwrap()
|
||||
r.as_ref().err().unwrap()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user