From d7fb49e14052c69a5ae8100d37d107acde1cfdbb Mon Sep 17 00:00:00 2001 From: buhe Date: Thu, 18 Nov 2021 10:57:27 +0800 Subject: [PATCH] pipe implement --- ...222\255 4 \351\251\261\345\212\250 LCD.md" | 2 +- os/src/fs/mod.rs | 11 ++ os/src/fs/pipe.rs | 165 ++++++++++++++++++ os/src/fs/stdio.rs | 43 +++++ os/src/link_app.S | 34 +++- os/src/main.rs | 1 + os/src/mmu/memory_set.rs | 1 - os/src/mmu/mod.rs | 2 + os/src/mmu/user_buffer.rs | 54 ++++++ os/src/scall_sbi/fs.rs | 95 ++++++---- os/src/scall_sbi/mod.rs | 6 +- os/src/task/task.rs | 30 ++++ user/src/bin/pipe_large_test.rs | 69 ++++++++ user/src/bin/pipetest.rs | 44 +++++ user/src/lib.rs | 2 + user/src/scall_os.rs | 10 ++ 16 files changed, 522 insertions(+), 47 deletions(-) create mode 100644 os/src/fs/mod.rs create mode 100644 os/src/fs/pipe.rs create mode 100644 os/src/fs/stdio.rs create mode 100644 os/src/mmu/user_buffer.rs create mode 100644 user/src/bin/pipe_large_test.rs create mode 100644 user/src/bin/pipetest.rs diff --git "a/docs/\346\217\222\346\222\255 4 \351\251\261\345\212\250 LCD.md" "b/docs/\346\217\222\346\222\255 4 \351\251\261\345\212\250 LCD.md" index eb9f1bd..5b2b639 100644 --- "a/docs/\346\217\222\346\222\255 4 \351\251\261\345\212\250 LCD.md" +++ "b/docs/\346\217\222\346\222\255 4 \351\251\261\345\212\250 LCD.md" @@ -52,5 +52,5 @@ pub trait LCDHL { } ``` -LCD 是结构体,定义了 gpiohs +LCD 用的是 SPI 总线, diff --git a/os/src/fs/mod.rs b/os/src/fs/mod.rs new file mode 100644 index 0000000..73a8d66 --- /dev/null +++ b/os/src/fs/mod.rs @@ -0,0 +1,11 @@ +mod pipe; +mod stdio; + +use crate::mmu::UserBuffer; +pub trait File : Send + Sync { + fn read(&self, buf: UserBuffer) -> usize; + fn write(&self, buf: UserBuffer) -> usize; +} + +pub use pipe::{Pipe, make_pipe}; +pub use stdio::{Stdin, Stdout}; \ No newline at end of file diff --git a/os/src/fs/pipe.rs b/os/src/fs/pipe.rs new file mode 100644 index 0000000..86518ce --- /dev/null +++ b/os/src/fs/pipe.rs @@ -0,0 +1,165 @@ +use super::File; +use alloc::sync::{Arc, Weak}; +use spin::Mutex; +use crate::mmu::{ + UserBuffer, +}; +use crate::task::suspend_current_and_run_next; + +pub struct Pipe { + readable: bool, + writable: bool, + buffer: Arc>, +} + +impl Pipe { + pub fn read_end_with_buffer(buffer: Arc>) -> Self { + Self { + readable: true, + writable: false, + buffer, + } + } + pub fn write_end_with_buffer(buffer: Arc>) -> Self { + Self { + readable: false, + writable: true, + buffer, + } + } +} + +const RING_BUFFER_SIZE: usize = 32; + +#[derive(Copy, Clone, PartialEq)] +enum RingBufferStatus { + FULL, + EMPTY, + NORMAL, +} + +pub struct PipeRingBuffer { + arr: [u8; RING_BUFFER_SIZE], + head: usize, + tail: usize, + status: RingBufferStatus, + write_end: Option>, +} + +impl PipeRingBuffer { + pub fn new() -> Self { + Self { + arr: [0; RING_BUFFER_SIZE], + head: 0, + tail: 0, + status: RingBufferStatus::EMPTY, + write_end: None, + } + } + pub fn set_write_end(&mut self, write_end: &Arc) { + self.write_end = Some(Arc::downgrade(write_end)); + } + pub fn write_byte(&mut self, byte: u8) { + self.status = RingBufferStatus::NORMAL; + self.arr[self.tail] = byte; + self.tail = (self.tail + 1) % RING_BUFFER_SIZE; + if self.tail == self.head { + self.status = RingBufferStatus::FULL; + } + } + pub fn read_byte(&mut self) -> u8 { + self.status = RingBufferStatus::NORMAL; + let c = self.arr[self.head]; + self.head = (self.head + 1) % RING_BUFFER_SIZE; + if self.head == self.tail { + self.status = RingBufferStatus::EMPTY; + } + c + } + pub fn available_read(&self) -> usize { + if self.status == RingBufferStatus::EMPTY { + 0 + } else { + if self.tail > self.head { + self.tail - self.head + } else { + self.tail + RING_BUFFER_SIZE - self.head + } + } + } + pub fn available_write(&self) -> usize { + if self.status == RingBufferStatus::FULL { + 0 + } else { + RING_BUFFER_SIZE - self.available_read() + } + } + pub fn all_write_ends_closed(&self) -> bool { + self.write_end.as_ref().unwrap().upgrade().is_none() + } +} + +/// Return (read_end, write_end) +pub fn make_pipe() -> (Arc, Arc) { + let buffer = Arc::new(Mutex::new(PipeRingBuffer::new())); + let read_end = Arc::new( + Pipe::read_end_with_buffer(buffer.clone()) + ); + let write_end = Arc::new( + Pipe::write_end_with_buffer(buffer.clone()) + ); + buffer.lock().set_write_end(&write_end); + (read_end, write_end) +} + +impl File for Pipe { + fn read(&self, buf: UserBuffer) -> usize { + assert_eq!(self.readable, true); + let mut buf_iter = buf.into_iter(); + let mut read_size = 0usize; + loop { + let mut ring_buffer = self.buffer.lock(); + let loop_read = ring_buffer.available_read(); + if loop_read == 0 { + if ring_buffer.all_write_ends_closed() { + return read_size; + } + drop(ring_buffer); + suspend_current_and_run_next(); + continue; + } + // read at most loop_read bytes + for _ in 0..loop_read { + if let Some(byte_ref) = buf_iter.next() { + unsafe { *byte_ref = ring_buffer.read_byte(); } + read_size += 1; + } else { + return read_size; + } + } + } + } + fn write(&self, buf: UserBuffer) -> usize { + assert_eq!(self.writable, true); + let mut buf_iter = buf.into_iter(); + let mut write_size = 0usize; + loop { + let mut ring_buffer = self.buffer.lock(); + let loop_write = ring_buffer.available_write(); + if loop_write == 0 { + drop(ring_buffer); + suspend_current_and_run_next(); + continue; + } + // write at most loop_write bytes + for _ in 0..loop_write { + if let Some(byte_ref) = buf_iter.next() { + ring_buffer.write_byte(unsafe { *byte_ref }); + write_size += 1; + } else { + return write_size; + } + } + } + } +} \ No newline at end of file diff --git a/os/src/fs/stdio.rs b/os/src/fs/stdio.rs new file mode 100644 index 0000000..001fa2f --- /dev/null +++ b/os/src/fs/stdio.rs @@ -0,0 +1,43 @@ +use super::File; +use crate::mmu::{UserBuffer}; +use crate::scall_sbi::console_getchar; +use crate::task::suspend_current_and_run_next; + +pub struct Stdin; + +pub struct Stdout; + +impl File for Stdin { + fn read(&self, mut user_buf: UserBuffer) -> usize { + assert_eq!(user_buf.len(), 1); + // busy loop + let mut c: usize; + loop { + c = console_getchar(); + if c == 0 { + suspend_current_and_run_next(); + continue; + } else { + break; + } + } + let ch = c as u8; + unsafe { user_buf.buffers[0].as_mut_ptr().write_volatile(ch); } + 1 + } + fn write(&self, _user_buf: UserBuffer) -> usize { + panic!("Cannot write to stdin!"); + } +} + +impl File for Stdout { + fn read(&self, _user_buf: UserBuffer) -> usize{ + panic!("Cannot read from stdout!"); + } + fn write(&self, user_buf: UserBuffer) -> usize { + for buffer in user_buf.buffers.iter() { + print!("{}", core::str::from_utf8(*buffer).unwrap()); + } + user_buf.len() + } +} \ No newline at end of file diff --git a/os/src/link_app.S b/os/src/link_app.S index dde74c1..cef95de 100644 --- a/os/src/link_app.S +++ b/os/src/link_app.S @@ -3,7 +3,7 @@ .section .data .global _num_app _num_app: - .quad 8 + .quad 10 .quad app_0_start .quad app_1_start .quad app_2_start @@ -12,13 +12,17 @@ _num_app: .quad app_5_start .quad app_6_start .quad app_7_start - .quad app_7_end + .quad app_8_start + .quad app_9_start + .quad app_9_end .global _app_names _app_names: .string "forktest" .string "hello" .string "initproc" + .string "pipe_large_test" + .string "pipetest" .string "power_3" .string "power_5" .string "power_7" @@ -54,7 +58,7 @@ app_2_end: .global app_3_end .align 3 app_3_start: - .incbin "../user/target/riscv64gc-unknown-none-elf/release/power_3" + .incbin "../user/target/riscv64gc-unknown-none-elf/release/pipe_large_test" app_3_end: .section .data @@ -62,7 +66,7 @@ app_3_end: .global app_4_end .align 3 app_4_start: - .incbin "../user/target/riscv64gc-unknown-none-elf/release/power_5" + .incbin "../user/target/riscv64gc-unknown-none-elf/release/pipetest" app_4_end: .section .data @@ -70,7 +74,7 @@ app_4_end: .global app_5_end .align 3 app_5_start: - .incbin "../user/target/riscv64gc-unknown-none-elf/release/power_7" + .incbin "../user/target/riscv64gc-unknown-none-elf/release/power_3" app_5_end: .section .data @@ -78,7 +82,7 @@ app_5_end: .global app_6_end .align 3 app_6_start: - .incbin "../user/target/riscv64gc-unknown-none-elf/release/sleep" + .incbin "../user/target/riscv64gc-unknown-none-elf/release/power_5" app_6_end: .section .data @@ -86,5 +90,21 @@ app_6_end: .global app_7_end .align 3 app_7_start: - .incbin "../user/target/riscv64gc-unknown-none-elf/release/user_shell" + .incbin "../user/target/riscv64gc-unknown-none-elf/release/power_7" app_7_end: + + .section .data + .global app_8_start + .global app_8_end + .align 3 +app_8_start: + .incbin "../user/target/riscv64gc-unknown-none-elf/release/sleep" +app_8_end: + + .section .data + .global app_9_start + .global app_9_end + .align 3 +app_9_start: + .incbin "../user/target/riscv64gc-unknown-none-elf/release/user_shell" +app_9_end: diff --git a/os/src/main.rs b/os/src/main.rs index ce4eef5..7d129a4 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -28,6 +28,7 @@ mod scall_sbi; mod task; mod timer; mod trap; +mod fs; // use k210_soc::sysctl::{self, clock}; diff --git a/os/src/mmu/memory_set.rs b/os/src/mmu/memory_set.rs index 94e102a..a86f5bb 100644 --- a/os/src/mmu/memory_set.rs +++ b/os/src/mmu/memory_set.rs @@ -277,7 +277,6 @@ impl MemorySet { .find(|(_, area)| area.vpn_range.get_start() == start_vpn) { area.unmap(&mut self.page_table); - println!("m area len is {}", self.areas.len()); self.areas.remove(idx); } } diff --git a/os/src/mmu/mod.rs b/os/src/mmu/mod.rs index 45ffb12..b858127 100644 --- a/os/src/mmu/mod.rs +++ b/os/src/mmu/mod.rs @@ -2,6 +2,7 @@ mod address; mod frame_allocator; mod memory_set; mod page_table; +mod user_buffer; pub use address::{PhysAddr, PhysPageNum, VirtAddr, VirtPageNum}; use address::{StepByOne, VPNRange}; @@ -9,6 +10,7 @@ pub use frame_allocator::{frame_alloc, FrameTracker}; pub use memory_set::{MapPermission, MemorySet, KERNEL_SPACE}; pub use page_table::{translated_byte_buffer, translated_refmut, translated_str, PageTableEntry}; use page_table::{PTEFlags, PageTable}; +pub use user_buffer::UserBuffer; pub fn init() { // 启动分页器 diff --git a/os/src/mmu/user_buffer.rs b/os/src/mmu/user_buffer.rs new file mode 100644 index 0000000..f565414 --- /dev/null +++ b/os/src/mmu/user_buffer.rs @@ -0,0 +1,54 @@ +use alloc::vec::Vec; + +pub struct UserBuffer { + pub buffers: Vec<&'static mut [u8]>, +} + +impl UserBuffer { + pub fn new(buffers: Vec<&'static mut [u8]>) -> Self { + Self { buffers } + } + pub fn len(&self) -> usize { + let mut total: usize = 0; + for b in self.buffers.iter() { + total += b.len(); + } + total + } +} + +impl IntoIterator for UserBuffer { + type Item = *mut u8; + type IntoIter = UserBufferIterator; + fn into_iter(self) -> Self::IntoIter { + UserBufferIterator { + buffers: self.buffers, + current_buffer: 0, + current_idx: 0, + } + } +} + +pub struct UserBufferIterator { + buffers: Vec<&'static mut [u8]>, + current_buffer: usize, + current_idx: usize, +} + +impl Iterator for UserBufferIterator { + type Item = *mut u8; + fn next(&mut self) -> Option { + if self.current_buffer >= self.buffers.len() { + None + } else { + let r = &mut self.buffers[self.current_buffer][self.current_idx] as *mut _; + if self.current_idx + 1 == self.buffers[self.current_buffer].len() { + self.current_idx = 0; + self.current_buffer += 1; + } else { + self.current_idx += 1; + } + Some(r) + } + } +} \ No newline at end of file diff --git a/os/src/scall_sbi/fs.rs b/os/src/scall_sbi/fs.rs index efe6936..7d0b00b 100644 --- a/os/src/scall_sbi/fs.rs +++ b/os/src/scall_sbi/fs.rs @@ -1,46 +1,67 @@ -use crate::{mmu::translated_byte_buffer, scall_sbi::console_getchar, task::{current_user_token, suspend_current_and_run_next}}; +use crate::{fs::make_pipe, mmu::{UserBuffer, translated_byte_buffer, translated_refmut}, task::{current_task, current_user_token}}; -const FD_STDIN: usize = 0; -const FD_STDOUT: usize = 1; pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize { - match fd { - FD_STDOUT => { - // 改为使用虚拟内存 - let buffers = translated_byte_buffer(current_user_token(), buf, len); - for buffer in buffers { - // 使用宏 - print!("{}", core::str::from_utf8(buffer).unwrap()); - } - len as isize - } - _ => { - panic!("Unsupported fd in sys_write!"); - } + let token = current_user_token(); + let task = current_task().unwrap(); + let inner = task.acquire_inner_lock(); + if fd >= inner.fd_table.len() { + return -1; + } + if let Some(file) = &inner.fd_table[fd] { + let file = file.clone(); + // release Task lock manually to avoid deadlock + drop(inner); + file.write( + UserBuffer::new(translated_byte_buffer(token, buf, len)) + ) as isize + } else { + -1 } } pub fn sys_read(fd: usize, buf: *const u8, len: usize) -> isize { - match fd { - FD_STDIN => { - assert_eq!(len, 1, "Only support len = 1 in sys_read!"); - let mut c: usize; - loop { - c = console_getchar(); - if c == 0 { - suspend_current_and_run_next(); - continue; - } else { - break; - } - } - let ch = c as u8; - let mut buffers = translated_byte_buffer(current_user_token(), buf, len); - unsafe { buffers[0].as_mut_ptr().write_volatile(ch); } - 1 - } - _ => { - panic!("Unsupported fd in sys_read!"); - } + let token = current_user_token(); + let task = current_task().unwrap(); + let inner = task.acquire_inner_lock(); + if fd >= inner.fd_table.len() { + return -1; + } + if let Some(file) = &inner.fd_table[fd] { + let file = file.clone(); + // release Task lock manually to avoid deadlock + drop(inner); + file.read( + UserBuffer::new(translated_byte_buffer(token, buf, len)) + ) as isize + } else { + -1 + } +} + +pub fn sys_close(fd: usize) -> isize { + let task = current_task().unwrap(); + let mut inner = task.acquire_inner_lock(); + if fd >= inner.fd_table.len() { + return -1; + } + if inner.fd_table[fd].is_none() { + return -1; } + inner.fd_table[fd].take(); + 0 +} + +pub fn sys_pipe(pipe: *mut usize) -> isize { + let task = current_task().unwrap(); + let token = current_user_token(); + let mut inner = task.acquire_inner_lock(); + let (pipe_read, pipe_write) = make_pipe(); + let read_fd = inner.alloc_fd(); + inner.fd_table[read_fd] = Some(pipe_read); + let write_fd = inner.alloc_fd(); + inner.fd_table[write_fd] = Some(pipe_write); + *translated_refmut(token, pipe) = read_fd; + *translated_refmut(token, unsafe { pipe.add(1) }) = write_fd; + 0 } \ No newline at end of file diff --git a/os/src/scall_sbi/mod.rs b/os/src/scall_sbi/mod.rs index 905597e..3b5c68e 100644 --- a/os/src/scall_sbi/mod.rs +++ b/os/src/scall_sbi/mod.rs @@ -6,6 +6,8 @@ mod process; use fs::*; use process::*; +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; @@ -19,7 +21,9 @@ const SYSCALL_WAITPID: usize = 260; // 处理来自 apps 的 trap pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { match syscall_id { - SYSCALL_READ => sys_read(args[0], args[1] as *const u8, args[2]), + SYSCALL_CLOSE => sys_close(args[0]), + SYSCALL_PIPE => sys_pipe(args[0] as *mut usize), + SYSCALL_READ => sys_read(args[0], args[1] as *const u8, args[2]), 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(), diff --git a/os/src/task/task.rs b/os/src/task/task.rs index 55b2a6d..883ac4f 100644 --- a/os/src/task/task.rs +++ b/os/src/task/task.rs @@ -4,8 +4,10 @@ use crate::config::TRAP_CONTEXT; use crate::mmu::{MemorySet, PhysPageNum, VirtAddr, KERNEL_SPACE}; use crate::trap::{trap_handler, TrapContext}; use alloc::sync::{Arc, Weak}; +use alloc::vec; use alloc::vec::Vec; use spin::{Mutex, MutexGuard}; +use crate::fs::{File, Stdin, Stdout}; pub struct TaskControlBlock { // immutable @@ -24,6 +26,7 @@ pub struct TaskControlBlockInner { pub parent: Option>, pub children: Vec>, pub exit_code: i32, + pub fd_table: Vec>>, } impl TaskControlBlockInner { @@ -42,6 +45,15 @@ impl TaskControlBlockInner { pub fn is_zombie(&self) -> bool { self.get_status() == TaskStatus::Zombie } + pub fn alloc_fd(&mut self) -> usize { + if let Some(fd) = (0..self.fd_table.len()) + .find(|fd| self.fd_table[*fd].is_none()) { + fd + } else { + self.fd_table.push(None); + self.fd_table.len() - 1 + } + } } impl TaskControlBlock { @@ -73,6 +85,14 @@ impl TaskControlBlock { parent: None, children: Vec::new(), exit_code: 0, + fd_table: vec![ + // 0 -> stdin + Some(Arc::new(Stdin)), + // 1 -> stdout + Some(Arc::new(Stdout)), + // 2 -> stderr + Some(Arc::new(Stdout)), + ], }), }; // prepare TrapContext in user space @@ -126,6 +146,15 @@ impl TaskControlBlock { let kernel_stack_top = kernel_stack.get_top(); // push a goto_trap_return task_cx on the top of kernel stack let task_cx_ptr = kernel_stack.push_on_top(TaskContext::goto_trap_return()); + // copy fd table + let mut new_fd_table: Vec>> = Vec::new(); + for fd in parent_inner.fd_table.iter() { + if let Some(file) = fd { + new_fd_table.push(Some(file.clone())); + } else { + new_fd_table.push(None); + } + } let task_control_block = Arc::new(TaskControlBlock { pid: pid_handle, kernel_stack, @@ -138,6 +167,7 @@ impl TaskControlBlock { parent: Some(Arc::downgrade(self)), children: Vec::new(), exit_code: 0, + fd_table: new_fd_table, }), }); // add child diff --git a/user/src/bin/pipe_large_test.rs b/user/src/bin/pipe_large_test.rs new file mode 100644 index 0000000..7d334cd --- /dev/null +++ b/user/src/bin/pipe_large_test.rs @@ -0,0 +1,69 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user; + +extern crate alloc; + +use user::{fork, close, pipe, read, write, wait, get_time}; +use alloc::format; + +const LENGTH: usize = 3000; +#[no_mangle] +pub fn main() -> i32 { + // create pipes + // parent write to child + let mut down_pipe_fd = [0usize; 2]; + // child write to parent + let mut up_pipe_fd = [0usize; 2]; + pipe(&mut down_pipe_fd); + pipe(&mut up_pipe_fd); + let mut random_str = [0u8; LENGTH]; + if fork() == 0 { + // close write end of down pipe + close(down_pipe_fd[1]); + // close read end of up pipe + close(up_pipe_fd[0]); + assert_eq!(read(down_pipe_fd[0], &mut random_str) as usize, LENGTH); + close(down_pipe_fd[0]); + let sum: usize = random_str.iter().map(|v| *v as usize).sum::(); + println!("sum = {}(child)", sum); + let sum_str = format!("{}", sum); + write(up_pipe_fd[1], sum_str.as_bytes()); + close(up_pipe_fd[1]); + println!("Child process exited!"); + 0 + } else { + // close read end of down pipe + close(down_pipe_fd[0]); + // 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; + } + // send it + 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) + let sum: usize = random_str.iter().map(|v| *v as usize).sum::(); + println!("sum = {}(parent)", sum); + // recv sum(child) + let mut child_result = [0u8; 32]; + let result_len = read(up_pipe_fd[0], &mut child_result) as usize; + close(up_pipe_fd[0]); + // check + assert_eq!( + sum, + str::parse::( + 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 diff --git a/user/src/bin/pipetest.rs b/user/src/bin/pipetest.rs new file mode 100644 index 0000000..e21ebac --- /dev/null +++ b/user/src/bin/pipetest.rs @@ -0,0 +1,44 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user; + +use user::{fork, close, pipe, read, write, wait}; + +static STR: &str = "Hello, world!"; + +#[no_mangle] +pub fn main() -> i32 { + // create pipe + let mut pipe_fd = [0usize; 2]; + pipe(&mut pipe_fd); + // read end + assert_eq!(pipe_fd[0], 3); + // write end + assert_eq!(pipe_fd[1], 4); + if fork() == 0 { + // child process, read from parent + // close write_end + close(pipe_fd[1]); + let mut buffer = [0u8; 32]; + let len_read = read(pipe_fd[0], &mut buffer) as usize; + // close read_end + close(pipe_fd[0]); + assert_eq!(core::str::from_utf8(&buffer[..len_read]).unwrap(), STR); + println!("Read OK, child process exited!"); + 0 + } else { + // parent process, write to child + // close read end + close(pipe_fd[0]); + assert_eq!(write(pipe_fd[1], STR.as_bytes()), STR.len() as isize); + // close write end + close(pipe_fd[1]); + let mut child_exit_code: i32 = 0; + wait(&mut child_exit_code); + assert_eq!(child_exit_code, 0); + println!("pipetest passed!"); + 0 + } +} \ No newline at end of file diff --git a/user/src/lib.rs b/user/src/lib.rs index 6b4232b..d6d53aa 100644 --- a/user/src/lib.rs +++ b/user/src/lib.rs @@ -41,6 +41,8 @@ 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); } diff --git a/user/src/scall_os.rs b/user/src/scall_os.rs index 52f7072..dffa34b 100644 --- a/user/src/scall_os.rs +++ b/user/src/scall_os.rs @@ -1,3 +1,5 @@ +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; @@ -23,6 +25,14 @@ fn syscall(id: usize, args: [usize; 3]) -> isize { ret } +pub fn sys_close(fd: usize) -> isize { + syscall(SYSCALL_CLOSE, [fd, 0, 0]) +} + +pub fn sys_pipe(pipe: &mut [usize]) -> isize { + syscall(SYSCALL_PIPE, [pipe.as_mut_ptr() as usize, 0, 0]) +} + pub fn sys_read(fd: usize, buffer: &mut [u8]) -> isize { syscall(SYSCALL_READ, [fd, buffer.as_mut_ptr() as usize, buffer.len()]) }