Ch0 Anwser
1.配环境
我用的是nixos/macos双系统,我的macos也使用的nix-darwin,所以我基本上只用在nisos中配好home-manager,就可以了,当然其实最好的方式是写一个nix shell,然后每次工作的时候使用nix shell
然后qemu没什么好说的,加一个qemu包即可,但是交叉编译工具链可能和普通的包不一样,需要写pkgsCross.riscv64-embedded.buildPackages.gcc
,然后使用alias把riscv64-none-elf-gdb 到riscv64-unknown-elf-gdb,然后clone下rcore的仓库,make run即可,至于为啥是none,具体是由于stdenv的原因
2.exception
在Linux环境下编写一个会产生异常的应用程序,并简要解释操作系统的处理结果
使用rust编写一个除0函数,将报告
> rustc exception.rs
error: this operation will panic at runtime
--> exception.rs:3:13
|
3 | let a = 1/0;
| ^^^ attempt to divide `1_i32` by zero
|
= note: `#[deny(unconditional_panic)]` on by default
error: aborting due to 1 previous error
如果使用他给的建议#![allow(unconditional_panic)]
> RUST_BACKTRACE=1 ./exception
thread 'main' panicked at exception.rs:3:13:
attempt to divide by zero
stack backtrace:
0: __rustc::rust_begin_unwind
at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/std/src/panicking.rs:697:5
1: core::panicking::panic_fmt
at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/core/src/panicking.rs:75:14
2: core::panicking::panic_const::panic_const_div_by_zero
at /rustc/29483883eed69d5fb4db01964cdf2af4d86e9cb2/library/core/src/panicking.rs:175:17
3: exception::main
4: core::ops::function::FnOnce::call_once
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
会panic,但是看起来并不是操作系统的panic,而是unwind,然后走的编程语言级别的panic,于是打算使用c语言编写
> gcc exception.c
exception.c: In function ‘main’:
exception.c:3:15: warning: division by zero [-Wdiv-by-zero]
3 | int a = 1 / 0;
> ./a.out
0
很奇怪,为什么不会出错,是不是arm对于除0错误并不会报异常
搜了一下,发现是存在某个寄存器来控制是否报异常
3.sleep
** 在Linux环境下编写一个可以睡眠5秒后打印出一个字符串,并把字符串内容存入一个文件中的应用程序A。(基于C或Rust语言)
学习了一点rust中的文件操作,并学习了一点错误处理相关的知识,得到了如下最佳实践
-
对于预料之内的错误应该错误传播,如rust中的?
-
对于预料之外的错误应该立刻panic并退出
-
函数应该检查参数的合法性,最好将参数定义为一个新类型,并由类型检查来检查合法性
-
使用unwrap等方法会比match更简洁
之后的代码
use std::io::{self, Write};
use std::{thread, time};
use std::fs::{OpenOptions};
fn main() -> Result<(), io::Error>{
let mut file = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.truncate(true)
.open("foo.txt").expect("main: open file Unexpected error");
loop {
file.write_all(b"Hello, Rust\n").expect("main: write file unexpected error");
println!("Hello, Rust!\n");
thread::sleep(time::Duration::new(5, 0));
}
4.Concurrency
*** 在Linux环境下编写一个应用程序B,简要说明此程序能够体现操作系统的并发性、异步性、共享性和持久性。(基于C或Rust语言)
有点懵逼,去学了rust book的Fearless Concurrency 但是第三个有点看不懂,就是线程中通过内存共享来通信,因为还没看智能指针部分,然后写下了如下简单的线程代码
use std::{sync::mpsc, thread, time::Duration};
fn main() {
let (tx, rx) = mpsc::channel();
let handle = thread::spawn(move || {
for i in 1..10 {
println!("hi {i} from spawned thread!");
//thread::sleep(Duration::from_millis(1));
}
tx.send(String::from("hi")).unwrap();
});
let received = rx.recv().unwrap();
for i in 1..10 {
println!("hi {i} from main thread!");
//thread::sleep(Duration::from_millis(1));
}
println!("got {received}");
handle.join().unwrap();
}
将handle.join().unwrap();
和 let received = rx.recv().unwrap();
放在不同位置会打印出不同的结果