Skip to content

Commit

Permalink
wip(lab/4): update
Browse files Browse the repository at this point in the history
  • Loading branch information
GZTimeWalker committed Feb 22, 2024
1 parent ad31dbd commit 6342cd4
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 19 deletions.
26 changes: 22 additions & 4 deletions docs/labs/0x04/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ macro_rules! entry {

本次实验你应当在 `pkg/kernel/config/boot.conf` 中,将 `load_apps` 设置为 `true`。

为了存储用户程序的相关信息,在 bootloader 中,定义一个 `App` 结构体,并添加“已加载的用户程序”字段到 `BootInfo` 结构体中:
为了存储用户程序的相关信息,在 `pkg\boot\src\lib.rs` 中,定义一个 `App` 结构体,并添加“已加载的用户程序”字段到 `BootInfo` 结构体中:

```rust
use arrayvec::{ArrayString, ArrayVec};
Expand Down Expand Up @@ -347,7 +347,7 @@ pub fn spawn(

!!! warning "**删除或注释上次实验中有关内核线程的代码,防止后续修改后的进程模型在执行内核线程时遇到意外的问题。**"

在加载的过程中,你可以复用 `elf::load_elf` 函数。可以通过为它添加参数的方式,控制这一映射的内容是否可以被用户权限访问
在加载的过程中,你可以复用 `elf::load_elf` 函数。可以通过为它添加参数的方式,控制这一映射的内容是否可以被用户权限(Ring 3)代码访问

```rust
pub fn load_elf(
Expand All @@ -361,14 +361,16 @@ pub fn load_elf(
}
```

在映射页面时,根据此参数决定是否添加 `USER_ACCESSIBLE` 标识位
在映射页面时,根据此参数决定是否添加 `USER_ACCESSIBLE` 标志位

```rust
if user_access {
page_table_flags |= PageTableFlags::USER_ACCESSIBLE;
}
```

这一标志位只应当为用户进程所使用,内核相关代码不应当拥有这一权限。由于用户程序是不可信的,需要以此防止用户态程序访问内核的内存空间。

!!! note "**对于用户进程而言,不再与内核共享页表,而是通过克隆内核页表获取了自己的页表。这意味着可以为每个用户进程分配同样的栈地址,而不会相互干扰。**"

需要在 GDT 中为 Ring 3 的代码段和数据段添加对应的选择子,在初始化栈帧的时候将其传入。在 `kernel/src/memory/gdt.rs` 中,你可以使用如下方式添加:
Expand Down Expand Up @@ -548,7 +550,23 @@ int _start() {

在这一部分的实现中,着重实现了 `read``write` 系统调用的封装和内核侧的实现,并通过内存分配、释放的系统调用,给予用户态程序动态内存分配的能力。

后者已经在给出的代码中实现,你可以参考它们的内容进行其他系统调用功能的实现。
### 动态内存分配

为了方便用户态程序使用动态内存分配,而不是基于 `mmap` 等方式进行完全用户态的动态内存管理,选择使用系统调用的方式,将内存分配的任务委托给内核完成。

与内核堆类似,在 `src/memory/user.rs` 中,定义了用户态的堆。

与内核使用 `static` 在内核 `bss` 段声明内存空间不同,由于在页表映射时需添加 `USER_ACCESSIBLE` 标志位,**用户态堆需要采用内核页面分配的能力完成**。其次需要注意的是,为了调试和安全性考量,这部分内存还需要 `NO_EXECUTE` 标志位。

有关用户态堆初始化的过程需要补全部分代码,指定合适的页面范围,分配并映射相关的页表,你可以参考、使用并修改 `elf::map_range` 完成这里的初始化。

!!! question "内存安全?"

这里的实现是不够安全的,共享用户态堆意味着用户程序可以任意读取访问其他用户进程的堆空间。

不过这样的实现可以大幅简化用户态库的相关实现,在能且仅能运行自己的程序、完成实验方面,这样的选择是很合适的。

在系统调用的实现方面,给出的代码中已包含,可以参考它们的内容进行其他系统调用功能的实现。

### 标准输入输出

Expand Down
17 changes: 2 additions & 15 deletions src/0x04/pkg/kernel/src/memory/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,13 @@ pub fn init() {
}

pub fn init_user_heap() -> Result<(), MapToError<Size4KiB>> {
let page_range = {
// FIXME: get heap page range by constants
// - Page::range(start, end)
};

debug!(
"User Heap : 0x{:016x}-0x{:016x}",
page_range.start.start_address().as_u64(),
page_range.end.start_address().as_u64()
);

// Get current pagetable mapper
let mapper = &mut PageTableContext::new().mapper();
// Get global frame allocator
let frame_allocator = &mut *super::get_frame_alloc_for_sure();

for page in page_range {
// FIXME: allocate new frame
// FIXME: map the page to the frame (R/W/User Access)
}
// FIXME: use elf::map_range to allocate & map
// frames (R/W/User Access)

unsafe {
USER_ALLOCATOR
Expand Down

0 comments on commit 6342cd4

Please sign in to comment.