#![no_std]#![no_main]#[macro_use]externcrate rust;// IMPORTANT: Must define main() like this#[no_mangle]pubfnmain()->i32{println!("Rust user shell");loop{}}
修改 Makefile,将用户程序和 shell 打包成 img :
# in Makefile
usr_path := usr
export SFSIMG = $(usr_path)/rcore32.img
# in usr/Makefile
.PHONY: all clean rust build
all: rust build
build: $(out_img)
$(out_img): rust
@rcore-fs-fuse $@ $(out_dir) zip
rcore-fs-fuse:
ifeq ($(shell which rcore-fs-fuse),)
@echo Installing rcore-fs-fuse
@cargo install rcore-fs-fuse --git https://github.com/rcore-os/rcore-fs --rev c611248
endif
// in process/mod.rs
use crate::fs::ROOT_INODE;
use crate::fs::INodeExt;
pub fn kmain() {
CPU.run();
}
pub fn init() {
println!("+------ now to initialize process ------+");
let scheduler = Scheduler::new(1);
let thread_pool = ThreadPool::new(100, scheduler);
CPU.init(Thread::new_idle(), Box::new(thread_pool));
let data = ROOT_INODE
.lookup("rust/shell")
.unwrap()
.read_as_vec()
.unwrap();
println!("size of program {:#x}", data.len());
let user = unsafe{ Thread::new_user(data.as_slice()) };
CPU.add_thread(user);
}
// in init.rs
use crate::process::{ init as process_init, kmain };
use crate::fs::init as fs_init;
#[no_mangle]
pub extern "C" fn rust_main(hartid: usize, dtb: usize) -> ! {
interrupt_init();
println!("Hello RISCV ! in hartid {}, dtb @ {:#x} ", hartid, dtb);
memory_init(dtb);
fs_init();
clock_init();
process_init();
kmain();
loop {}
}
// in lib.rs
mod fs;
// in fs/mod.rs
use lazy_static::*;
use rcore_fs::vfs::*;
use rcore_fs_sfs::SimpleFileSystem;
use alloc::{ sync::Arc, vec::Vec };
mod device;
lazy_static! {
/// The root of file system
pub static ref ROOT_INODE: Arc<INode> = {
let device = {
extern {
fn _user_img_start();
fn _user_img_end();
}
// 将存储磁盘文件的内存范围初始化为虚拟磁盘 Membuf
Arc::new(unsafe { device::MemBuf::new(_user_img_start, _user_img_end) })
};
let sfs = SimpleFileSystem::open(device).expect("failed to open SFS");
sfs.root_inode()
};
}
pub trait INodeExt {
fn read_as_vec(&self) -> Result<Vec<u8>>;
}
impl INodeExt for INode {
fn read_as_vec(&self) -> Result<Vec<u8>> {
let size = self.metadata()?.size;
let mut buf = Vec::with_capacity(size);
unsafe {
buf.set_len(size);
}
self.read_at(0, buf.as_mut_slice())?;
Ok(buf)
}
}
pub fn init() {
// 打印当前目录下的所有项的名字
let mut id = 0;
while let Ok(name) = ROOT_INODE.get_entry(id) {
id += 1;
println!("{}", name);
}
}
// in fs/device.rs
use spin::RwLock;
use rcore_fs::dev::*;
pub struct MemBuf(RwLock<&'static mut [u8]>);
impl MemBuf {
pub unsafe fn new(begin: unsafe extern "C" fn(), end: unsafe extern "C" fn()) -> Self {
use core::slice;
MemBuf(RwLock::new(slice::from_raw_parts_mut(
begin as *mut u8,
end as usize - begin as usize,
)))
}
}
impl Device for MemBuf {
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
let slice = self.0.read();
let len = buf.len().min(slice.len() - offset); // 取磁盘剩余长度和 buf 大小的较小值
buf[..len].copy_from_slice(&slice[offset..offset + len]);
Ok(len)
}
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
let mut slice = self.0.write();
let len = buf.len().min(slice.len() - offset);
slice[offset..offset + len].copy_from_slice(&buf[..len]);
Ok(len)
}
fn sync(&self) -> Result<()> {
Ok(())
}
}
// in Cargo.toml
rcore-fs = { path = "crate/rcore-fs" }
rcore-fs-sfs = { path = "crate/rcore-fs-sfs" }
// in init.rs
use crate::process::{ init as process_init, kmain };
use crate::fs::init as fs_init;
#[no_mangle]
pub extern "C" fn rust_main(hartid: usize, dtb: usize) -> ! {
interrupt_init();
println!("Hello RISCV ! in hartid {}, dtb @ {:#x} ", hartid, dtb);
memory_init(dtb);
fs_init();
clock_init();
process_init();
kmain();
loop {}
}
...
tid to alloc: 0
Rust user shell
thread 0 ran just now
thread 0 ran just now
thread 0 ran just now
thread 0 ran just now
thread 0 ran just now
...