Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
rcore-os
RCore Tutorial V3
提交
2e673402
R
RCore Tutorial V3
项目概览
rcore-os
/
RCore Tutorial V3
上一次同步 1 年多
通知
15
Star
793
Fork
260
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
4
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
RCore Tutorial V3
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
4
Issue
4
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
2e673402
编写于
12月 13, 2020
作者:
Y
Yifan Wu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Rewrite Stdin/Stdout
上级
f5c029d3
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
338 addition
and
42 deletion
+338
-42
os/src/fs/mod.rs
os/src/fs/mod.rs
+20
-0
os/src/fs/pipe.rs
os/src/fs/pipe.rs
+167
-0
os/src/fs/stdio.rs
os/src/fs/stdio.rs
+46
-0
os/src/main.rs
os/src/main.rs
+1
-0
os/src/mm/mod.rs
os/src/mm/mod.rs
+2
-0
os/src/mm/page_table.rs
os/src/mm/page_table.rs
+53
-4
os/src/syscall/fs.rs
os/src/syscall/fs.rs
+32
-38
os/src/task/task.rs
os/src/task/task.rs
+17
-0
未找到文件。
os/src/fs/mod.rs
0 → 100644
浏览文件 @
2e673402
mod
pipe
;
mod
stdio
;
use
crate
::
mm
::
UserBuffer
;
use
core
::
any
::
Any
;
pub
trait
File
:
Any
+
Send
+
Sync
{
fn
read
(
&
self
,
buf
:
UserBuffer
)
->
usize
;
fn
write
(
&
self
,
buf
:
UserBuffer
)
->
usize
;
fn
as_any_ref
(
&
self
)
->
&
dyn
Any
;
}
impl
dyn
File
{
pub
fn
downcast_ref
<
T
:
File
>
(
&
self
)
->
Option
<&
T
>
{
self
.as_any_ref
()
.downcast_ref
::
<
T
>
()
}
}
pub
use
pipe
::{
Pipe
};
pub
use
stdio
::{
Stdin
,
Stdout
};
\ No newline at end of file
os/src/fs/pipe.rs
0 → 100644
浏览文件 @
2e673402
use
super
::
File
;
use
alloc
::
sync
::{
Arc
,
Weak
};
use
spin
::
Mutex
;
use
crate
::
mm
::{
UserBuffer
,
};
use
crate
::
task
::
suspend_current_and_run_next
;
use
core
::
any
::
Any
;
pub
struct
Pipe
{
readable
:
bool
,
writable
:
bool
,
buffer
:
Arc
<
Mutex
<
PipeRingBuffer
>>
,
}
impl
Pipe
{
pub
fn
read_end_with_buffer
(
buffer
:
Arc
<
Mutex
<
PipeRingBuffer
>>
)
->
Self
{
Self
{
readable
:
true
,
writable
:
false
,
buffer
,
}
}
pub
fn
write_end_with_buffer
(
buffer
:
Arc
<
Mutex
<
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
<
Mutex
<
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
<
Mutex
<
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
<
Mutex
<
Pipe
>>
,
Arc
<
Mutex
<
Pipe
>>
)
{
let
buffer
=
Arc
::
new
(
Mutex
::
new
(
PipeRingBuffer
::
new
()));
let
read_end
=
Arc
::
new
(
Mutex
::
new
(
Pipe
::
read_end_with_buffer
(
buffer
.clone
())
));
let
write_end
=
Arc
::
new
(
Mutex
::
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
=
0u
size
;
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
=
0u
size
;
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
;
}
}
}
}
fn
as_any_ref
(
&
self
)
->
&
dyn
Any
{
self
}
}
\ No newline at end of file
os/src/fs/stdio.rs
0 → 100644
浏览文件 @
2e673402
use
super
::
File
;
use
crate
::
mm
::{
UserBuffer
,
UserBufferIterator
};
use
crate
::
sbi
::
console_getchar
;
use
crate
::
task
::
suspend_current_and_run_next
;
use
core
::
any
::
Any
;
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
,
_u
ser_buf
:
UserBuffer
)
->
usize
{
panic!
(
"Cannot write to stdin!"
);
}
fn
as_any_ref
(
&
self
)
->
&
dyn
Any
{
self
}
}
impl
File
for
Stdout
{
fn
read
(
&
self
,
_u
ser_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
()
}
fn
as_any_ref
(
&
self
)
->
&
dyn
Any
{
self
}
}
\ No newline at end of file
os/src/main.rs
浏览文件 @
2e673402
...
...
@@ -22,6 +22,7 @@ mod config;
mod
task
;
mod
timer
;
mod
mm
;
mod
fs
;
global_asm!
(
include_str!
(
"entry.asm"
));
global_asm!
(
include_str!
(
"link_app.S"
));
...
...
os/src/mm/mod.rs
浏览文件 @
2e673402
...
...
@@ -13,6 +13,8 @@ pub use page_table::{
translated_byte_buffer
,
translated_str
,
translated_refmut
,
UserBuffer
,
UserBufferIterator
,
};
pub
use
memory_set
::{
MemorySet
,
KERNEL_SPACE
,
MapPermission
};
pub
use
memory_set
::
remap_test
;
...
...
os/src/mm/page_table.rs
浏览文件 @
2e673402
...
...
@@ -138,9 +138,7 @@ impl PageTable {
pub
fn
translate_va
(
&
self
,
va
:
VirtAddr
)
->
Option
<
PhysAddr
>
{
self
.find_pte
(
va
.clone
()
.floor
())
.map
(|
pte
|
{
//println!("translate_va:va = {:?}", va);
let
aligned_pa
:
PhysAddr
=
pte
.ppn
()
.into
();
//println!("translate_va:pa_align = {:?}", aligned_pa);
let
offset
=
va
.page_offset
();
let
aligned_pa_usize
:
usize
=
aligned_pa
.into
();
(
aligned_pa_usize
+
offset
)
.into
()
...
...
@@ -189,9 +187,60 @@ pub fn translated_str(token: usize, ptr: *const u8) -> String {
}
pub
fn
translated_refmut
<
T
>
(
token
:
usize
,
ptr
:
*
mut
T
)
->
&
'static
mut
T
{
//println!("into translated_refmut!");
let
page_table
=
PageTable
::
from_token
(
token
);
let
va
=
ptr
as
usize
;
//println!("translated_refmut: before translate_va");
page_table
.translate_va
(
VirtAddr
::
from
(
va
))
.unwrap
()
.get_mut
()
}
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
<
Self
::
Item
>
{
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
os/src/syscall/fs.rs
浏览文件 @
2e673402
use
crate
::
mm
::
translated_byte_buffer
;
use
crate
::
task
::{
current_user_token
,
suspend_current_and_run_next
};
use
crate
::
sbi
::
console_getchar
;
const
FD_STDIN
:
usize
=
0
;
const
FD_STDOUT
:
usize
=
1
;
use
crate
::
mm
::{
UserBuffer
,
translated_byte_buffer
};
use
crate
::
task
::{
current_user_token
,
current_task
};
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
{
buffers
:
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
{
buffers
:
translated_byte_buffer
(
token
,
buf
,
len
),
})
as
isize
}
else
{
-
1
}
}
\ No newline at end of file
os/src/task/task.rs
浏览文件 @
2e673402
...
...
@@ -4,8 +4,10 @@ use crate::config::{TRAP_CONTEXT};
use
super
::
TaskContext
;
use
super
::{
PidHandle
,
pid_alloc
,
KernelStack
};
use
alloc
::
sync
::{
Weak
,
Arc
};
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
<
Weak
<
TaskControlBlock
>>
,
pub
children
:
Vec
<
Arc
<
TaskControlBlock
>>
,
pub
exit_code
:
i32
,
pub
fd_table
:
Vec
<
Option
<
Arc
<
dyn
File
+
Send
+
Sync
>>>
,
}
impl
TaskControlBlockInner
{
...
...
@@ -74,6 +77,10 @@ impl TaskControlBlock {
parent
:
None
,
children
:
Vec
::
new
(),
exit_code
:
0
,
fd_table
:
vec!
[
Some
(
Arc
::
new
(
Stdin
)),
Some
(
Arc
::
new
(
Stdout
)),
],
}),
};
// prepare TrapContext in user space
...
...
@@ -136,6 +143,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
<
Option
<
Arc
<
dyn
File
+
Send
+
Sync
>>>
=
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
,
...
...
@@ -148,6 +164,7 @@ impl TaskControlBlock {
parent
:
Some
(
Arc
::
downgrade
(
self
)),
children
:
Vec
::
new
(),
exit_code
:
0
,
fd_table
:
new_fd_table
,
}),
});
// add child
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录