diff --git a/src/chap03/your_app.md b/src/chap03/your_app.md index 8479dbb..3b8b7d6 100644 --- a/src/chap03/your_app.md +++ b/src/chap03/your_app.md @@ -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= MUSL= ARCH= LOG= ARGS= NET= V9P= V9P_PATH= BLK= SMP= + ``` + - **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 与内核、应用链接到一起即可。 diff --git a/src/chap06/crates/algorithms.md b/src/chap06/crates/algorithms.md index e594c28..489a525 100644 --- a/src/chap06/crates/algorithms.md +++ b/src/chap06/crates/algorithms.md @@ -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>; + + /// Deallocate memory at the given position, size, and alignment. + fn dealloc(&mut self, pos: NonNull, 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; + + /// 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; + + /// 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; + + /// 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`。 diff --git a/src/chap06/modules/config-and-initialization.md b/src/chap06/modules/config-and-initialization.md index f788c70..4a0d66a 100644 --- a/src/chap06/modules/config-and-initialization.md +++ b/src/chap06/modules/config-and-initialization.md @@ -1,16 +1,28 @@ - # 配置及运行时初始化 +为了规范的配置操作系统的各项参数,以及设置虚拟机的相关参数,RuxOS 分为了三个阶段来进行内核配置及相关运行时的初始化,如下图所示。 + +

+ RuxOS-init +

### 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 初始化的重要模块。 + diff --git a/src/chap06/modules/kernel-submodules.md b/src/chap06/modules/kernel-submodules.md index 6fa6165..e55c1a6 100644 --- a/src/chap06/modules/kernel-submodules.md +++ b/src/chap06/modules/kernel-submodules.md @@ -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 支持动态挂载文件系统,并能根据路径执行指定文件系统的相关方法,目前仍在完善中。 diff --git a/src/figures/initialization.jpg b/src/figures/initialization.jpg new file mode 100644 index 0000000..50d149b Binary files /dev/null and b/src/figures/initialization.jpg differ