rCore - Chapter01
rCore - Chapter01
课后练习
实现一个linux应用程序A,显示当前目录下的文件名。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
use std::fs;
use std::io;
fn main() -> io::Result<()> {
let current_dir = std::env::current_dir()?;
let entries = fs::read_dir(current_dir)?;
for entry in entries {
let entry = entry?;
let file_name = entry.file_name();
println!("{}", file_name.to_string_lossy());
}
Ok(())
}
实现一个linux应用程序B,能打印出调用栈链信息。
可以参考Stanford CS110L的Project 1,用Rust语言实现了一个简单的debugger,比较有意思
实现一个基于rcore tutorial的应用程序C,用sleep系统调用睡眠5秒
如果你做过xv6,你应该知道需要通过qemu
模拟的CLINT(Core Local Interruptor)
去得到mtime
寄存器的值,该寄存器映射到了内存中0x2000000 + 0xBFF8
上,其中前者是CLINT
映射的起始地址,后者是mtime
相对于CLINT
基地址的偏移量,mtime
寄存器的大小是8字节,记得在[dependency]
里加入riscv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const CLINT_BASE: usize = 0x2000000;
const MTIME_OFFSET: usize = 0xBFF8;
const TIMER_FREQUENCY: u64 = 10_000_000;
pub fn sleep(duration: u64) {
let ticks = duration * TIMER_FREQUENCY;
sleep_ticks(ticks);
}
fn sleep_ticks(duration: u64) {
let current_time = read_mtime();
let wake_time = current_time + duration;
sbi_rt::set_timer(wake_time); // 设置wakeup时间
riscv::asm::wfi(); // 让cpu进入low-power等待状态,等待interrupt
}
fn read_mtime() -> u64 {
unsafe { core::ptr::read_volatile((CLINT_BASE + MTIME_OFFSET) as *const u64) }
}
实验练习
彩色化LOG
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use core::sync::atomic::{AtomicU8, Ordering};
pub const RESET: &str = "\x1b[0m";
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
#[repr(u8)]
pub enum LogLevel {
NONE = 0, // No output
ERROR = 1,
WARN = 2,
INFO = 3,
DEBUG = 4,
TRACE = 5,
}
/// Atomic global log level (Safe access without `unsafe`)
static LOG_LEVEL_FILTER: AtomicU8 = AtomicU8::new(LogLevel::INFO as u8);
#[derive(Debug, Clone, Copy)]
pub struct LogConfig {
pub color: &'static str,
pub name: &'static str,
pub level: LogLevel,
}
pub const ERROR: LogConfig = LogConfig {
color: "\x1b[31m",
name: "ERROR",
level: LogLevel::ERROR,
};
pub const WARN: LogConfig = LogConfig {
color: "\x1b[93m",
name: "WARN",
level: LogLevel::WARN,
};
pub const INFO: LogConfig = LogConfig {
color: "\x1b[34m",
name: "INFO",
level: LogLevel::INFO,
};
pub const DEBUG: LogConfig = LogConfig {
color: "\x1b[32m",
name: "DEBUG",
level: LogLevel::DEBUG,
};
pub const TRACE: LogConfig = LogConfig {
color: "\x1b[90m",
name: "TRACE",
level: LogLevel::TRACE,
};
#[macro_export]
macro_rules! log {
($level:expr, $($arg:tt)*) => {
if $level.level as u8 <= $crate::logging::get_log_level() as u8 {
print!("{}[{}] ", $level.color, $level.name);
println!($($arg)*);
print!("{}", $crate::logging::RESET);
}
};
}
#[macro_export]
macro_rules! error {
($($arg:tt)*) => (log!($crate::logging::ERROR, $($arg)*));
}
#[macro_export]
macro_rules! warn {
($($arg:tt)*) => (log!($crate::logging::WARN, $($arg)*));
}
#[macro_export]
macro_rules! info {
($($arg:tt)*) => (log!($crate::logging::INFO, $($arg)*));
}
#[macro_export]
macro_rules! debug {
($($arg:tt)*) => (log!($crate::logging::DEBUG, $($arg)*));
}
#[macro_export]
macro_rules! trace {
($($arg:tt)*) => (log!($crate::logging::TRACE, $($arg)*));
}
/// **Set log level safely**
pub fn set_log_level(level: LogLevel) {
LOG_LEVEL_FILTER.store(level as u8, Ordering::Relaxed);
}
/// **Get current log level safely**
pub fn get_log_level() -> LogLevel {
match LOG_LEVEL_FILTER.load(Ordering::Relaxed) {
0 => LogLevel::NONE,
1 => LogLevel::ERROR,
2 => LogLevel::WARN,
3 => LogLevel::INFO,
4 => LogLevel::DEBUG,
5 => LogLevel::TRACE,
_ => LogLevel::INFO, // Default to INFO
}
}
/// **Initialize log level from environment variable (`LOG`)**
pub fn init_log_level() {
use core::option_env;
let log_str = option_env!("LOG").unwrap_or("INFO");
let level = match log_str {
"NONE" => LogLevel::NONE,
"ERROR" => LogLevel::ERROR,
"WARN" => LogLevel::WARN,
"INFO" => LogLevel::INFO,
"DEBUG" => LogLevel::DEBUG,
"TRACE" => LogLevel::TRACE,
_ => LogLevel::INFO, // Default INFO
};
set_log_level(level);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
LOG ?= INFO
build:
cargo build --release
rust-objcopy \
--strip-all \
target/riscv64gc-unknown-none-elf/release/os \
-O binary \
target/riscv64gc-unknown-none-elf/release/os.bin
run: build
qemu-system-riscv64 \
-machine virt \
-nographic \
-bios ../bootloader/rustsbi-qemu.bin \
-device loader,file=target/riscv64gc-unknown-none-elf/release/os.bin,addr=0x80200000
clean:
cargo clean
输出:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
rust-objcopy \
--strip-all \
target/riscv64gc-unknown-none-elf/release/os \
-O binary \
target/riscv64gc-unknown-none-elf/release/os.bin
qemu-system-riscv64 \
-machine virt \
-nographic \
-bios ../bootloader/rustsbi-qemu.bin \
-device loader,file=target/riscv64gc-unknown-none-elf/release/os.bin,addr=0x80200000
[rustsbi] RustSBI version 0.3.1, adapting to RISC-V SBI v1.0.0
.______ __ __ _______.___________. _______..______ __
| _ \ | | | | / | | / || _ \ | |
| |_) | | | | | | (----`---| |----`| (----`| |_) || |
| / | | | | \ \ | | \ \ | _ < | |
| |\ \----.| `--' |.----) | | | .----) | | |_) || |
| _| `._____| \______/ |_______/ |__| |_______/ |______/ |__|
[rustsbi] Implementation : RustSBI-QEMU Version 0.2.0-alpha.2
[rustsbi] Platform Name : riscv-virtio,qemu
[rustsbi] Platform SMP : 1
[rustsbi] Platform Memory : 0x80000000..0x88000000
[rustsbi] Boot HART : 0
[rustsbi] Device Tree Region : 0x87000000..0x87000ef2
[rustsbi] Firmware Address : 0x80000000
[rustsbi] Supervisor Address : 0x80200000
[rustsbi] pmp01: 0x00000000..0x80000000 (-wr)
[rustsbi] pmp02: 0x80000000..0x80200000 (---)
[rustsbi] pmp03: 0x80200000..0x88000000 (xwr)
[rustsbi] pmp04: 0x88000000..0x00000000 (-wr)
[INFO] .text [0x80200000, 0x80202000)
[INFO] .rodata [0x80202000, 0x80203000)
[INFO] .data [0x80203000, 0x80204000)
[INFO] .bss [0x80214000, 0x80214000)
Hello, world!
Panicked at src/main.rs:23 Shutdown machine!
make: *** [Makefile:12: run] Error 255
This post is licensed under CC BY 4.0 by the author.