添加用户引用 0号进程

ch5
zhangxinyu 2 years ago
parent 713571b729
commit 2f40dbce77

@ -7,6 +7,7 @@ edition = "2021"
[dependencies] [dependencies]
riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] } riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] }
buddy_system_allocator = "0.6"
[profile.release] [profile.release]
debug = true debug = true

@ -25,4 +25,4 @@ build: build_elf
clean: clean:
rm -rf ./target* #rm -rf ./target*

@ -0,0 +1,27 @@
#![no_std]
#![no_main]
use user_lib::syscall::{sys_fork, sys_yield, sys_exec};
use user_lib::{println, wait};
#[no_mangle]
fn main() -> i32 {
if sys_fork() == 0 {
// 注意需要手动添加\0 转为 c_str
sys_exec("user_shell\0");
} else {
loop {
let mut exit_code: i32 = 0;
let pid = wait(&mut exit_code);
if pid == -1 {
sys_yield();
continue;
}
println!(
"[initproc] Released a zombie process, pid={}, exit_code={}",
pid, exit_code,
);
}
}
0
}

@ -0,0 +1,70 @@
#![no_std]
#![no_main]
#![allow(clippy::println_empty_string)]
extern crate alloc;
const LF: u8 = 0x0au8;
const CR: u8 = 0x0du8;
const DL: u8 = 0x7fu8;
const BS: u8 = 0x08u8;
use alloc::string::String;
use user_lib::{ print, println, waitpid};
use user_lib::syscall::{sys_exec, sys_yield, sys_fork};
use user_lib::user_console::getchar;
#[no_mangle]
pub fn main() -> i32 {
println!("Rust user shell");
// line变量 维护着当前输入的内容, 它不断发生变化
let mut line: String = String::new();
print!(">> ");
loop {
// 循环读取标准输入
let c = getchar();
match c {
// 如果是 回车键, 开启一个新的进程, 把 line中的内容 使用exec 执行
LF | CR => {
println!("");
if !line.is_empty() {
line.push('\0');
let pid = sys_fork();
if pid == 0 {
// child process
if sys_exec(line.as_str()) == -1 {
// 返回 -1 说明没有存在 line中的程序
println!("Error when executing!");
return -4;
}
unreachable!();
} else {
// 等待上方子进程结束
let mut exit_code: i32 = 0;
let exit_pid = waitpid(pid as usize, &mut exit_code);
assert_eq!(pid, exit_pid);
println!("Shell: Process {} exited with code {}", pid, exit_code);
}
line.clear();
}
print!(">> ");
}
// 如果是退格键
BS | DL => {
if !line.is_empty() {
print!("{}", BS as char);
print!(" ");
print!("{}", BS as char);
line.pop();
}
}
_ => {
print!("{}", c as char);
line.push(c as char);
}
}
}
}

@ -8,12 +8,25 @@ pub use user_lang_items::*;
pub mod syscall; pub mod syscall;
use syscall::*; use syscall::*;
use buddy_system_allocator::LockedHeap;
const USER_HEAP_SIZE: usize = 16384;
static mut HEAP_SPACE: [u8; USER_HEAP_SIZE] = [0; USER_HEAP_SIZE];
// 用户应用的分配器
#[global_allocator]
static HEAP: LockedHeap = LockedHeap::empty();
// 只要使用这个包, 那么这里就会作为bin程序的开始 // 只要使用这个包, 那么这里就会作为bin程序的开始
#[no_mangle] #[no_mangle]
#[link_section = ".text.entry"] // 链接到指定的段 #[link_section = ".text.entry"] // 链接到指定的段
pub extern "C" fn _start() -> ! { pub extern "C" fn _start() -> ! {
unsafe {
HEAP.lock()
.init(HEAP_SPACE.as_ptr() as usize, USER_HEAP_SIZE);
}
sys_exit(main()); // 这里执行的main程序是我们 bin文件夹里面的main, 而不是下面的, 下面的main程序只有在bin程序没有main函数的时候才会链接 sys_exit(main()); // 这里执行的main程序是我们 bin文件夹里面的main, 而不是下面的, 下面的main程序只有在bin程序没有main函数的时候才会链接
// 正常是不会走到这一步的, 因为上面已经退出了程序 // 正常是不会走到这一步的, 因为上面已经退出了程序
panic!("unreachable after sys_exit!"); panic!("unreachable after sys_exit!");
@ -24,3 +37,27 @@ pub extern "C" fn _start() -> ! {
fn main() -> i32 { fn main() -> i32 {
panic!("Cannot find main!"); panic!("Cannot find main!");
} }
pub fn wait(exit_code: &mut i32) -> isize {
loop {
match sys_waitpid(-1, exit_code as *mut _) {
-2 => {
sys_yield();
}
// -1 or a real pid
exit_pid => return exit_pid,
}
}
}
pub fn waitpid(pid: usize, exit_code: &mut i32) -> isize {
loop {
match sys_waitpid(pid as isize, exit_code as *mut _) {
-2 => {
sys_yield();
}
// -1 or a real pid
exit_pid => return exit_pid,
}
}
}

@ -1,10 +1,15 @@
use core::arch::asm; use core::arch::asm;
const SYSCALL_READ: usize = 63;
const SYSCALL_WRITE: usize = 64; const SYSCALL_WRITE: usize = 64;
const SYSCALL_EXIT: usize = 93; const SYSCALL_EXIT: usize = 93;
const SYSCALL_YIELD: usize = 124; const SYSCALL_YIELD: usize = 124;
const SYSCALL_GET_TIME: usize = 169; const SYSCALL_GET_TIME: usize = 169;
const SYSCALL_SBRK: usize = 214; const SYSCALL_SBRK: usize = 214;
const SYSCALL_GETPID: usize = 172;
const SYSCALL_FORK: usize = 220;
const SYSCALL_EXEC: usize = 221;
const SYSCALL_WAITPID: usize = 260;
fn syscall(id: usize, args: [usize; 3]) -> isize { fn syscall(id: usize, args: [usize; 3]) -> isize {
@ -43,4 +48,25 @@ pub fn sys_sbrk(size: i32) -> isize {
syscall(SYSCALL_SBRK, [size as usize, 0, 0]) syscall(SYSCALL_SBRK, [size as usize, 0, 0])
} }
pub fn sys_getpid() -> isize {
syscall(SYSCALL_GETPID, [0, 0, 0])
}
pub fn sys_fork() -> isize {
syscall(SYSCALL_FORK, [0, 0, 0])
}
pub fn sys_exec(path: &str) -> isize {
syscall(SYSCALL_EXEC, [path.as_ptr() as usize, 0, 0])
}
pub fn sys_waitpid(pid: isize, exit_code: *mut i32) -> isize {
syscall(SYSCALL_WAITPID, [pid as usize, exit_code as usize, 0])
}
pub fn sys_read(fd: usize, buffer: &mut [u8]) -> isize {
syscall(
SYSCALL_READ,
[fd, buffer.as_mut_ptr() as usize, buffer.len()],
)
}

@ -1,8 +1,9 @@
use core::fmt::{Arguments, Write, Result}; use core::fmt::{Arguments, Write, Result};
use crate::syscall::sys_write; use crate::syscall::{sys_read, sys_write};
struct Stdout; struct Stdout;
const STDIN: usize = 0; // 读取 标准输入的标志
const STDOUT: usize = 1; const STDOUT: usize = 1;
impl Write for Stdout { impl Write for Stdout {
@ -12,6 +13,14 @@ impl Write for Stdout {
} }
} }
// 每次从标准输入读出一个字符
pub fn getchar() -> u8 {
let mut c = [0u8; 1];
sys_read(STDIN, &mut c);
c[0]
}
pub fn print(args: Arguments) { pub fn print(args: Arguments) {
Stdout.write_fmt(args).unwrap(); Stdout.write_fmt(args).unwrap();
} }

Loading…
Cancel
Save