Remove pipe && Fix cat and huge_write.
This commit is contained in:
parent
57f7debbc6
commit
5389b7adca
10 changed files with 7 additions and 332 deletions
|
@ -1,4 +1,3 @@
|
||||||
mod pipe;
|
|
||||||
mod stdio;
|
mod stdio;
|
||||||
mod inode;
|
mod inode;
|
||||||
|
|
||||||
|
@ -11,6 +10,5 @@ pub trait File : Send + Sync {
|
||||||
fn write(&self, buf: UserBuffer) -> usize;
|
fn write(&self, buf: UserBuffer) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use pipe::{Pipe, make_pipe};
|
|
||||||
pub use stdio::{Stdin, Stdout};
|
pub use stdio::{Stdin, Stdout};
|
||||||
pub use inode::{OSInode, open_file, OpenFlags, list_apps};
|
pub use inode::{OSInode, open_file, OpenFlags, list_apps};
|
||||||
|
|
|
@ -1,168 +0,0 @@
|
||||||
use super::File;
|
|
||||||
use alloc::sync::{Arc, Weak};
|
|
||||||
use crate::sync::UPSafeCell;
|
|
||||||
use crate::mm::UserBuffer;
|
|
||||||
|
|
||||||
use crate::task::suspend_current_and_run_next;
|
|
||||||
|
|
||||||
pub struct Pipe {
|
|
||||||
readable: bool,
|
|
||||||
writable: bool,
|
|
||||||
buffer: Arc<UPSafeCell<PipeRingBuffer>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Pipe {
|
|
||||||
pub fn read_end_with_buffer(buffer: Arc<UPSafeCell<PipeRingBuffer>>) -> Self {
|
|
||||||
Self {
|
|
||||||
readable: true,
|
|
||||||
writable: false,
|
|
||||||
buffer,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn write_end_with_buffer(buffer: Arc<UPSafeCell<PipeRingBuffer>>) -> 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<Weak<Pipe>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
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<Pipe>) {
|
|
||||||
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<Pipe>, Arc<Pipe>) {
|
|
||||||
let buffer = Arc::new(unsafe {
|
|
||||||
UPSafeCell::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.exclusive_access().set_write_end(&write_end);
|
|
||||||
(read_end, write_end)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl File for Pipe {
|
|
||||||
fn readable(&self) -> bool { self.readable }
|
|
||||||
fn writable(&self) -> bool { self.writable }
|
|
||||||
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.exclusive_access();
|
|
||||||
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.exclusive_access();
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +1,10 @@
|
||||||
use crate::mm::{
|
use crate::mm::{
|
||||||
UserBuffer,
|
UserBuffer,
|
||||||
translated_byte_buffer,
|
translated_byte_buffer,
|
||||||
translated_refmut,
|
|
||||||
translated_str,
|
translated_str,
|
||||||
};
|
};
|
||||||
use crate::task::{current_user_token, current_task};
|
use crate::task::{current_user_token, current_task};
|
||||||
use crate::fs::{make_pipe, OpenFlags, open_file};
|
use crate::fs::{OpenFlags, open_file};
|
||||||
use alloc::sync::Arc;
|
|
||||||
|
|
||||||
pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize {
|
pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize {
|
||||||
let token = current_user_token();
|
let token = current_user_token();
|
||||||
|
@ -81,31 +79,3 @@ pub fn sys_close(fd: usize) -> isize {
|
||||||
inner.fd_table[fd].take();
|
inner.fd_table[fd].take();
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sys_pipe(pipe: *mut usize) -> isize {
|
|
||||||
let task = current_task().unwrap();
|
|
||||||
let token = current_user_token();
|
|
||||||
let mut inner = task.inner_exclusive_access();
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn sys_dup(fd: usize) -> isize {
|
|
||||||
let task = current_task().unwrap();
|
|
||||||
let mut inner = task.inner_exclusive_access();
|
|
||||||
if fd >= inner.fd_table.len() {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if inner.fd_table[fd].is_none() {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
let new_fd = inner.alloc_fd();
|
|
||||||
inner.fd_table[new_fd] = Some(Arc::clone(inner.fd_table[fd].as_ref().unwrap()));
|
|
||||||
new_fd as isize
|
|
||||||
}
|
|
|
@ -1,7 +1,5 @@
|
||||||
const SYSCALL_DUP: usize = 24;
|
|
||||||
const SYSCALL_OPEN: usize = 56;
|
const SYSCALL_OPEN: usize = 56;
|
||||||
const SYSCALL_CLOSE: usize = 57;
|
const SYSCALL_CLOSE: usize = 57;
|
||||||
const SYSCALL_PIPE: usize = 59;
|
|
||||||
const SYSCALL_READ: usize = 63;
|
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;
|
||||||
|
@ -20,10 +18,8 @@ use process::*;
|
||||||
|
|
||||||
pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
|
pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
|
||||||
match syscall_id {
|
match syscall_id {
|
||||||
SYSCALL_DUP=> sys_dup(args[0]),
|
|
||||||
SYSCALL_OPEN => sys_open(args[0] as *const u8, args[1] as u32),
|
SYSCALL_OPEN => sys_open(args[0] as *const u8, args[1] as u32),
|
||||||
SYSCALL_CLOSE => sys_close(args[0]),
|
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_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_WRITE => sys_write(args[0], args[1] as *const u8, args[2]),
|
||||||
SYSCALL_EXIT => sys_exit(args[0] as i32),
|
SYSCALL_EXIT => sys_exit(args[0] as i32),
|
||||||
|
|
|
@ -21,14 +21,12 @@ pub fn main(argc: usize, argv: &[&str]) -> i32 {
|
||||||
panic!("Error occured when opening file");
|
panic!("Error occured when opening file");
|
||||||
}
|
}
|
||||||
let fd = fd as usize;
|
let fd = fd as usize;
|
||||||
let mut buf = [0u8; 16];
|
let mut buf = [0u8; 256];
|
||||||
let mut s = String::new();
|
|
||||||
loop {
|
loop {
|
||||||
let size = read(fd, &mut buf) as usize;
|
let size = read(fd, &mut buf) as usize;
|
||||||
if size == 0 { break; }
|
if size == 0 { break; }
|
||||||
s.push_str(core::str::from_utf8(&buf[..size]).unwrap());
|
println!("{}", core::str::from_utf8(&buf[..size]).unwrap());
|
||||||
}
|
}
|
||||||
println!("{}", s);
|
|
||||||
close(fd);
|
close(fd);
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ pub fn main() -> i32 {
|
||||||
for i in 0..buffer.len() {
|
for i in 0..buffer.len() {
|
||||||
buffer[i] = i as u8;
|
buffer[i] = i as u8;
|
||||||
}
|
}
|
||||||
let f = open("testf", OpenFlags::CREATE | OpenFlags::WRONLY);
|
let f = open("testf\0", OpenFlags::CREATE | OpenFlags::WRONLY);
|
||||||
if f < 0 {
|
if f < 0 {
|
||||||
panic!("Open test file failed!");
|
panic!("Open test file failed!");
|
||||||
}
|
}
|
||||||
|
@ -33,4 +33,4 @@ pub fn main() -> i32 {
|
||||||
let speed_kbs = size_mb * 1000000 / time_ms;
|
let speed_kbs = size_mb * 1000000 / time_ms;
|
||||||
println!("{}MiB written, time cost = {}ms, write speed = {}KiB/s", size_mb, time_ms, speed_kbs);
|
println!("{}MiB written, time cost = {}ms, write speed = {}KiB/s", size_mb, time_ms, speed_kbs);
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
#![no_std]
|
|
||||||
#![no_main]
|
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate user_lib;
|
|
||||||
|
|
||||||
extern crate alloc;
|
|
||||||
|
|
||||||
use user_lib::{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::<usize>();
|
|
||||||
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::<usize>();
|
|
||||||
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::<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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
#![no_std]
|
|
||||||
#![no_main]
|
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate user_lib;
|
|
||||||
|
|
||||||
use user_lib::{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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -71,7 +71,6 @@ bitflags! {
|
||||||
pub fn dup(fd: usize) -> isize { sys_dup(fd) }
|
pub fn dup(fd: usize) -> isize { sys_dup(fd) }
|
||||||
pub fn open(path: &str, flags: OpenFlags) -> isize { sys_open(path, flags.bits) }
|
pub fn open(path: &str, flags: OpenFlags) -> isize { sys_open(path, flags.bits) }
|
||||||
pub fn close(fd: usize) -> isize { sys_close(fd) }
|
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 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 write(fd: usize, buf: &[u8]) -> isize { sys_write(fd, buf) }
|
||||||
pub fn exit(exit_code: i32) -> ! { sys_exit(exit_code); }
|
pub fn exit(exit_code: i32) -> ! { sys_exit(exit_code); }
|
||||||
|
|
|
@ -3,7 +3,6 @@ use core::arch::asm;
|
||||||
const SYSCALL_DUP: usize = 24;
|
const SYSCALL_DUP: usize = 24;
|
||||||
const SYSCALL_OPEN: usize = 56;
|
const SYSCALL_OPEN: usize = 56;
|
||||||
const SYSCALL_CLOSE: usize = 57;
|
const SYSCALL_CLOSE: usize = 57;
|
||||||
const SYSCALL_PIPE: usize = 59;
|
|
||||||
const SYSCALL_READ: usize = 63;
|
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;
|
||||||
|
@ -40,10 +39,6 @@ pub fn sys_close(fd: usize) -> isize {
|
||||||
syscall(SYSCALL_CLOSE, [fd, 0, 0])
|
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 {
|
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()])
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue