未验证 提交 8f0fcfaf 编写于 作者: C chyyuu 提交者: GitHub

Merge pull request #40 from zhanghx0905/ch6

[Ch6] update user module to 2021autumn version
.idea/*
os/target/*
os/.idea/*
.idea
Cargo.lock
target
os/src/link_app.S
os/last-*
os/Cargo.lock
user/target/*
user/.idea/*
user/Cargo.lock
tools/
user/build
tools
......@@ -29,6 +29,8 @@ OBJCOPY := rust-objcopy --binary-architecture=riscv64
# Disassembly
DISASM ?= -x
TEST ?= 0
build: env switch-check $(KERNEL_BIN)
switch-check:
......@@ -48,7 +50,7 @@ $(KERNEL_BIN): kernel
@$(OBJCOPY) $(KERNEL_ELF) --strip-all -O binary $@
kernel:
@cd ../user && make build
@cd ../user && make build TEST=$(TEST)
@echo Platform: $(BOARD)
@cp src/linker-$(BOARD).ld src/linker.ld
@cargo build --release --features "board_$(BOARD)"
......
use std::fs::{read_dir, File};
use std::io::{Result, Write};
use std::fs::{File, read_dir};
fn main() {
println!("cargo:rerun-if-changed=../user/src/");
......@@ -7,11 +7,11 @@ fn main() {
insert_app_data().unwrap();
}
static TARGET_PATH: &str = "../user/target/riscv64gc-unknown-none-elf/release/";
static TARGET_PATH: &str = "../user/build/elf/";
fn insert_app_data() -> Result<()> {
let mut f = File::create("src/link_app.S").unwrap();
let mut apps: Vec<_> = read_dir("../user/src/bin")
let mut apps: Vec<_> = read_dir("../user/build/elf/")
.unwrap()
.into_iter()
.map(|dir_entry| {
......@@ -22,35 +22,46 @@ fn insert_app_data() -> Result<()> {
.collect();
apps.sort();
writeln!(f, r#"
writeln!(
f,
r#"
.align 3
.section .data
.global _num_app
_num_app:
.quad {}"#, apps.len())?;
.quad {}"#,
apps.len()
)?;
for i in 0..apps.len() {
writeln!(f, r#" .quad app_{}_start"#, i)?;
}
writeln!(f, r#" .quad app_{}_end"#, apps.len() - 1)?;
writeln!(f, r#"
writeln!(
f,
r#"
.global _app_names
_app_names:"#)?;
_app_names:"#
)?;
for app in apps.iter() {
writeln!(f, r#" .string "{}""#, app)?;
}
for (idx, app) in apps.iter().enumerate() {
println!("app_{}: {}", idx, app);
writeln!(f, r#"
writeln!(
f,
r#"
.section .data
.global app_{0}_start
.global app_{0}_end
.align 3
app_{0}_start:
.incbin "{2}{1}"
app_{0}_end:"#, idx, app, TARGET_PATH)?;
.incbin "{2}{1}.elf"
app_{0}_end:"#,
idx, app, TARGET_PATH
)?;
}
Ok(())
}
\ No newline at end of file
}
......@@ -6,7 +6,7 @@ pub const KERNEL_HEAP_SIZE: usize = 0x20_0000;
pub const MEMORY_END: usize = 0x80600000;
#[cfg(feature = "board_qemu")]
pub const MEMORY_END: usize = 0x80800000;
pub const MEMORY_END: usize = 0x80f00000;
pub const PAGE_SIZE: usize = 0x1000;
pub const PAGE_SIZE_BITS: usize = 0xc;
......
......@@ -24,7 +24,7 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
SYSCALL_WRITE => sys_write(args[0], args[1] as *const u8, args[2]),
SYSCALL_EXIT => sys_exit(args[0] as i32),
SYSCALL_YIELD => sys_yield(),
SYSCALL_GET_TIME => sys_get_time(),
SYSCALL_GET_TIME => sys_get_time(args[0] as *mut TimeVal, args[1]),
SYSCALL_GETPID => sys_getpid(),
SYSCALL_FORK => sys_fork(),
SYSCALL_EXEC => sys_exec(args[0] as *const u8),
......
......@@ -5,7 +5,7 @@ use crate::task::{
current_user_token,
add_task,
};
use crate::timer::get_time_ms;
use crate::timer::get_time_us;
use crate::mm::{
translated_str,
translated_refmut,
......@@ -13,6 +13,13 @@ use crate::mm::{
use crate::loader::get_app_data_by_name;
use alloc::sync::Arc;
#[repr(C)]
#[derive(Debug)]
pub struct TimeVal {
pub sec: usize,
pub usec: usize,
}
pub fn sys_exit(exit_code: i32) -> ! {
exit_current_and_run_next(exit_code);
panic!("Unreachable in sys_exit!");
......@@ -23,8 +30,15 @@ pub fn sys_yield() -> isize {
0
}
pub fn sys_get_time() -> isize {
get_time_ms() as isize
pub fn sys_get_time(_ts: *mut TimeVal, _tz: usize) -> isize {
let _us = get_time_us();
// unsafe {
// *ts = TimeVal {
// sec: us / 1_000_000,
// usec: us % 1_000_000,
// };
// }
0
}
pub fn sys_getpid() -> isize {
......
......@@ -3,14 +3,14 @@ use crate::sbi::set_timer;
use crate::config::CLOCK_FREQ;
const TICKS_PER_SEC: usize = 100;
const MSEC_PER_SEC: usize = 1000;
const MICRO_PER_SEC: usize = 1_000_000;
pub fn get_time() -> usize {
time::read()
}
pub fn get_time_ms() -> usize {
time::read() / (CLOCK_FREQ / MSEC_PER_SEC)
pub fn get_time_us() -> usize {
time::read() / (CLOCK_FREQ / MICRO_PER_SEC)
}
pub fn set_next_trigger() {
......
......@@ -7,4 +7,7 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
buddy_system_allocator = "0.6"
\ No newline at end of file
buddy_system_allocator = "0.6"
bitflags = "1.2.1"
spin = "0.9"
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
......@@ -2,22 +2,39 @@ TARGET := riscv64gc-unknown-none-elf
MODE := release
APP_DIR := src/bin
TARGET_DIR := target/$(TARGET)/$(MODE)
APPS := $(wildcard $(APP_DIR)/*.rs)
ELFS := $(patsubst $(APP_DIR)/%.rs, $(TARGET_DIR)/%, $(APPS))
BINS := $(patsubst $(APP_DIR)/%.rs, $(TARGET_DIR)/%.bin, $(APPS))
BUILD_DIR := build
OBJDUMP := rust-objdump --arch-name=riscv64
OBJCOPY := rust-objcopy --binary-architecture=riscv64
PY := python3
TEST ?= 0
ifeq ($(TEST), 0)
APPS := $(filter-out $(wildcard $(APP_DIR)/test*.rs), $(wildcard $(APP_DIR)/*.rs))
else
APPS := $(wildcard $(APP_DIR)/test*.rs) $(APP_DIR)/initproc.rs $(APP_DIR)/user_shell.rs
endif
ELFS := $(patsubst $(APP_DIR)/%.rs, $(TARGET_DIR)/%, $(APPS))
elf: $(APPS)
@cargo build --release
binary: elf
$(foreach elf, $(ELFS), $(OBJCOPY) $(elf) --strip-all -O binary $(patsubst $(TARGET_DIR)/%, $(TARGET_DIR)/%.bin, $(elf));)
@$(foreach elf, $(ELFS), \
$(OBJCOPY) $(elf) --strip-all -O binary $(patsubst $(TARGET_DIR)/%, $(TARGET_DIR)/%.bin, $(elf)); \
cp $(elf) $(patsubst $(TARGET_DIR)/%, $(TARGET_DIR)/%.elf, $(elf));)
build: binary
pre:
@mkdir -p $(BUILD_DIR)/bin/
@mkdir -p $(BUILD_DIR)/elf/
@mkdir -p $(BUILD_DIR)/app/
@$(foreach t, $(APPS), cp $(t) $(BUILD_DIR)/app/;)
build: clean pre binary
@$(foreach t, $(ELFS), cp $(t).bin $(BUILD_DIR)/bin/;)
@$(foreach t, $(ELFS), cp $(t).elf $(BUILD_DIR)/elf/;)
clean:
@cargo clean
@rm -rf $(BUILD_DIR)
.PHONY: elf binary build clean
\ No newline at end of file
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
extern crate alloc;
use user_lib::{
open,
OpenFlags,
close,
read,
};
use alloc::string::String;
#[no_mangle]
pub fn main(argc: usize, argv: &[&str]) -> i32 {
assert!(argc == 2);
let fd = open(argv[1], OpenFlags::RDONLY);
if fd == -1 {
panic!("Error occured when opening file");
}
let fd = fd as usize;
let mut buf = [0u8; 16];
let mut s = String::new();
loop {
let size = read(fd, &mut buf) as usize;
if size == 0 { break; }
s.push_str(core::str::from_utf8(&buf[..size]).unwrap());
}
println!("{}", s);
close(fd);
0
}
\ No newline at end of file
......@@ -3,7 +3,7 @@
#[macro_use]
extern crate user_lib;
use user_lib::{fork, yield_, waitpid, exit, wait};
use user_lib::{exit, fork, wait, waitpid, yield_};
const MAGIC: i32 = -0x10384;
......@@ -13,7 +13,9 @@ pub fn main() -> i32 {
let pid = fork();
if pid == 0 {
println!("I am the child.");
for _ in 0..7 { yield_(); }
for _ in 0..7 {
yield_();
}
exit(MAGIC);
} else {
println!("I am parent, fork a child pid {}", pid);
......@@ -26,4 +28,3 @@ pub fn main() -> i32 {
println!("exit pass.");
0
}
......@@ -41,4 +41,4 @@ pub fn main() -> i32 {
println!("{}", color_text!(text, i));
}
0
}
\ No newline at end of file
}
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{
open,
close,
read,
write,
OpenFlags,
};
#[no_mangle]
pub fn main() -> i32 {
let test_str = "Hello, world!";
let filea = "filea\0";
let fd = open(filea, OpenFlags::CREATE | OpenFlags::WRONLY);
assert!(fd > 0);
let fd = fd as usize;
write(fd, test_str.as_bytes());
close(fd);
let fd = open(filea, OpenFlags::RDONLY);
assert!(fd > 0);
let fd = fd as usize;
let mut buffer = [0u8; 100];
let read_len = read(fd, &mut buffer) as usize;
close(fd);
assert_eq!(
test_str,
core::str::from_utf8(&buffer[..read_len]).unwrap(),
);
println!("file_test passed!");
0
}
\ No newline at end of file
......@@ -4,7 +4,7 @@
#[macro_use]
extern crate user_lib;
use user_lib::{fork, wait, exit};
use user_lib::{exit, fork, wait};
const MAX_CHILD: usize = 40;
......@@ -31,4 +31,4 @@ pub fn main() -> i32 {
}
println!("forktest pass.");
0
}
\ No newline at end of file
}
......@@ -4,7 +4,7 @@
#[macro_use]
extern crate user_lib;
use user_lib::{fork, wait, getpid, exit, sleep, get_time};
use user_lib::{exit, fork, get_time, getpid, sleep, wait};
static NUM: usize = 30;
......@@ -14,7 +14,8 @@ pub fn main() -> i32 {
let pid = fork();
if pid == 0 {
let current_time = get_time();
let sleep_length = (current_time as i32 as isize) * (current_time as i32 as isize) % 1000 + 1000;
let sleep_length =
(current_time as i32 as isize) * (current_time as i32 as isize) % 1000 + 1000;
println!("pid {} sleep for {} ms", getpid(), sleep_length);
sleep(sleep_length as usize);
println!("pid {} OK!", getpid());
......@@ -30,4 +31,4 @@ pub fn main() -> i32 {
assert!(wait(&mut exit_code) < 0);
println!("forktest2 test passed!");
0
}
\ No newline at end of file
}
......@@ -25,4 +25,4 @@ pub fn main() -> i32 {
println!("child process pid = {}, exit code = {}", pid, exit_code);
0
}
}
\ No newline at end of file
}
......@@ -4,7 +4,7 @@
#[macro_use]
extern crate user_lib;
use user_lib::{sleep, getpid, fork, exit, yield_};
use user_lib::{exit, fork, getpid, sleep, yield_};
const DEPTH: usize = 4;
......
......@@ -8,4 +8,4 @@ extern crate user_lib;
pub fn main() -> i32 {
println!("Hello world from user mode program!");
0
}
\ No newline at end of file
}
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{
OpenFlags,
open,
close,
write,
get_time,
};
#[no_mangle]
pub fn main() -> i32 {
let mut buffer = [0u8; 1024]; // 1KiB
for i in 0..buffer.len() {
buffer[i] = i as u8;
}
let f = open("testf", OpenFlags::CREATE | OpenFlags::WRONLY);
if f < 0 {
panic!("Open test file failed!");
}
let f = f as usize;
let start = get_time();
let size_mb = 1usize;
for _ in 0..1024*size_mb {
write(f, &buffer);
}
close(f);
let time_ms = (get_time() - start) as usize;
let speed_kbs = size_mb * 1000000 / time_ms;
println!("time cost = {}ms, write speed = {}KiB/s", time_ms, speed_kbs);
0
}
\ No newline at end of file
......@@ -4,12 +4,7 @@
#[macro_use]
extern crate user_lib;
use user_lib::{
fork,
wait,
exec,
yield_,
};
use user_lib::{exec, fork, wait, yield_};
#[no_mangle]
fn main() -> i32 {
......@@ -25,10 +20,9 @@ fn main() -> i32 {
}
println!(
"[initproc] Released a zombie process, pid={}, exit_code={}",
pid,
exit_code,
pid, exit_code,
);
}
}
0
}
\ No newline at end of file
}
......@@ -4,7 +4,7 @@
#[macro_use]
extern crate user_lib;
use user_lib::{fork, wait, yield_, exit, getpid, get_time};
use user_lib::{exit, fork, get_time, getpid, wait, yield_};
static NUM: usize = 35;
const N: usize = 10;
......@@ -27,6 +27,7 @@ fn work(times: isize) {
for i in 0..N {
for j in 0..N {
c[i][j] = 0;
#[allow(clippy::needless_range_loop)]
for k in 0..N {
c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % P;
}
......@@ -65,4 +66,4 @@ pub fn main() -> i32 {
assert!(wait(&mut exit_code) < 0);
println!("matrix passed.");
0
}
\ No newline at end of file
}
......@@ -6,8 +6,8 @@ extern crate user_lib;
extern crate alloc;
use user_lib::{fork, close, pipe, read, write, wait, get_time};
use alloc::format;
use user_lib::{close, fork, get_time, pipe, read, wait, write};
const LENGTH: usize = 3000;
#[no_mangle]
......@@ -40,11 +40,14 @@ pub fn main() -> i32 {
// close write end of up pipe
close(up_pipe_fd[1]);
// generate a long random string
for i in 0..LENGTH {
random_str[i] = get_time() as u8;
for ch in random_str.iter_mut().take(LENGTH) {
*ch = get_time() as u8;
}
// send it
assert_eq!(write(down_pipe_fd[1], &random_str) as usize, random_str.len());
assert_eq!(
write(down_pipe_fd[1], &random_str) as usize,
random_str.len()
);
// close write end of down pipe
close(down_pipe_fd[1]);
// calculate sum(parent)
......@@ -57,13 +60,12 @@ pub fn main() -> i32 {
// check
assert_eq!(
sum,
str::parse::<usize>(
core::str::from_utf8(&child_result[..result_len]).unwrap()
).unwrap()
str::parse::<usize>(core::str::from_utf8(&child_result[..result_len]).unwrap())
.unwrap()
);
let mut _unused: i32 = 0;
wait(&mut _unused);
println!("pipe_large_test passed!");
0
}
}
\ No newline at end of file
}
......@@ -4,7 +4,7 @@
#[macro_use]
extern crate user_lib;
use user_lib::{fork, close, pipe, read, write, wait};
use user_lib::{close, fork, pipe, read, wait, write};
static STR: &str = "Hello, world!";
......@@ -41,4 +41,4 @@ pub fn main() -> i32 {
println!("pipetest passed!");
0
}
}
\ No newline at end of file
}
......@@ -4,7 +4,7 @@
#[macro_use]
extern crate user_lib;
use user_lib::{fork, exec, wait};
use user_lib::{exec, fork, wait};
#[no_mangle]
pub fn main() -> i32 {
......@@ -18,4 +18,4 @@ pub fn main() -> i32 {
}
}
0
}
\ No newline at end of file
}
......@@ -4,7 +4,7 @@
#[macro_use]
extern crate user_lib;
use user_lib::{sleep, exit, get_time, fork, waitpid};
use user_lib::{exit, fork, get_time, sleep, waitpid};
fn sleepy() {
let time: usize = 100;
......@@ -27,4 +27,4 @@ pub fn main() -> i32 {
println!("use {} msecs.", get_time() - current_time);
println!("sleep pass.");
0
}
\ No newline at end of file
}
......@@ -13,7 +13,11 @@ pub fn main() -> i32 {
println!("current time_msec = {}", start);
sleep(100);
let end = get_time();
println!("time_msec = {} after sleeping 100 ticks, delta = {}ms!", end, end - start);
println!(
"time_msec = {} after sleeping 100 ticks, delta = {}ms!",
end,
end - start
);
println!("r_sleep passed!");
0
}
\ No newline at end of file
}
......@@ -5,7 +5,7 @@
extern crate user_lib;
fn f(d: usize) {
println!("d = {}",d);
println!("d = {}", d);
f(d + 1);
}
......@@ -14,4 +14,4 @@ pub fn main() -> i32 {
println!("It should trigger segmentation fault!");
f(0);
0
}
\ No newline at end of file
}
#![no_std]
#![no_main]
extern crate user_lib;
use user_lib::exit;
/*
辅助测例,正常退出,不输出 FAIL 即可。
*/
#[allow(unreachable_code)]
#[no_mangle]
pub fn main() -> i32 {
exit(66778);
panic!("FAIL: T.T\n");
0
}
#![no_std]
#![no_main]
extern crate user_lib;
use user_lib::exit;
/*
辅助测例,正常退出,不输出 FAIL 即可。
*/
#[allow(unreachable_code)]
#[no_mangle]
pub fn main() -> i32 {
exit(-233);
panic!("FAIL: T.T\n");
0
}
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{close, open, read, write, OpenFlags};
/// 测试文件基本读写,输出 Test file0 OK! 就算正确。
#[no_mangle]
pub fn main() -> i32 {
let test_str = "Hello, world!";
let fname = "fname\0";
let fd = open(fname, OpenFlags::CREATE | OpenFlags::WRONLY);
assert!(fd > 0);
let fd = fd as usize;
write(fd, test_str.as_bytes());
close(fd);
let fd = open(fname, OpenFlags::RDONLY);
assert!(fd > 0);
let fd = fd as usize;
let mut buffer = [0u8; 100];
let read_len = read(fd, &mut buffer) as usize;
close(fd);
assert_eq!(test_str, core::str::from_utf8(&buffer[..read_len]).unwrap(),);
println!("Test file0 OK!");
0
}
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{close, fstat, open, OpenFlags, Stat, StatMode};
/// 测试 fstat,输出 Test fstat OK! 就算正确。
#[no_mangle]
pub fn main() -> i32 {
let fname = "fname1\0";
let fd = open(fname, OpenFlags::CREATE | OpenFlags::WRONLY);
assert!(fd > 0);
let fd = fd as usize;
let stat: Stat = Stat::new();
let ret = fstat(fd, &stat);
assert_eq!(ret, 0);
assert_eq!(stat.mode, StatMode::FILE);
assert_eq!(stat.nlink, 1);
close(fd);
// unlink(fname);
// It's recommended to rebuild the disk image. This program will not clean the file "fname1".
println!("Test fstat OK!");
0
}
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{close, fstat, link, open, read, unlink, write, OpenFlags, Stat};
/// 测试 link/unlink,输出 Test link OK! 就算正确。
#[no_mangle]
pub fn main() -> i32 {
let test_str = "Hello, world!";
let fname = "fname2\0";
let (lname0, lname1, lname2) = ("linkname0\0", "linkname1\0", "linkname2\0");
let fd = open(fname, OpenFlags::CREATE | OpenFlags::WRONLY) as usize;
link(fname, lname0);
let stat = Stat::new();
fstat(fd, &stat);
assert_eq!(stat.nlink, 2);
link(fname, lname1);
link(fname, lname2);
fstat(fd, &stat);
assert_eq!(stat.nlink, 4);
write(fd, test_str.as_bytes());
close(fd);
unlink(fname);
let fd = open(lname0, OpenFlags::RDONLY) as usize;
let stat2 = Stat::new();
let mut buf = [0u8; 100];
let read_len = read(fd, &mut buf) as usize;
assert_eq!(test_str, core::str::from_utf8(&buf[..read_len]).unwrap(),);
fstat(fd, &stat2);
assert_eq!(stat2.dev, stat.dev);
assert_eq!(stat2.ino, stat.ino);
assert_eq!(stat2.nlink, 3);
unlink(lname1);
unlink(lname2);
fstat(fd, &stat2);
assert_eq!(stat2.nlink, 1);
close(fd);
unlink(lname0);
// It's Ok if you don't delete the inode and data blocks.
println!("Test link OK!");
0
}
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::getpid;
/*
辅助测例 打印子进程 pid
*/
#[no_mangle]
pub fn main() -> i32 {
let pid = getpid();
println!("Test getpid OK! pid = {}", pid);
0
}
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{getpid, mail_read, mail_write};
const BUF_LEN: usize = 256;
/// 测试邮箱基本功能,输出 mail0 test OK! 就算正确。
#[no_mangle]
fn main() -> i32 {
let pid = getpid();
let buffer0 = ['a' as u8; 27];
assert_eq!(mail_write(pid as usize, &buffer0), 27);
let buffer1 = ['b' as u8; BUF_LEN + 1];
assert_eq!(mail_write(pid as usize, &buffer1), BUF_LEN as isize);
let mut buf = [0u8; BUF_LEN];
assert_eq!(mail_read(&mut buf), 27);
assert_eq!(buf[..27], buffer0);
assert_eq!(mail_read(&mut buf[..27]), 27);
assert_eq!(buf[..27], buffer1[..27]);
println!("mail0 test OK!");
0
}
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{getpid, mail_read, mail_write};
const BUF_LEN: usize = 256;
const MAIL_MAX: usize = 16;
/// 测试邮箱容量,输出 mail1 test OK! 就算正确。
#[no_mangle]
fn main() -> i32 {
let pid = getpid();
let buffer0 = ['a' as u8; BUF_LEN];
for _ in 0..MAIL_MAX {
assert_eq!(mail_write(pid as usize, &buffer0), BUF_LEN as isize);
}
assert_eq!(mail_write(pid as usize, &buffer0), -1);
let mut buf = [0u8; BUF_LEN];
assert_eq!(mail_read(&mut buf), BUF_LEN as isize);
assert_eq!(mail_write(pid as usize, &buffer0), BUF_LEN as isize);
assert_eq!(mail_write(pid as usize, &buffer0), -1);
println!("mail1 test OK!");
0
}
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{exit, fork, mail_read, mail_write, sleep, wait};
const BUF_LEN: usize = 256;
// 双进程邮箱测试,最终输出 mail2 test OK! 就算正确。
#[no_mangle]
fn main() -> i32 {
let pid = fork();
if pid == 0 {
println!("I am child");
let mut buffer = [0u8; BUF_LEN];
assert_eq!(mail_read(&mut buffer), -1);
println!("child read 1 mail fail");
println!("child sleep 2s");
sleep(2000 as usize);
for i in 0..16 {
let mut buffer = [0u8; BUF_LEN];
assert_eq!(mail_read(&mut buffer), BUF_LEN as isize);
assert_eq!(buffer, [i as u8; BUF_LEN]);
}
println!("child read 16 mails succeed");
assert_eq!(mail_read(&mut buffer), -1);
println!("child read 1 mail fail");
println!("child sleep 1s");
sleep(1000 as usize);
assert_eq!(mail_read(&mut buffer), BUF_LEN as isize);
assert_eq!(buffer, [16 as u8; BUF_LEN]);
println!("child read 1 mail succeed");
println!("child exit");
exit(0);
}
println!("I am father");
println!("father sleep 1s");
sleep(1000 as usize);
for i in 0..16 {
let buffer = [i as u8; BUF_LEN];
assert_eq!(mail_write(pid as usize, &buffer), BUF_LEN as isize);
}
println!("father wirte 16 mails succeed");
let buffer = [16 as u8; BUF_LEN];
assert_eq!(mail_write(pid as usize, &buffer), -1);
println!("father wirte 1 mail fail");
println!("father sleep 1.5s");
sleep(1500 as usize);
assert_eq!(mail_write(pid as usize, &buffer), BUF_LEN as isize);
println!("father wirte 1 mail succeed");
let mut xstate: i32 = -100;
assert!(wait(&mut xstate) > 0);
assert_eq!(xstate, 0);
println!("mail2 test OK!");
0
}
#![no_std]
#![no_main]
extern crate core;
#[macro_use]
extern crate user_lib;
use core::slice;
use user_lib::{getpid, mail_read, mail_write};
const BUF_LEN: usize = 256;
const MAIL_MAX: usize = 16;
const BAD_ADDRESS: usize = 0x90000000;
/// 邮箱错误参数测试,输出 mail3 test OK! 就算正确。
#[no_mangle]
fn main() -> i32 {
let pid = getpid();
let null = unsafe { slice::from_raw_parts(BAD_ADDRESS as *const _, 10) };
assert_eq!(mail_write(pid as usize, &null), -1);
let mut empty = ['a' as u8; 0];
assert_eq!(mail_write(pid as usize, &empty), 0);
assert_eq!(mail_read(&mut empty), -1);
let buffer0 = ['a' as u8; BUF_LEN];
for _ in 0..MAIL_MAX {
assert_eq!(mail_write(pid as usize, &buffer0), BUF_LEN as isize);
}
assert_eq!(mail_write(pid as usize, &empty), -1);
assert_eq!(mail_read(&mut empty), 0);
assert_eq!(mail_write(pid as usize, &empty), -1);
println!("mail3 test OK!");
0
}
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::mmap;
/*
理想结果:输出 Test 04_1 OK!
*/
#[no_mangle]
fn main() -> i32 {
let start: usize = 0x10000000;
let len: usize = 4096;
let prot: usize = 3;
assert_eq!(0, mmap(start, len, prot));
for i in start..(start + len) {
let addr: *mut u8 = i as *mut u8;
unsafe {
*addr = i as u8;
}
}
for i in start..(start + len) {
let addr: *mut u8 = i as *mut u8;
unsafe {
assert_eq!(*addr, i as u8);
}
}
println!("Test 04_1 OK!");
0
}
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::mmap;
/*
理想结果:程序触发访存异常,被杀死。不输出 error 就算过。
*/
#[no_mangle]
fn main() -> i32 {
let start: usize = 0x10000000;
let len: usize = 4096;
let prot: usize = 1;
assert_eq!(0, mmap(start, len, prot));
let addr: *mut u8 = start as *mut u8;
unsafe {
*addr = start as u8;
}
println!("Should cause error, Test 04_2 fail!");
0
}
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::mmap;
/*
理想结果:程序触发访存异常,被杀死。不输出 error 就算过。
*/
#[no_mangle]
fn main() -> i32 {
let start: usize = 0x10000000;
let len: usize = 4096;
let prot: usize = 2;
assert_eq!(0, mmap(start, len, prot));
let addr: *mut u8 = start as *mut u8;
unsafe {
// *addr = start as u8; // can't write, R == 0 && W == 1 is illegal in riscv
assert!(*addr != 0);
}
println!("Should cause error, Test 04_2 fail!");
0
}
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::mmap;
/*
理想结果:对于错误的 mmap 返回 -1,最终输出 Test 04_4 test OK!
*/
#[no_mangle]
fn main() -> i32 {
let start: usize = 0x10000000;
let len: usize = 4096;
let prot: usize = 3;
assert_eq!(0, mmap(start, len, prot));
assert_eq!(mmap(start - len, len + 1, prot), -1);
assert_eq!(mmap(start + len + 1, len, prot), -1);
assert_eq!(mmap(start + len, len, 0), -1);
assert_eq!(mmap(start + len, len, prot | 8), -1);
println!("Test 04_4 test OK!");
0
}
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{get_time, yield_};
/// 正确输出:(无报错信息)
/// get_time OK! {...}
/// Test sleep OK!
#[no_mangle]
fn main() -> i32 {
let current_time = get_time();
assert!(current_time > 0);
println!("get_time OK! {}", current_time);
let wait_for = current_time + 3000;
while get_time() < wait_for {
yield_();
}
println!("Test sleep OK!");
0
}
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{get_time, sleep};
#[no_mangle]
pub fn main() -> i32 {
let start = get_time();
println!("current time_msec = {}", start);
sleep(100);
let end = get_time();
println!(
"time_msec = {} after sleeping 100 ticks, delta = {}ms!",
end,
end - start
);
println!("Test sleep1 passed!");
0
}
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{spawn, wait};
const MAX_CHILD: usize = 40;
/*
理想结果:生成 MAX_CHILD 个 getpid 的子进程,全部结束后,输出 Test spawn0 OK!
*/
#[no_mangle]
pub fn main() -> i32 {
for _ in 0..MAX_CHILD {
let cpid = spawn("test_getpid\0");
assert!(cpid >= 0, "child pid invalid");
println!("new child {}", cpid);
}
let mut exit_code: i32 = 0;
for _ in 0..MAX_CHILD {
assert!(wait(&mut exit_code) > 0, "wait stopped early");
assert_eq!(exit_code, 0, "error exit ocde {}", exit_code);
}
assert!(wait(&mut exit_code) <= 0, "wait got too many");
println!("Test spawn0 OK!");
0
}
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{spawn, wait, waitpid};
/// 程序行为:先后产生 3 个有特定返回值的程序,检查 waitpid 能够获取正确返回值。
/// 理想输出:
/// new child i
/// Test wait OK!
/// Test waitpid OK!
#[no_mangle]
pub fn main() -> i32 {
let cpid = spawn("test_exit0\0");
assert!(cpid >= 0, "child pid invalid");
println!("new child {}", cpid);
let mut exit_code: i32 = 0;
let exit_pid = wait(&mut exit_code);
assert_eq!(exit_pid, cpid, "error exit pid");
assert_eq!(exit_code, 66778, "error exit code");
println!("Test wait OK!");
let (cpid0, cpid1) = (spawn("test_exit0\0"), spawn("test_exit1\0"));
let exit_pid = waitpid(cpid1 as usize, &mut exit_code);
assert_eq!(exit_pid, cpid1, "error exit pid");
assert_eq!(exit_code, -233, "error exit code");
let exit_pid = wait(&mut exit_code);
assert_eq!(exit_pid, cpid0, "error exit pid");
assert_eq!(exit_code, 66778, "error exit code");
println!("Test waitpid OK!");
0
}
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{mmap, munmap};
/*
理想结果:输出 Test 04_5 ummap OK!
*/
#[no_mangle]
fn main() -> i32 {
let start: usize = 0x10000000;
let len: usize = 4096;
let prot: usize = 3;
assert_eq!(0, mmap(start, len, prot));
assert_eq!(mmap(start + len, len * 2, prot), 0);
assert_eq!(munmap(start, len), 0);
assert_eq!(mmap(start - len, len + 1, prot), 0);
for i in (start - len)..(start + len * 3) {
let addr: *mut u8 = i as *mut u8;
unsafe {
*addr = i as u8;
}
}
for i in (start - len)..(start + len * 3) {
let addr: *mut u8 = i as *mut u8;
unsafe {
assert_eq!(*addr, i as u8);
}
}
println!("Test 04_5 ummap OK!");
0
}
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{mmap, munmap};
/*
理想结果:输出 Test 04_6 ummap2 OK!
*/
#[no_mangle]
fn main() -> i32 {
let start: usize = 0x10000000;
let len: usize = 4096;
let prot: usize = 3;
assert_eq!(0, mmap(start, len, prot));
assert_eq!(munmap(start, len + 1), -1);
assert_eq!(munmap(start + 1, len - 1), -1);
println!("Test 04_6 ummap2 OK!");
0
}
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
static TESTS: &[&str] = &[
"test_sleep\0",
"test_sleep1\0",
"test_mmap0\0",
"test_mmap1\0",
"test_mmap2\0",
"test_mmap3\0",
"test_unmap\0",
"test_unmap2\0",
"test_spawn0\0",
"test_spawn1\0",
"test_mail0\0",
"test_mail1\0",
"test_mail2\0",
"test_mail3\0",
];
use user_lib::{exec, fork, waitpid};
/// 辅助测例,运行所有其他测例。
#[no_mangle]
pub fn main() -> i32 {
for test in TESTS {
println!("Usertests: Running {}", test);
let pid = fork();
if pid == 0 {
exec(*test);
panic!("unreachable!");
} else {
let mut exit_code: i32 = Default::default();
let wait_pid = waitpid(pid as usize, &mut exit_code);
assert_eq!(pid, wait_pid);
println!(
"\x1b[32mUsertests: Test {} in Process {} exited with code {}\x1b[0m",
test, pid, exit_code
);
}
}
println!("ch6 Usertests passed!");
0
}
#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
use user_lib::{write, STDOUT};
const DATA_STRING: &str = "string from data section\n";
/// 正确输出:
/// string from data section
/// strinstring from stack section
/// strin
/// Test write1 OK!
#[no_mangle]
pub fn main() -> i32 {
assert_eq!(write(1234, DATA_STRING.as_bytes()), -1);
assert_eq!(
write(STDOUT, DATA_STRING.as_bytes()),
DATA_STRING.len() as isize
);
assert_eq!(write(STDOUT, &DATA_STRING.as_bytes()[..5]), 5);
let stack_string = "string from stack section\n";
assert_eq!(
write(STDOUT, stack_string.as_bytes()),
stack_string.len() as isize
);
assert_eq!(write(STDOUT, &stack_string.as_bytes()[..5]), 5);
println!("\nTest write1 OK!");
0
}
......@@ -12,19 +12,22 @@ const DL: u8 = 0x7fu8;
const BS: u8 = 0x08u8;
use alloc::string::String;
use user_lib::{fork, exec, waitpid};
use user_lib::console::getchar;
use user_lib::{exec, flush, fork, waitpid};
// 利用 pipe 机制为 Shell 实现管道运算符 '|'
#[no_mangle]
pub fn main() -> i32 {
println!("Rust user shell");
let mut line: String = String::new();
print!(">> ");
flush();
loop {
let c = getchar();
match c {
LF | CR => {
println!("");
println!();
if !line.is_empty() {
line.push('\0');
let pid = fork();
......@@ -44,19 +47,22 @@ pub fn main() -> i32 {
line.clear();
}
print!(">> ");
flush();
}
BS | DL => {
if !line.is_empty() {
print!("{}", BS as char);
print!(" ");
print!("{}", BS as char);
flush();
line.pop();
}
}
_ => {
print!("{}", c as char);
flush();
line.push(c as char);
}
}
}
}
\ No newline at end of file
}
......@@ -8,14 +8,18 @@ static TESTS: &[&str] = &[
"exit\0",
"fantastic_text\0",
"forktest\0",
"forktest2\0",
"forktest_simple\0",
"hello_world\0",
"matrix\0",
"sleep\0",
"sleep_simple\0",
"stack_overflow\0",
"yield\0",
"pipetest\0",
// 正确实现 sys_get_time 后这些程序才能运行
// "pipe_large_test\0",
// "forktest2\0",
// "sleep\0",
// "sleep_simple\0",
// "forktree\0",
];
use user_lib::{exec, fork, waitpid};
......@@ -32,9 +36,12 @@ pub fn main() -> i32 {
let mut exit_code: i32 = Default::default();
let wait_pid = waitpid(pid as usize, &mut exit_code);
assert_eq!(pid, wait_pid);
println!("\x1b[32mUsertests: Test {} in Process {} exited with code {}\x1b[0m", test, pid, exit_code);
println!(
"\x1b[32mUsertests: Test {} in Process {} exited with code {}\x1b[0m",
test, pid, exit_code
);
}
}
println!("Usertests passed!");
0
}
\ No newline at end of file
}
......@@ -14,4 +14,4 @@ pub fn main() -> i32 {
}
println!("yield pass.");
0
}
\ No newline at end of file
}
use alloc::collections::vec_deque::VecDeque;
use alloc::sync::Arc;
use core::fmt::{self, Write};
use spin::mutex::Mutex;
const STDIN: usize = 0;
const STDOUT: usize = 1;
pub const STDIN: usize = 0;
pub const STDOUT: usize = 1;
const CONSOLE_BUFFER_SIZE: usize = 256 * 10;
use super::{read, write};
use lazy_static::*;
struct ConsoleBuffer(VecDeque<u8>);
lazy_static! {
static ref CONSOLE_BUFFER: Arc<Mutex<ConsoleBuffer>> = {
let buffer = VecDeque::<u8>::with_capacity(CONSOLE_BUFFER_SIZE);
Arc::new(Mutex::new(ConsoleBuffer(buffer)))
};
}
struct Stdout;
impl ConsoleBuffer {
fn flush(&mut self) -> isize {
let s: &[u8] = self.0.make_contiguous();
let ret = write(STDOUT, s);
self.0.clear();
ret
}
}
impl Write for Stdout {
impl Write for ConsoleBuffer {
fn write_str(&mut self, s: &str) -> fmt::Result {
write(STDOUT, s.as_bytes());
for c in s.as_bytes().iter() {
self.0.push_back(*c);
if (*c == b'\n' || self.0.len() == CONSOLE_BUFFER_SIZE) && -1 == self.flush() {
return Err(fmt::Error);
}
}
Ok(())
}
}
#[allow(unused)]
pub fn print(args: fmt::Arguments) {
Stdout.write_fmt(args).unwrap();
let mut buf = CONSOLE_BUFFER.lock();
// buf.write_fmt(args).unwrap();
// BUG FIX: 关闭 stdout 后,本函数不能触发 panic,否则会造成死锁
buf.write_fmt(args);
}
#[macro_export]
......@@ -27,6 +58,9 @@ macro_rules! print {
#[macro_export]
macro_rules! println {
() => {
$crate::console::print(format_args!("\n"));
};
($fmt: literal $(, $($arg: tt)+)?) => {
$crate::console::print(format_args!(concat!($fmt, "\n") $(, $($arg)+)?));
}
......@@ -37,3 +71,8 @@ pub fn getchar() -> u8 {
read(STDIN, &mut c);
c[0]
}
pub fn flush() {
let mut buf = CONSOLE_BUFFER.lock();
buf.flush();
}
......@@ -4,9 +4,14 @@ use super::exit;
fn panic_handler(panic_info: &core::panic::PanicInfo) -> ! {
let err = panic_info.message().unwrap();
if let Some(location) = panic_info.location() {
println!("Panicked at {}:{}, {}", location.file(), location.line(), err);
println!(
"Panicked at {}:{}, {}",
location.file(),
location.line(),
err
);
} else {
println!("Panicked: {}", err);
}
exit(-1);
}
\ No newline at end of file
}
......@@ -6,13 +6,17 @@
#[macro_use]
pub mod console;
mod syscall;
mod lang_items;
mod syscall;
extern crate alloc;
extern crate core;
#[macro_use]
extern crate bitflags;
use syscall::*;
use buddy_system_allocator::LockedHeap;
pub use console::{flush, STDIN, STDOUT};
pub use syscall::*;
const USER_HEAP_SIZE: usize = 16384;
......@@ -42,22 +46,155 @@ fn main() -> i32 {
panic!("Cannot find main!");
}
pub fn close(fd: usize) -> isize { sys_close(fd) }
pub fn pipe(pipe_fd: &mut [usize]) -> isize { sys_pipe(pipe_fd) }
pub fn read(fd: usize, buf: &mut [u8]) -> isize { sys_read(fd, buf) }
pub fn write(fd: usize, buf: &[u8]) -> isize { sys_write(fd, buf) }
pub fn exit(exit_code: i32) -> ! { sys_exit(exit_code); }
pub fn yield_() -> isize { sys_yield() }
pub fn get_time() -> isize { sys_get_time() }
pub fn getpid() -> isize { sys_getpid() }
pub fn fork() -> isize { sys_fork() }
pub fn exec(path: &str) -> isize { sys_exec(path) }
bitflags! {
pub struct OpenFlags: u32 {
const RDONLY = 0;
const WRONLY = 1 << 0;
const RDWR = 1 << 1;
const CREATE = 1 << 9;
const TRUNC = 1 << 10;
}
}
#[repr(C)]
#[derive(Debug, Default)]
pub struct TimeVal {
pub sec: usize,
pub usec: usize,
}
impl TimeVal {
pub fn new() -> Self {
Self::default()
}
}
#[repr(C)]
#[derive(Debug)]
pub struct Stat {
/// ID of device containing file
pub dev: u64,
/// inode number
pub ino: u64,
/// file type and mode
pub mode: StatMode,
/// number of hard links
pub nlink: u32,
/// unused pad
pad: [u64; 7],
}
impl Stat {
pub fn new() -> Self {
Stat {
dev: 0,
ino: 0,
mode: StatMode::NULL,
nlink: 0,
pad: [0; 7],
}
}
}
impl Default for Stat {
fn default() -> Self {
Self::new()
}
}
bitflags! {
pub struct StatMode: u32 {
const NULL = 0;
/// directory
const DIR = 0o040000;
/// ordinary regular file
const FILE = 0o100000;
}
}
const AT_FDCWD: isize = -100;
pub fn open(path: &str, flags: OpenFlags) -> isize {
sys_openat(AT_FDCWD as usize, path, flags.bits, OpenFlags::RDWR.bits)
}
pub fn close(fd: usize) -> isize {
if fd == STDOUT {
console::flush();
}
sys_close(fd)
}
pub fn read(fd: usize, buf: &mut [u8]) -> isize {
sys_read(fd, buf)
}
pub fn write(fd: usize, buf: &[u8]) -> isize {
sys_write(fd, buf)
}
pub fn link(old_path: &str, new_path: &str) -> isize {
sys_linkat(AT_FDCWD as usize, old_path, AT_FDCWD as usize, new_path, 0)
}
pub fn unlink(path: &str) -> isize {
sys_unlinkat(AT_FDCWD as usize, path, 0)
}
pub fn fstat(fd: usize, st: &Stat) -> isize {
sys_fstat(fd, st)
}
pub fn mail_read(buf: &mut [u8]) -> isize {
sys_mail_read(buf)
}
pub fn mail_write(pid: usize, buf: &[u8]) -> isize {
sys_mail_write(pid, buf)
}
pub fn exit(exit_code: i32) -> ! {
console::flush();
sys_exit(exit_code);
}
pub fn yield_() -> isize {
sys_yield()
}
pub fn get_time() -> isize {
let time = TimeVal::new();
match sys_get_time(&time, 0) {
0 => ((time.sec & 0xffff) * 1000 + time.usec / 1000) as isize,
_ => -1,
}
}
pub fn getpid() -> isize {
sys_getpid()
}
pub fn fork() -> isize {
sys_fork()
}
pub fn exec(path: &str) -> isize {
sys_exec(path)
}
pub fn set_priority(prio: isize) -> isize {
sys_set_priority(prio)
}
pub fn wait(exit_code: &mut i32) -> isize {
loop {
match sys_waitpid(-1, exit_code as *mut _) {
-2 => { yield_(); }
// -1 or a real pid
exit_pid => return exit_pid,
-2 => {
sys_yield();
}
n => {
return n;
}
}
}
}
......@@ -65,15 +202,38 @@ pub fn wait(exit_code: &mut i32) -> isize {
pub fn waitpid(pid: usize, exit_code: &mut i32) -> isize {
loop {
match sys_waitpid(pid as isize, exit_code as *mut _) {
-2 => { yield_(); }
// -1 or a real pid
exit_pid => return exit_pid,
-2 => {
sys_yield();
}
n => {
return n;
}
}
}
}
pub fn sleep(period_ms: usize) {
let start = sys_get_time();
while sys_get_time() < start + period_ms as isize {
let start = get_time();
while get_time() < start + period_ms as isize {
sys_yield();
}
}
\ No newline at end of file
}
pub fn mmap(start: usize, len: usize, prot: usize) -> isize {
sys_mmap(start, len, prot)
}
pub fn munmap(start: usize, len: usize) -> isize {
sys_munmap(start, len)
}
pub fn spawn(path: &str) -> isize {
sys_spawn(path)
}
pub fn dup(fd: usize) -> isize {
sys_dup(fd)
}
pub fn pipe(pipe_fd: &mut [usize]) -> isize {
sys_pipe(pipe_fd)
}
const SYSCALL_CLOSE: usize = 57;
const SYSCALL_PIPE: usize = 59;
const SYSCALL_READ: usize = 63;
const SYSCALL_WRITE: usize = 64;
const SYSCALL_EXIT: usize = 93;
const SYSCALL_YIELD: usize = 124;
const SYSCALL_GET_TIME: usize = 169;
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 {
use super::{Stat, TimeVal};
pub const SYSCALL_OPENAT: usize = 56;
pub const SYSCALL_CLOSE: usize = 57;
pub const SYSCALL_READ: usize = 63;
pub const SYSCALL_WRITE: usize = 64;
pub const SYSCALL_UNLINKAT: usize = 35;
pub const SYSCALL_LINKAT: usize = 37;
pub const SYSCALL_FSTAT: usize = 80;
pub const SYSCALL_EXIT: usize = 93;
pub const SYSCALL_YIELD: usize = 124;
pub const SYSCALL_GETTIMEOFDAY: usize = 169;
pub const SYSCALL_GETPID: usize = 172;
pub const SYSCALL_FORK: usize = 220;
pub const SYSCALL_EXEC: usize = 221;
pub const SYSCALL_WAITPID: usize = 260;
pub const SYSCALL_SET_PRIORITY: usize = 140;
pub const SYSCALL_MUNMAP: usize = 215;
pub const SYSCALL_MMAP: usize = 222;
pub const SYSCALL_SPAWN: usize = 400;
pub const SYSCALL_MAIL_READ: usize = 401;
pub const SYSCALL_MAIL_WRITE: usize = 402;
pub const SYSCALL_DUP: usize = 24;
pub const SYSCALL_PIPE: usize = 59;
pub fn syscall(id: usize, args: [usize; 3]) -> isize {
let mut ret: isize;
unsafe {
asm!(
......@@ -24,22 +37,93 @@ fn syscall(id: usize, args: [usize; 3]) -> isize {
ret
}
pub fn sys_close(fd: usize) -> isize {
syscall(SYSCALL_CLOSE, [fd, 0, 0])
pub fn syscall6(id: usize, args: [usize; 6]) -> isize {
let mut ret: isize;
unsafe {
asm!("ecall",
inlateout("x10") args[0] => ret,
in("x11") args[1],
in("x12") args[2],
in("x13") args[3],
in("x14") args[4],
in("x15") args[5],
in("x17") id
);
}
ret
}
pub fn sys_pipe(pipe: &mut [usize]) -> isize {
syscall(SYSCALL_PIPE, [pipe.as_mut_ptr() as usize, 0, 0])
pub fn sys_openat(dirfd: usize, path: &str, flags: u32, mode: u32) -> isize {
syscall6(
SYSCALL_OPENAT,
[
dirfd,
path.as_ptr() as usize,
flags as usize,
mode as usize,
0,
0,
],
)
}
pub fn sys_close(fd: usize) -> isize {
syscall(SYSCALL_CLOSE, [fd, 0, 0])
}
pub fn sys_read(fd: usize, buffer: &mut [u8]) -> isize {
syscall(SYSCALL_READ, [fd, buffer.as_mut_ptr() as usize, buffer.len()])
syscall(
SYSCALL_READ,
[fd, buffer.as_mut_ptr() as usize, buffer.len()],
)
}
pub fn sys_write(fd: usize, buffer: &[u8]) -> isize {
syscall(SYSCALL_WRITE, [fd, buffer.as_ptr() as usize, buffer.len()])
}
pub fn sys_linkat(
old_dirfd: usize,
old_path: &str,
new_dirfd: usize,
new_path: &str,
flags: usize,
) -> isize {
syscall6(
SYSCALL_LINKAT,
[
old_dirfd,
old_path.as_ptr() as usize,
new_dirfd,
new_path.as_ptr() as usize,
flags,
0,
],
)
}
pub fn sys_unlinkat(dirfd: usize, path: &str, flags: usize) -> isize {
syscall(SYSCALL_UNLINKAT, [dirfd, path.as_ptr() as usize, flags])
}
pub fn sys_fstat(fd: usize, st: &Stat) -> isize {
syscall(SYSCALL_FSTAT, [fd, st as *const _ as usize, 0])
}
pub fn sys_mail_read(buffer: &mut [u8]) -> isize {
syscall(
SYSCALL_MAIL_READ,
[buffer.as_ptr() as usize, buffer.len(), 0],
)
}
pub fn sys_mail_write(pid: usize, buffer: &[u8]) -> isize {
syscall(
SYSCALL_MAIL_WRITE,
[pid, buffer.as_ptr() as usize, buffer.len()],
)
}
pub fn sys_exit(exit_code: i32) -> ! {
syscall(SYSCALL_EXIT, [exit_code as usize, 0, 0]);
panic!("sys_exit never returns!");
......@@ -49,8 +133,8 @@ pub fn sys_yield() -> isize {
syscall(SYSCALL_YIELD, [0, 0, 0])
}
pub fn sys_get_time() -> isize {
syscall(SYSCALL_GET_TIME, [0, 0, 0])
pub fn sys_get_time(time: &TimeVal, tz: usize) -> isize {
syscall(SYSCALL_GETTIMEOFDAY, [time as *const _ as usize, tz, 0])
}
pub fn sys_getpid() -> isize {
......@@ -65,6 +149,30 @@ 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])
}
\ No newline at end of file
pub fn sys_waitpid(pid: isize, xstatus: *mut i32) -> isize {
syscall(SYSCALL_WAITPID, [pid as usize, xstatus as usize, 0])
}
pub fn sys_set_priority(prio: isize) -> isize {
syscall(SYSCALL_SET_PRIORITY, [prio as usize, 0, 0])
}
pub fn sys_mmap(start: usize, len: usize, prot: usize) -> isize {
syscall(SYSCALL_MMAP, [start, len, prot])
}
pub fn sys_munmap(start: usize, len: usize) -> isize {
syscall(SYSCALL_MUNMAP, [start, len, 0])
}
pub fn sys_spawn(path: &str) -> isize {
syscall(SYSCALL_SPAWN, [path.as_ptr() as usize, 0, 0])
}
pub fn sys_dup(fd: usize) -> isize {
syscall(SYSCALL_DUP, [fd, 0, 0])
}
pub fn sys_pipe(pipe: &mut [usize]) -> isize {
syscall(SYSCALL_PIPE, [pipe.as_mut_ptr() as usize, 0, 0])
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册