mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 07:06:47 +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:
parent
d46c6d2794
commit
8d72b68da9
6
.github/actions/import-toolchain/action.yml
vendored
6
.github/actions/import-toolchain/action.yml
vendored
@ -15,7 +15,8 @@ runs:
|
|||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/opt
|
~/opt
|
||||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('tools/build_gcc_toolchain.sh') }}-${{ hashFiles('tools/install_musl_gcc.sh') }}
|
~/.bashrc
|
||||||
|
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('tools/build_gcc_toolchain.sh') }}
|
||||||
|
|
||||||
- name: Cache build tools
|
- name: Cache build tools
|
||||||
id: cache-build-tools
|
id: cache-build-tools
|
||||||
@ -28,7 +29,8 @@ runs:
|
|||||||
~/.cargo
|
~/.cargo
|
||||||
~/.rustup
|
~/.rustup
|
||||||
~/.bashrc
|
~/.bashrc
|
||||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.dadk_version }}-${{ hashFiles('.github/workflows/cache-toolchain.yml') }}
|
~/opt
|
||||||
|
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.dadk_version }}-${{ hashFiles('.github/workflows/cache-toolchain.yml') }}-${{ hashFiles('tools/install_musl_gcc.sh') }}
|
||||||
|
|
||||||
- uses: ./.github/actions/install-apt-packages
|
- uses: ./.github/actions/install-apt-packages
|
||||||
|
|
||||||
|
8
.github/workflows/cache-toolchain.yml
vendored
8
.github/workflows/cache-toolchain.yml
vendored
@ -18,14 +18,14 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/opt
|
~/opt
|
||||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('tools/build_gcc_toolchain.sh') }}-${{ hashFiles('tools/install_musl_gcc.sh') }}
|
~/.bashrc
|
||||||
|
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('tools/build_gcc_toolchain.sh') }}
|
||||||
|
|
||||||
- if: ${{ steps.cache-dragonos-gcc.outputs.cache-hit != 'true' }}
|
- if: ${{ steps.cache-dragonos-gcc.outputs.cache-hit != 'true' }}
|
||||||
name: build dragonos-gcc
|
name: build dragonos-gcc
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
run: |
|
run: |
|
||||||
bash tools/build_gcc_toolchain.sh -f
|
bash tools/build_gcc_toolchain.sh -f
|
||||||
bash tools/install_musl_gcc.sh
|
|
||||||
|
|
||||||
- uses: ./.github/actions/install-apt-packages
|
- uses: ./.github/actions/install-apt-packages
|
||||||
|
|
||||||
@ -40,12 +40,14 @@ jobs:
|
|||||||
~/.cargo
|
~/.cargo
|
||||||
~/.rustup
|
~/.rustup
|
||||||
~/.bashrc
|
~/.bashrc
|
||||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.dadk_version }}-${{ hashFiles('.github/workflows/cache-toolchain.yml') }}
|
~/opt
|
||||||
|
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.dadk_version }}-${{ hashFiles('.github/workflows/cache-toolchain.yml') }}-${{ hashFiles('tools/install_musl_gcc.sh') }}
|
||||||
|
|
||||||
- if: ${{ steps.cache-build-tools.outputs.cache-hit != 'true' }}
|
- if: ${{ steps.cache-build-tools.outputs.cache-hit != 'true' }}
|
||||||
name: Install toolchain
|
name: Install toolchain
|
||||||
continue-on-error: false
|
continue-on-error: false
|
||||||
run: |
|
run: |
|
||||||
|
USE_GITHUB=1 bash tools/install_musl_gcc.sh
|
||||||
|
|
||||||
cargo install cargo-binutils
|
cargo install cargo-binutils
|
||||||
rustup toolchain install nightly-x86_64-unknown-linux-gnu
|
rustup toolchain install nightly-x86_64-unknown-linux-gnu
|
||||||
|
15
.github/workflows/makefile.yml
vendored
15
.github/workflows/makefile.yml
vendored
@ -2,7 +2,7 @@ name: Build Check
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ "master", "patch-add-riscv64-github-workflow" ]
|
branches: [ "master" ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ "master" ]
|
branches: [ "master" ]
|
||||||
|
|
||||||
@ -50,6 +50,7 @@ jobs:
|
|||||||
- uses: ./.github/actions/import-toolchain
|
- uses: ./.github/actions/import-toolchain
|
||||||
|
|
||||||
- name: Run kernel static test
|
- name: Run kernel static test
|
||||||
|
shell: bash -ileo pipefail {0}
|
||||||
env:
|
env:
|
||||||
ARCH: ${{ matrix.arch }}
|
ARCH: ${{ matrix.arch }}
|
||||||
run: bash -c "source ~/.cargo/env && cd kernel && make test"
|
run: bash -c "source ~/.cargo/env && cd kernel && make test"
|
||||||
@ -68,7 +69,14 @@ jobs:
|
|||||||
- name: build the DragonOS
|
- name: build the DragonOS
|
||||||
env:
|
env:
|
||||||
ARCH: x86_64
|
ARCH: x86_64
|
||||||
run: bash -c "source ~/.cargo/env && export DragonOS_GCC=$HOME/opt/dragonos-gcc/gcc-x86_64-unknown-none/bin && make -j $(nproc) "
|
shell: bash -ileo pipefail {0}
|
||||||
|
|
||||||
|
run: |
|
||||||
|
source ~/.bashrc
|
||||||
|
source ~/.cargo/env
|
||||||
|
export DragonOS_GCC=$HOME/opt/dragonos-gcc/gcc-x86_64-unknown-none/bin
|
||||||
|
|
||||||
|
make -j $(nproc)
|
||||||
|
|
||||||
|
|
||||||
build-riscv64:
|
build-riscv64:
|
||||||
@ -84,8 +92,9 @@ jobs:
|
|||||||
- uses: ./.github/actions/import-toolchain
|
- uses: ./.github/actions/import-toolchain
|
||||||
|
|
||||||
- name: build the DragonOS
|
- name: build the DragonOS
|
||||||
|
shell: bash -ileo pipefail {0}
|
||||||
env:
|
env:
|
||||||
ARCH: riscv64
|
ARCH: riscv64
|
||||||
|
|
||||||
run: bash -c "source ~/.cargo/env && make kernel -j $(nproc)"
|
run: source ~/.bashrc && source ~/.cargo/env && make kernel -j $(nproc)
|
||||||
|
|
||||||
|
8
.vscode/settings.json
vendored
8
.vscode/settings.json
vendored
@ -172,7 +172,13 @@
|
|||||||
"clocksource.h": "c",
|
"clocksource.h": "c",
|
||||||
"ata.h": "c",
|
"ata.h": "c",
|
||||||
"barrier": "c",
|
"barrier": "c",
|
||||||
"charconv": "c"
|
"charconv": "c",
|
||||||
|
"printf.h": "c",
|
||||||
|
"klog.h": "c",
|
||||||
|
"sqlite3ext.h": "c",
|
||||||
|
"malloc.h": "c",
|
||||||
|
"*.o": "c",
|
||||||
|
"k_log.h": "c"
|
||||||
},
|
},
|
||||||
"C_Cpp.errorSquiggles": "enabled",
|
"C_Cpp.errorSquiggles": "enabled",
|
||||||
"esbonio.sphinx.confDir": "",
|
"esbonio.sphinx.confDir": "",
|
||||||
|
@ -7,6 +7,7 @@ description = "需要导出的依赖项(为保持内核依赖版本与调试
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
ringbuffer = "0.15.0"
|
||||||
memoffset = "0.9.0"
|
memoffset = "0.9.0"
|
||||||
crc = { path = "../crc" }
|
crc = { path = "../crc" }
|
||||||
|
|
||||||
|
@ -6,4 +6,6 @@ pub extern crate thingbuf;
|
|||||||
|
|
||||||
pub extern crate memoffset;
|
pub extern crate memoffset;
|
||||||
|
|
||||||
|
pub extern crate ringbuffer;
|
||||||
|
|
||||||
pub extern crate crc;
|
pub extern crate crc;
|
||||||
|
@ -491,7 +491,7 @@ impl SignalArch for X86_64SignalArch {
|
|||||||
"Error occurred when handling signal: {}, pid={:?}, errcode={:?}",
|
"Error occurred when handling signal: {}, pid={:?}, errcode={:?}",
|
||||||
sig_number as i32,
|
sig_number as i32,
|
||||||
ProcessManager::current_pcb().pid(),
|
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 x86_64::registers::model_specific::EferFlags;
|
||||||
|
|
||||||
use crate::driver::tty::serial::serial8250::send_to_default_serial8250_port;
|
use crate::driver::tty::serial::serial8250::send_to_default_serial8250_port;
|
||||||
|
use crate::filesystem::procfs::kmsg::kmsg_init;
|
||||||
use crate::include::bindings::bindings::{
|
use crate::include::bindings::bindings::{
|
||||||
multiboot2_get_load_base, multiboot2_get_memory, multiboot2_iter, multiboot_mmap_entry_t,
|
multiboot2_get_load_base, multiboot2_get_memory, multiboot2_iter, multiboot_mmap_entry_t,
|
||||||
multiboot_tag_load_base_addr_t,
|
multiboot_tag_load_base_addr_t,
|
||||||
@ -419,6 +420,8 @@ pub fn mm_init() {
|
|||||||
unsafe { allocator_init() };
|
unsafe { allocator_init() };
|
||||||
// enable mmio
|
// enable mmio
|
||||||
mmio_init();
|
mmio_init();
|
||||||
|
// enable KMSG
|
||||||
|
kmsg_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn allocator_init() {
|
unsafe fn allocator_init() {
|
||||||
|
@ -594,8 +594,12 @@ pub extern "C" fn rs_e1000e_init() {
|
|||||||
|
|
||||||
pub fn e1000e_init() -> () {
|
pub fn e1000e_init() -> () {
|
||||||
match e1000e_probe() {
|
match e1000e_probe() {
|
||||||
Ok(_code) => kinfo!("Successfully init e1000e device!"),
|
Ok(_code) => {
|
||||||
Err(_error) => kinfo!("Error occurred!"),
|
kinfo!("Successfully init e1000e device!");
|
||||||
|
}
|
||||||
|
Err(_error) => {
|
||||||
|
kinfo!("Error occurred!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1196,7 +1196,7 @@ impl Drop for FATFileSystem {
|
|||||||
if r.is_err() {
|
if r.is_err() {
|
||||||
kerror!(
|
kerror!(
|
||||||
"Umount FAT filesystem failed: errno={:?}, FS detail:{self:?}",
|
"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,
|
FileSystem, FsInfo, IndexNode, InodeId, Metadata,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub mod kmsg;
|
||||||
|
pub mod log;
|
||||||
|
mod syscall;
|
||||||
|
|
||||||
/// @brief 进程文件类型
|
/// @brief 进程文件类型
|
||||||
/// @usage 用于定义进程文件夹下的各类文件类型
|
/// @usage 用于定义进程文件夹下的各类文件类型
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -42,6 +46,8 @@ pub enum ProcFileType {
|
|||||||
ProcStatus = 0,
|
ProcStatus = 0,
|
||||||
/// meminfo
|
/// meminfo
|
||||||
ProcMeminfo = 1,
|
ProcMeminfo = 1,
|
||||||
|
/// kmsg
|
||||||
|
ProcKmsg = 2,
|
||||||
//todo: 其他文件类型
|
//todo: 其他文件类型
|
||||||
///默认文件类型
|
///默认文件类型
|
||||||
Default,
|
Default,
|
||||||
@ -52,6 +58,7 @@ impl From<u8> for ProcFileType {
|
|||||||
match value {
|
match value {
|
||||||
0 => ProcFileType::ProcStatus,
|
0 => ProcFileType::ProcStatus,
|
||||||
1 => ProcFileType::ProcMeminfo,
|
1 => ProcFileType::ProcMeminfo,
|
||||||
|
2 => ProcFileType::ProcKmsg,
|
||||||
_ => ProcFileType::Default,
|
_ => ProcFileType::Default,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -336,6 +343,19 @@ impl ProcFS {
|
|||||||
panic!("create meminfo error");
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -456,6 +476,7 @@ impl IndexNode for LockedProcFSInode {
|
|||||||
match inode.fdata.ftype {
|
match inode.fdata.ftype {
|
||||||
ProcFileType::ProcStatus => return inode.proc_read(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::ProcMeminfo => return inode.proc_read(offset, len, buf, private_data),
|
||||||
|
ProcFileType::ProcKmsg => (),
|
||||||
ProcFileType::Default => (),
|
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={:?}",
|
"pid: {:?} failed to close file: {:?}, errno={:?}",
|
||||||
ProcessManager::current_pcb().pid(),
|
ProcessManager::current_pcb().pid(),
|
||||||
self,
|
self,
|
||||||
r.unwrap_err()
|
r.as_ref().unwrap_err()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,17 @@
|
|||||||
use core::fmt::{self, Write};
|
use core::fmt::{self, Write};
|
||||||
|
|
||||||
|
use alloc::string::ToString;
|
||||||
|
|
||||||
use super::lib_ui::textui::{textui_putstr, FontColor};
|
use super::lib_ui::textui::{textui_putstr, FontColor};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
filesystem::procfs::{
|
||||||
|
kmsg::KMSG,
|
||||||
|
log::{LogLevel, LogMessage},
|
||||||
|
},
|
||||||
|
time::TimeSpec,
|
||||||
|
};
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! print {
|
macro_rules! print {
|
||||||
($($arg:tt)*) => ($crate::libs::printk::__printk(format_args!($($arg)*)));
|
($($arg:tt)*) => ($crate::libs::printk::__printk(format_args!($($arg)*)));
|
||||||
@ -30,14 +40,15 @@ macro_rules! printk_color {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! kdebug {
|
macro_rules! kdebug {
|
||||||
($($arg:tt)*) => {
|
($($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)*)))
|
$crate::libs::printk::PrintkWriter.__write_fmt(format_args!("[ DEBUG ] ({}:{})\t {}\n", file!(), line!(),format_args!($($arg)*)))
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! kinfo {
|
macro_rules! kinfo {
|
||||||
($($arg:tt)*) => {
|
($($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)*)))
|
$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_export]
|
||||||
macro_rules! kwarn {
|
macro_rules! kwarn {
|
||||||
($($arg:tt)*) => {
|
($($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_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)*)));
|
$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_export]
|
||||||
macro_rules! kerror {
|
macro_rules! kerror {
|
||||||
($($arg:tt)*) => {
|
($($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_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)*)));
|
$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_export]
|
||||||
macro_rules! kBUG {
|
macro_rules! kBUG {
|
||||||
($($arg:tt)*) => {
|
($($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_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)*)));
|
$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) {
|
pub fn __printk(args: fmt::Arguments) {
|
||||||
PrintkWriter.write_fmt(args).unwrap();
|
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_GETTID => Self::gettid().map(|tid| tid.into()),
|
||||||
SYS_GETUID => Self::getuid().map(|uid| uid.into()),
|
SYS_GETUID => Self::getuid().map(|uid| uid.into()),
|
||||||
|
|
||||||
SYS_SYSLOG => {
|
SYS_SYSLOG => {
|
||||||
kwarn!("SYS_SYSLOG has not yet been implemented");
|
let syslog_action_type = args[0] as usize;
|
||||||
Ok(0)
|
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_GETGID => Self::getgid().map(|gid| gid.into()),
|
||||||
SYS_SETUID => {
|
SYS_SETUID => {
|
||||||
kwarn!("SYS_SETUID has not yet been implemented");
|
kwarn!("SYS_SETUID has not yet been implemented");
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
use core::{
|
use core::{
|
||||||
fmt,
|
fmt,
|
||||||
|
intrinsics::unlikely,
|
||||||
ops::{self, Sub},
|
ops::{self, Sub},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::arch::CurrentTimeArch;
|
||||||
|
|
||||||
use self::timekeep::ktime_get_real_ns;
|
use self::timekeep::ktime_get_real_ns;
|
||||||
|
|
||||||
pub mod clocksource;
|
pub mod clocksource;
|
||||||
@ -55,6 +58,27 @@ impl TimeSpec {
|
|||||||
tv_nsec: nsec,
|
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 {
|
impl Sub for TimeSpec {
|
||||||
|
@ -129,7 +129,7 @@ impl Timer {
|
|||||||
if unlikely(r.is_err()) {
|
if unlikely(r.is_err()) {
|
||||||
kerror!(
|
kerror!(
|
||||||
"Failed to run timer function: {self:?} {:?}",
|
"Failed to run timer function: {self:?} {:?}",
|
||||||
r.err().unwrap()
|
r.as_ref().err().unwrap()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,32 @@
|
|||||||
# 该脚本会自动下载musl交叉编译工具链,并将其添加到PATH中
|
# 该脚本会自动下载musl交叉编译工具链,并将其添加到PATH中
|
||||||
#########################################################################
|
#########################################################################
|
||||||
|
|
||||||
|
export USE_GITHUB=${USE_GITHUB:=0}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MUSL_GCC_DATE="231114"
|
MUSL_GCC_DATE="231114"
|
||||||
MUSL_GCC_VERSION="9.4.0"
|
MUSL_GCC_VERSION="9.4.0"
|
||||||
|
MUSL_GCC_X86_64_TAR=
|
||||||
|
MUSL_GCC_RISCV64_TAR=
|
||||||
|
|
||||||
|
MUSL_GCC_X86_64_DOWNLOAD_URL=""
|
||||||
|
MUSL_GCC_RISCV64_DOWNLOAD_URL=""
|
||||||
|
if [ $USE_GITHUB -eq 1 ]; then
|
||||||
|
echo "Download from github"
|
||||||
|
|
||||||
|
MUSL_GCC_X86_64_TAR=x86_64-linux-musl-cross-gcc-${MUSL_GCC_VERSION}.tar.xz
|
||||||
|
MUSL_GCC_RISCV64_TAR=riscv64-linux-musl-cross-gcc-${MUSL_GCC_VERSION}.tar.xz
|
||||||
|
MUSL_GCC_X86_64_DOWNLOAD_URL="https://github.com/DragonOS-Community/musl-cross-make/releases/download/${MUSL_GCC_VERSION}-${MUSL_GCC_DATE}/${MUSL_GCC_X86_64_TAR}"
|
||||||
|
MUSL_GCC_RISCV64_DOWNLOAD_URL="https://github.com/DragonOS-Community/musl-cross-make/releases/download/${MUSL_GCC_VERSION}-${MUSL_GCC_DATE}/${MUSL_GCC_RISCV64_TAR}"
|
||||||
|
https://github.com/DragonOS-Community/musl-cross-make/releases/download/9.4.0-231114/riscv64-linux-musl-cross-gcc-9.4.0.tar.xz
|
||||||
|
else
|
||||||
|
echo "Download from mirrors.dragonos.org.cn"
|
||||||
MUSL_GCC_X86_64_TAR="x86_64-linux-musl-cross-gcc-${MUSL_GCC_VERSION}-${MUSL_GCC_DATE}.tar.xz"
|
MUSL_GCC_X86_64_TAR="x86_64-linux-musl-cross-gcc-${MUSL_GCC_VERSION}-${MUSL_GCC_DATE}.tar.xz"
|
||||||
MUSL_GCC_RISCV64_TAR="riscv64-linux-musl-cross-gcc-${MUSL_GCC_VERSION}-${MUSL_GCC_DATE}.tar.xz"
|
MUSL_GCC_RISCV64_TAR="riscv64-linux-musl-cross-gcc-${MUSL_GCC_VERSION}-${MUSL_GCC_DATE}.tar.xz"
|
||||||
MUSL_GCC_X86_64_DOWNLOAD_URL="https://mirrors.dragonos.org.cn/pub/third_party/toolchain/gcc/${MUSL_GCC_X86_64_TAR}"
|
MUSL_GCC_X86_64_DOWNLOAD_URL="https://mirrors.dragonos.org.cn/pub/third_party/toolchain/gcc/${MUSL_GCC_X86_64_TAR}"
|
||||||
MUSL_GCC_RISCV64_DOWNLOAD_URL="https://mirrors.dragonos.org.cn/pub/third_party/toolchain/gcc/${MUSL_GCC_RISCV64_TAR}"
|
MUSL_GCC_RISCV64_DOWNLOAD_URL="https://mirrors.dragonos.org.cn/pub/third_party/toolchain/gcc/${MUSL_GCC_RISCV64_TAR}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
INSTALL_POS="$HOME/opt/"
|
INSTALL_POS="$HOME/opt/"
|
||||||
|
@ -51,9 +51,8 @@ endif
|
|||||||
.PHONY: dadk_run
|
.PHONY: dadk_run
|
||||||
dadk_run: install_dadk
|
dadk_run: install_dadk
|
||||||
mkdir -p $(DADK_CACHE_DIR)
|
mkdir -p $(DADK_CACHE_DIR)
|
||||||
# 之所以在这里临时设置ARCH为空,是因为如果要设置这个环境变量,应当在DADK的配置文件中设置
|
dadk --config-dir dadk/config --cache-dir $(DADK_CACHE_DIR) --dragonos-dir $(ROOT_PATH)/bin/sysroot build
|
||||||
ARCH= dadk --config-dir dadk/config --cache-dir $(DADK_CACHE_DIR) --dragonos-dir $(ROOT_PATH)/bin/sysroot build
|
dadk --config-dir dadk/config --cache-dir $(DADK_CACHE_DIR) --dragonos-dir $(ROOT_PATH)/bin/sysroot install
|
||||||
ARCH= dadk --config-dir dadk/config --cache-dir $(DADK_CACHE_DIR) --dragonos-dir $(ROOT_PATH)/bin/sysroot install
|
|
||||||
|
|
||||||
.PHONY: dadk_clean
|
.PHONY: dadk_clean
|
||||||
dadk_clean: install_dadk
|
dadk_clean: install_dadk
|
||||||
|
1
user/apps/dmesg/.gitignore
vendored
Normal file
1
user/apps/dmesg/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
dmesg
|
17
user/apps/dmesg/Makefile
Normal file
17
user/apps/dmesg/Makefile
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
ifeq ($(ARCH), x86_64)
|
||||||
|
export PREFIX=x86_64-linux-musl-
|
||||||
|
else ifeq ($(ARCH), riscv64)
|
||||||
|
export PREFIX=riscv64-linux-musl-
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
export CC=$(PREFIX)gcc
|
||||||
|
|
||||||
|
all: dmesg
|
||||||
|
mv dmesg $(DADK_CURRENT_BUILD_DIR)
|
||||||
|
|
||||||
|
dmesg: main.c
|
||||||
|
$(CC) -static -o dmesg main.c dmesg.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm dmesg *.o
|
86
user/apps/dmesg/dmesg.c
Normal file
86
user/apps/dmesg/dmesg.c
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#include "dmesg.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 识别dmesg程序的第一个选项参数
|
||||||
|
*
|
||||||
|
* @param arg dmesg命令第一个选项参数
|
||||||
|
* @return int 有效时返回对应选项码,无效时返回 -1
|
||||||
|
*/
|
||||||
|
int getopt(char *arg)
|
||||||
|
{
|
||||||
|
if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
|
||||||
|
return 0;
|
||||||
|
else if (!strcmp(arg, "-c") || !strcmp(arg, "--read-clear"))
|
||||||
|
return 4;
|
||||||
|
else if (!strcmp(arg, "-C") || !strcmp(arg, "--clear"))
|
||||||
|
return 5;
|
||||||
|
else if (!strcmp(arg, "-l") || !strcmp(arg, "--level"))
|
||||||
|
return 8;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 识别dmesg程序的第二个选项参数
|
||||||
|
*
|
||||||
|
* @param arg dmesg命令第一个选项参数
|
||||||
|
* @return int 有效时返回设置的日志级别,无效时返回 -1
|
||||||
|
*/
|
||||||
|
int getlevel(char *arg)
|
||||||
|
{
|
||||||
|
if (!strcmp(arg, "EMERG") || !strcmp(arg, "emerg"))
|
||||||
|
return 0;
|
||||||
|
else if (!strcmp(arg, "ALERT") || !strcmp(arg, "alert"))
|
||||||
|
return 1;
|
||||||
|
else if (!strcmp(arg, "CRIT") || !strcmp(arg, "crit"))
|
||||||
|
return 2;
|
||||||
|
else if (!strcmp(arg, "ERR") || !strcmp(arg, "err"))
|
||||||
|
return 3;
|
||||||
|
else if (!strcmp(arg, "WARN") || !strcmp(arg, "warn"))
|
||||||
|
return 4;
|
||||||
|
else if (!strcmp(arg, "NOTICE") || !strcmp(arg, "notice"))
|
||||||
|
return 5;
|
||||||
|
else if (!strcmp(arg, "INFO") || !strcmp(arg, "info"))
|
||||||
|
return 6;
|
||||||
|
else if (!strcmp(arg, "DEBUG") || !strcmp(arg, "debug"))
|
||||||
|
return 7;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("dmesg: unknown level '%s'\n", arg);
|
||||||
|
}
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 打印dmesg手册
|
||||||
|
*/
|
||||||
|
void print_help_msg()
|
||||||
|
{
|
||||||
|
const char *help_msg = "Usage:\n"
|
||||||
|
" dmesg [options]\n\n"
|
||||||
|
"Display or control the kernel ring buffer.\n\n"
|
||||||
|
"Options:\n"
|
||||||
|
" -C, --clear clear the kernel ring buffer\n"
|
||||||
|
" -c, --read-clear read and clear all messages\n"
|
||||||
|
" -l, --level <list> restrict output to defined levels\n"
|
||||||
|
" -h, --help display this help\n\n"
|
||||||
|
"Supported log levels (priorities):\n"
|
||||||
|
" emerg - system is unusable\n"
|
||||||
|
" alert - action must be taken immediately\n"
|
||||||
|
" crit - critical conditions\n"
|
||||||
|
" err - error conditions\n"
|
||||||
|
" warn - warning conditions\n"
|
||||||
|
" notice - normal but significant condition\n"
|
||||||
|
" info - informational\n"
|
||||||
|
" debug - debug-level messages\n";
|
||||||
|
printf("%s\n", help_msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 打印dmesg错误使用的信息
|
||||||
|
*/
|
||||||
|
void print_bad_usage_msg()
|
||||||
|
{
|
||||||
|
const char *bad_usage_msg = "dmesg: bad usage\nTry 'dmesg --help' for more information.";
|
||||||
|
printf("%s\n", bad_usage_msg);
|
||||||
|
}
|
31
user/apps/dmesg/dmesg.h
Normal file
31
user/apps/dmesg/dmesg.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 识别dmesg程序的第一个选项参数
|
||||||
|
*
|
||||||
|
* @param arg dmesg命令第一个选项参数
|
||||||
|
* @return int 有效时返回对应选项码,无效时返回 -1
|
||||||
|
*/
|
||||||
|
int getopt(char *arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 识别dmesg程序的第二个选项参数
|
||||||
|
*
|
||||||
|
* @param arg dmesg命令第一个选项参数
|
||||||
|
* @return int 有效时返回设置的日志级别,无效时返回 -1
|
||||||
|
*/
|
||||||
|
int getlevel(char *arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 打印dmesg手册
|
||||||
|
*/
|
||||||
|
void print_help_msg();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 打印dmesg错误使用的信息
|
||||||
|
*/
|
||||||
|
void print_bad_usage_msg();
|
113
user/apps/dmesg/main.c
Normal file
113
user/apps/dmesg/main.c
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
#include "dmesg.h"
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
unsigned int len = 1;
|
||||||
|
char *buf = NULL;
|
||||||
|
int opt;
|
||||||
|
unsigned int color = 65280;
|
||||||
|
|
||||||
|
// 获取内核缓冲区大小
|
||||||
|
len = klogctl(10, buf, len);
|
||||||
|
|
||||||
|
if (len < 16 * 1024)
|
||||||
|
len = 16 * 1024;
|
||||||
|
if (len > 16 * 1024 * 1024)
|
||||||
|
len = 16 * 1024 * 1024;
|
||||||
|
|
||||||
|
buf = malloc(len);
|
||||||
|
if (buf == NULL)
|
||||||
|
{
|
||||||
|
perror("");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc == 1)
|
||||||
|
{
|
||||||
|
// 无选项参数,默认打印所有日志消息
|
||||||
|
len = klogctl(2, buf, len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 获取第一个选项参数
|
||||||
|
opt = getopt(argv[1]);
|
||||||
|
|
||||||
|
// 无效参数
|
||||||
|
if (opt == -1)
|
||||||
|
{
|
||||||
|
print_bad_usage_msg();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// 打印帮助手册
|
||||||
|
else if (opt == 0)
|
||||||
|
{
|
||||||
|
print_help_msg();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// 4 -> 读取内核缓冲区后,清空缓冲区
|
||||||
|
// 5 -> 清空内核缓冲区
|
||||||
|
else if (opt == 4 || opt == 5)
|
||||||
|
{
|
||||||
|
len = klogctl(opt, buf, len);
|
||||||
|
}
|
||||||
|
// 读取特定日志级别的消息
|
||||||
|
else if (opt == 8)
|
||||||
|
{
|
||||||
|
// 无指定日志级别参数,打印错误使用信息
|
||||||
|
if (argc < 3)
|
||||||
|
{
|
||||||
|
print_bad_usage_msg();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int level = -1;
|
||||||
|
|
||||||
|
// 获取日志级别
|
||||||
|
// 这里加1的原因是:如果klogctl的第三个参数是0,不会发生系统调用
|
||||||
|
level = getlevel(argv[2]) + 1;
|
||||||
|
|
||||||
|
if (level == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
klogctl(8, buf, level);
|
||||||
|
len = klogctl(2, buf, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 当前打印内容
|
||||||
|
// 0: 日志级别
|
||||||
|
// 1: 时间戳
|
||||||
|
// 2: 代码行号
|
||||||
|
// 3: 日志消息
|
||||||
|
unsigned int content = 0;
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
char c[2];
|
||||||
|
c[0] = buf[i];
|
||||||
|
c[1] = '\0';
|
||||||
|
syscall(100000, &c[0], color, 0);
|
||||||
|
if (content == 0 && buf[i] == '>')
|
||||||
|
{
|
||||||
|
content++;
|
||||||
|
}
|
||||||
|
else if (content == 1 && buf[i] == ']')
|
||||||
|
{
|
||||||
|
color = 16744448;
|
||||||
|
content++;
|
||||||
|
}
|
||||||
|
else if (content == 2 && buf[i] == ')')
|
||||||
|
{
|
||||||
|
color = 16777215;
|
||||||
|
content++;
|
||||||
|
}
|
||||||
|
else if (content == 3 && buf[i] == '\n')
|
||||||
|
{
|
||||||
|
color = 65280;
|
||||||
|
content = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
23
user/dadk/config/dmesg-0.1.0.dadk
Normal file
23
user/dadk/config/dmesg-0.1.0.dadk
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name": "dmesg",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "查看日志",
|
||||||
|
"task_type": {
|
||||||
|
"BuildFromSource": {
|
||||||
|
"Local": {
|
||||||
|
"path": "apps/dmesg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"depends": [ ],
|
||||||
|
"build": {
|
||||||
|
"build_command": "make"
|
||||||
|
},
|
||||||
|
"install": {
|
||||||
|
"in_dragonos_path": "/bin"
|
||||||
|
},
|
||||||
|
"clean": {
|
||||||
|
"clean_command": "make clean"
|
||||||
|
},
|
||||||
|
"envs": []
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user