Skip to content

Commit

Permalink
Merge pull request #22 from syswonder/dev
Browse files Browse the repository at this point in the history
finish left parts
  • Loading branch information
coolyjg authored Jun 18, 2024
2 parents 2dc74e6 + f0b037d commit 1a009e5
Show file tree
Hide file tree
Showing 5 changed files with 268 additions and 5 deletions.
46 changes: 45 additions & 1 deletion src/chap03/your_app.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,53 @@

# 自定义应用

本章节将包含如何将您的应用在 RuxOS 上运行起来。
本章节将包含如何将您的应用在 RuxOS 上运行起来,下面介绍的均为从源码编译、运行,更便捷的方式是[动态加载应用二进制文件](../chap02/ELF-loader.md)

## C 应用

RuxOS 对于 C 应用的支持是比较完善的,根据以下步骤即可完成:

- 将对应的 C 应用源码放到指定的路径,并声明所需要使用的内核 feature。

集成 C 应用的时候,有两个重要的文件:`axbuild.mk``features.txt`,前者用于指定需要编译的 C 文件和在编译 C 文件的时候需要提供的编译参数,用于将 C 源文件编译成目标文件后,与内核链接在一起,生成统一的二进制文件。后者用于声明该 C 应用所需要的内核特征,用于对内核进行裁剪。所有的 feature 在 RuxOS 的源码中 `api/ruxfeat` 中进行了定义。

- 选取需要使用的 C 标准库,RuxOS 提供了两种 C 标准库,分别是以直接函数调用支持的 ruxlibc 和以系统调用形式支持的标准 musl libc,只需要添加 `MUSL=y` 编译选项即可。

- 参考编译命令:

```shell
make run A=<arg1> MUSL=<arg2> ARCH=<arg3> LOG=<arg4> ARGS=<arg5> NET=<arg6> V9P=<arg7> V9P_PATH=<arg8> BLK=<arg9> SMP=<arg10>
```
- **arg1**:应用相对于当前终端的路径。

- arg2:y/n,y 表示使用 musl libc,默认为 n。

- arg3:目标架构,默认为 x86_64,可选 aarch64/riscv64。

- arg4:日志等级,可选 error/warn/info/debug/trace,默认为 warn。

- arg5:应用所需参数,对应 main 函数中的 argv变量,以逗号分隔,不支持空格。

- arg6:y/n,y 表示使用网络设备,默认为 n。

- arg7:y/n,y 表示使用 9pfs,默认为 n。

- arg8:使用 9pfs 时共享目录的路径。**在未开启 `blkfs` feature 时,该共享目录会挂载到 RuxOS 的根目录上,否则挂载到 `/9pfs/` 路径**

- arg9:y/n,y 表示使用块设备,默认为 n。

- arg10:核数,大于1会开启 `smp` feature,执行多核环境。

## 其他语言应用

### 解释型语言

解释型语言,以 python 为例,需要支持对应的解释器,然后由解释器去加载、运行源文件。

此时,只需要将解释器源码像上述 C 应用一样进行合理的放置和配置,通过 `ARGS` 参数来传递相关的应用路径即可,推荐借助 9pfs 共享目录。

### 带标准库的语言

以 Rust 为例,需要通过 musl libc 支持 Rust std,并将支持的 Rust std 与内核、应用链接到一起即可。


154 changes: 151 additions & 3 deletions src/chap06/crates/algorithms.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,174 @@ RuxOS 底层组件实现了多种内存分配和任务调度算法,提供给

## 内存分配算法

RuxOS 支持三种内存分配算法,提供给应用使用。在内存分配组件中,定义了如下特征:

```rust
/// The base allocator inherited by other allocators.
pub trait BaseAllocator {
/// Initialize the allocator with a free memory region.
fn init(&mut self, start: usize, size: usize);

/// Add a free memory region to the allocator.
fn add_memory(&mut self, start: usize, size: usize) -> AllocResult;
}
```

`BaseAllocator` 定义了作为分配器的基本方法,即初始化可用内存范围,以及扩大可用内存范围。

```rust
/// Byte-granularity allocator.
pub trait ByteAllocator: BaseAllocator {
/// Allocate memory with the given size (in bytes) and alignment.
fn alloc(&mut self, layout: Layout) -> AllocResult<NonNull<u8>>;

/// Deallocate memory at the given position, size, and alignment.
fn dealloc(&mut self, pos: NonNull<u8>, layout: Layout);

/// Returns total memory size in bytes.
fn total_bytes(&self) -> usize;

/// Returns allocated memory size in bytes.
fn used_bytes(&self) -> usize;

/// Returns available memory size in bytes.
fn available_bytes(&self) -> usize;
}
```

`ByteAllocator` 定义了以字节为粒度的分配器所具备的基本方法,包括:

- 分配/释放指定大小的内存,以 rust 的 `layout` 进行描述。

- 目前管理的内存信息,包括总字节数、已用字节数、可用字节数。


```rust
/// Page-granularity allocator.
pub trait PageAllocator: BaseAllocator {
/// The size of a memory page.
const PAGE_SIZE: usize;

/// Allocate contiguous memory pages with given count and alignment.
fn alloc_pages(&mut self, num_pages: usize, align_pow2: usize) -> AllocResult<usize>;

/// Deallocate contiguous memory pages with given position and count.
fn dealloc_pages(&mut self, pos: usize, num_pages: usize);

/// Returns the total number of memory pages.
fn total_pages(&self) -> usize;

/// Returns the number of allocated memory pages.
fn used_pages(&self) -> usize;

/// Returns the number of available memory pages.
fn available_pages(&self) -> usize;
}
```

`PageAllocator` 定义了以页为粒度的分配器的基本方法,与字节为粒度的分配器方法类似。


### buddy 算法

[Buddy](https://en.wikipedia.org/wiki/Buddy_memory_allocation) 算法将内存分为多个固定大小的块,分配的时候仅分配出去最接近需求大小的内存块。

RuxOS 借助第三方库 [buddy_system_allocator](https://crates.io/crates/buddy_system_allocator) 来进行实现,提供了 `BuddyByteAllocator` 结构体,为其实现了 `BaseAllocator``ByteAllocator` 两个 trait,基于 `buddy` feature 进行条件编译。


### slab 算法

[Slab](https://en.wikipedia.org/wiki/Slab_allocation) 分配器以从64到4096的2的幂次方大小的对象为粒度自主进行内存分配,对大于4096字节的内存块借助 `buddy_system` 分配器进行分配。

### tlsf 算法
RuxOS 自己实现了相关的 slab 算法分配语义,提供了 `SlabByteAllocator` 结构体,为其实现了 `BaseAllocator``ByteAllocator` 两个 trait,基于 `slab` feature 进行条件编译。

### tlsf 算法

[tlsf](http://www.gii.upv.es/tlsf/) 动态内存分配算法常用于实时系统中,借助第三方库 [rlsf](https://crates.io/crates/rlsf) 来进行实现,提供了 TlsfByteAllocator 结构体,为其实现了 `BaseAllocator``ByteAllocator` 两个 trait,基于 `tlsf` feature 进行条件编译。

## 任务调度算法

RuxOS 支持三种任务调度算法,定义了调度器的基本特征:

```rust
/// The base scheduler trait that all schedulers should implement.
///
/// All tasks in the scheduler are considered runnable. If a task is go to
/// sleep, it should be removed from the scheduler.
pub trait BaseScheduler {
/// Type of scheduled entities. Often a task struct.
type SchedItem;

/// Initializes the scheduler.
fn init(&mut self);

/// Adds a task to the scheduler.
fn add_task(&mut self, task: Self::SchedItem);

/// Removes a task by its reference from the scheduler. Returns the owned
/// removed task with ownership if it exists.
///
/// # Safety
///
/// The caller should ensure that the task is in the scheduler, otherwise
/// the behavior is undefined.
fn remove_task(&mut self, task: &Self::SchedItem) -> Option<Self::SchedItem>;

/// Picks the next task to run, it will be removed from the scheduler.
/// Returns [`None`] if there is not runnable task.
fn pick_next_task(&mut self) -> Option<Self::SchedItem>;

/// Puts the previous task back to the scheduler. The previous task is
/// usually placed at the end of the ready queue, making it less likely
/// to be re-scheduled.
///
/// `preempt` indicates whether the previous task is preempted by the next
/// task. In this case, the previous task may be placed at the front of the
/// ready queue.
fn put_prev_task(&mut self, prev: Self::SchedItem, preempt: bool);

/// Advances the scheduler state at each timer tick. Returns `true` if
/// re-scheduling is required.
///
/// `current` is the current running task.
fn task_tick(&mut self, current: &Self::SchedItem) -> bool;

/// set priority for a task
fn set_priority(&mut self, task: &Self::SchedItem, prio: isize) -> bool;
}
```

`BaseScheduler` 中定义了调度器的关联对象类型和基本方法:

- `SchedItem`:定义了调度器的调度对象,包含其属性等,与具体的调度算法有关。

- `init`:调度器初始化。

- `add_task/remove_task`:放入就绪的任务或移除任务。

- `pick_next_task`:获取下一个可运行的任务。

- `put_prev_task`:将上一个任务重新放回调度器中,如果该任务是被抢占的任务,则放入就绪队列的头部,否则放入末尾。

- `task_tick`:递增相关的时钟属性。

- `set_priority`:设置任务的优先级。


### FIFO 算法

FIFO 先入先出算法按序执行当前就绪队列中的所有任务,以先到达的任务先占据CPU为原则,直到该任务运行完成主动退出,或主动让出处理器,才会调度下一个就绪任务。由于该算法在当前的多种编程语言和主流应用中不适用,RuxOS 正在考虑移除该算法实现。

RuxOS 提供了 `FifoScheduler` 对象,为其实现了 `BaseScheduler`

### RR 算法

[Round Robin](https://en.wikipedia.org/wiki/Round-robin_scheduling) 时间片轮转算法以时间片为单位进行任务调度,当时钟中断来临时,对当前正在执行的任务进行换出,调度下一个等待的就绪任务。

### CFS 算法

RuxOS 提供了 `RRScheduler` 对象,为其实现了 `BaseScheduler`

### CFS 算法

[Completely Fair Scheduler](https://en.wikipedia.org/wiki/Completely_Fair_Scheduler) 完全公平调度算法基于 nice 值来对任务进行调度,期望任务根据优先级来按比例获取处理器时间。

RuxOS 提供了 `CFScheduler` 对象,为其实现了 `BaseScheduler`
14 changes: 13 additions & 1 deletion src/chap06/modules/config-and-initialization.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@


# 配置及运行时初始化

为了规范的配置操作系统的各项参数,以及设置虚拟机的相关参数,RuxOS 分为了三个阶段来进行内核配置及相关运行时的初始化,如下图所示。

<p align="center">
<img src="../../figures/initialization.jpg" alt="RuxOS-init" width="800">
</p>


### RuxOS 基本参数配置 ruxconfig

ruxconfig 模块定义了操作系统和 qemu 提供的内存等基本参数,包括:物理内存起始地址、物理内存大小、虚拟地址起始地址、外设地址等,其中 qemu 的具体配置借助的是 make 脚本,链接相关地址布局定义在 ruxhal 中,但在内核引导之前被使用。

### RuxOS 硬件抽象层 ruxhal

ruxhal 模块为内核引导的重要模块,[上图](#配置及运行时初始化)的第二阶段描述了这一层做的具体工作,这里对其中的调用链进行简单介绍:

- `_start`:该函数为 qemu 引导完成后跳入内核代码的第一个函数,在该函数中完成了相关寄存器的初始化,并使能了虚拟地址。

- `rust_entry`:配置页表、初始化异常处理模块等,这里是入口函数的补充,与具体平台的相关外设、硬件设备相关。

### RuxOS 运行时 ruxruntime

ruxruntime 模块提供了操作系统和应用运行时初始化入口,从 ruxhal 的 `rust_entry` 结束后,跳转到 ruxruntime 的 `rust_main` 入口,在这里进行诸多软件相关的初始化,包括内核各个子模块初始化、从核引导、musl libc 初始栈布局等工作,是 RuxOS 初始化的重要模块。



59 changes: 59 additions & 0 deletions src/chap06/modules/kernel-submodules.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,85 @@

# 内核子模块

基于 RuxOS 组件,在功能模块层封装出了多个内核子模块。

### 内存分配模块 axalloc

内存分配模块移植于 ArceOS,封装了底层不同的内存分配算法,提供统一的全局内存分配器 `GlobalAllocator`,提供给 rust 用作动态内存分配的分配器。

提供如下 feature,默认使用 tlsf 分配器。

- tlsf:使用 tlsf 算法。

- slab:使用 slab 算法。

- buddy:使用 buddy 算法。


### 网络模块 axnet

网络模块移植于 ArceOS,借助了第三方库 [smoltcp](https://crates.io/crates/smoltcp) 提供的网络栈,对其进行封装,支持TCP、UDP 协议,支持 IpV4 协议,提供套接字编程接口。

RuxOS 正在进行 lwip 的移植工作。

### 任务调度模块 ruxtask

ruxtask 模块提供了任务管理的多种数据结构及方法。

- 提供单线程/多线程环境下,调度器初始化、yield、睡眠、新任务生成等编程接口。

- 提供就绪队列、等待队列,及相关的编程接口,包括了任务的切换、调度、阻塞、唤醒等。支持基于事件的阻塞和唤醒机制,用于 futex 等机制的实现;支持基于定时器的阻塞和唤醒机制,用于 sleep 等系统调用。

- 对内核任务的描述,提供 `TaskInner` 数据结构,描述内核任务的基本属性、状态信息。

重要 feature:

```txt
multitask = [
"dep:ruxconfig", "dep:percpu", "dep:spinlock", "dep:lazy_init", "dep:memory_addr",
"dep:scheduler", "dep:timer_list", "kernel_guard", "dep:crate_interface",
]
tls = ["ruxhal/tls"]
preempt = ["irq", "percpu?/preempt", "kernel_guard/preempt"]
sched_fifo = ["multitask"]
sched_rr = ["multitask", "preempt"]
sched_cfs = ["multitask", "preempt"]
```

- multitask:是否启用多线程。

- tls:线程局部存储,可定义线程局部数据。

- preempt:是否支持任务抢占。

- sched_:选取调度算法。


### 驱动模块 ruxdriver

[底层组件](../crates/drivers.md)中对各类驱动的基本特征进行了定义,在该模块中,对各种类型的设备进行注册、初始化。

### 9pfs 模块 rux9p

9pfs 提供了主机与 qemu 共享目录的功能,方便了应用的开发,具体内容[参考这里](./9pfs.md)


### 显示模块 ruxdisplay

提供了对 virtio-gpu 设备的初始化接口,在这里维护了 `MAIN_DISPLAY` 这一静态变量,封装了底层组件的显示相关接口。


### 文件系统模块 ruxfs

ruxfs 提供了文件系统初始化的重要接口,以及借助 [rust-fatfs](https://github.com/syswonder/rust-fatfs.git) 支持了 fatfs。

- 提供对 ramfs/blkfs 的初始化,根目录默认初始化为内存文件系统或基于 virtio 的块设备文件系统。

- 提供兼容 Linux 的相关文件系统的挂载,包括 devfs、procfs、tmpfs、sysfs、etcfs,并生成相关的诸多系统文件。

- 提供 File/Directory 的数据结构和相关方法,用于上层系统调用的实现。

ruxfs 支持动态挂载文件系统,并能根据路径执行指定文件系统的相关方法,目前仍在完善中。

Binary file added src/figures/initialization.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 1a009e5

Please sign in to comment.