0%

2024年开源操作系统训练营第三阶段总结-silent12rt

1
make -C /home/linux/vscode/arceos A=/home/linux/vscode/my_arceos_app ARCH=aarch64 LOG=debug SMP=1 run

U.1.0 HelloWorld

![![[Pasted image 20241111091146.png]]](<2024年开源操作系统训练营第三阶段总结-silent12rt/Pasted image 20241111091146.png>)
该图展示了一个应用程序(hello_world)在系统中各个模块(如axruntimeaxhalaxstdarceos)之间的结构和交互关系。以下是各个部分的功能说明:

  1. axhal(硬件抽象层):该层对硬件细节进行抽象,为更高层提供一个屏蔽底层硬件的基础,使上层不需要直接管理底层硬件。

  2. axruntime(运行时环境):该层管理应用程序的运行时环境,包括内存分配、线程调度和其他运行时服务,是应用程序正常运行的基础。

  3. ulib(axstd):这是一个标准库,为应用层提供通用功能和实用工具,可能包含基本的I/O操作、数据处理等辅助功能。

  4. api(arceos):这是与底层操作系统(ArceOS)的应用编程接口,允许应用程序执行系统级操作,如文件管理、进程间通信等。

  5. app(hello_world):这是用户的应用程序,利用axstdarceos提供的库和接口来执行特定任务。

  6. 执行流程

    • 左侧的准备环境(蓝色箭头)表示系统的准备阶段,在此阶段,配置和初始化必要的资源和环境。
    • 右侧的调用功能(橙色箭头)表示应用程序在运行时与axstdarceos进行的交互,通过这些库和API执行特定功能。

U.2.0 Collections

Buddy System(伙伴系统)

  1. 分配内存单元
    设置最小分配单元(通常是 2 的幂次方大小),而不是按1字节来分配。这种划分可以提高分配效率,并且降低管理开销。例如,如果分配单元是 8 字节,最小分配的内存块将是 8 字节。在 Buddy System 中,不同大小的块按 2 的幂次划分(即 8、16、32、64 等),每个大小被称为一个 order。每个 order 是一种特定大小的块。
  2. 分配过程
    • 寻找最小满足请求的块。当程序请求内存时,分配器首先确定需要分配的块的大小(例如 64 字节)。然后分配器会在内存池中找到最小的能满足此请求的 order 块(例如 128 字节的块,若没有 64 字节的块)。
    • 二分切割。如果找到的 order 大于所需的大小,那么分配器将不断地对该块进行 二分切割,直到得到匹配所需大小的块。
    • 返回分配的块:分配器返回一个与请求大小匹配的块,并将它从空闲列表中移除。此时,程序可以使用该块。
  3. 释放过程
    • 检查是否有空闲的邻居块:当程序释放某块内存时,分配器会检查该块是否有“伙伴”块(即同一级的邻居块)也是空闲的。两个邻居块的地址通常具有某种关系,使分配器可以根据地址快速定位伙伴块。
    • 合并到高 order:如果找到空闲的伙伴块,分配器会将两个相邻的空闲块合并成一个更大的块。这个合并过程会尽量继续进行,直到不能再合并为止。
    • 挂到 Order List:如果无法进一步合并,最终的空闲块会挂到相应的空闲列表(Order List)中,以备后续分配使用。

内存分配算法-Slab

![![[Pasted image 20241111191653.png]]](<2024年开源操作系统训练营第三阶段总结-silent12rt/Pasted image 20241111191653 1.png>)
分配过程

  1. 找到合适的OrderList
    根据请求的内存大小,找到合适的 OrderList。OrderList 会匹配内存大小,确保分配合适的 Slab。
  2. 从 Slab 的空闲块链表中获取 block
    • 从空闲块链表 (Free Block List) 中弹出一个 block,完成分配。
    • 如果空闲块链表中没有可用的 block,则进入下一步。
  3. 调用 BuddyAllocator 分配新块:
    • 当空闲链表中没有足够的块时,向 Buddy Allocator 请求一个较大的内存块。
    • 将分配到的较大内存块切分为符合 Slab 需求大小的 block,然后加入到该 Slab 的空闲块链表。
    • 最终,分配请求从空闲块链表中取出一个 block 返回。

释放过程

  1. 释放 block 到空闲块链表
    • 释放时,将 block 放回对应 Slab 的空闲块链表。
    • 这样,当后续需要分配类似大小的块时,可以直接从该空闲块链表中分配,避免重复分配和释放较大块的开销。
  2. 管理内存回收
    • 如果某个 Slab 变得完全空闲(即所有 block 都释放),可以选择将该 Slab 的内存归还给 Buddy Allocator,以释放更多内存供其他用途。

U.3.0 Collections

U.4.0 Collections

核心算法:context_switch

任务上下文Context: 保存任务状态的最小的寄存器状态集合。
![![[Pasted image 20241112144224.png]]](<2024年开源操作系统训练营第三阶段总结-silent12rt/Pasted image 20241112144224.png>)
ra: 函数返回地址寄存器,这个切换实现了任务执行指令流的切换。
sp: 任务即线程,这个是线程栈
s0~s11:按照riscv规范,callee不能改这组寄存器的信息,所以需要保存。

抢占式调度算法ROUND_ROBIN

在协作式调度FIFO的基础上,由定时器定时递减当前任务的时间片,耗尽时允许调度,一旦外部条件符合,边沿触发抢占,当前任务排到队尾,如此完成各个任务的循环排列。
![![[Pasted image 20241112151551.png]]](<2024年开源操作系统训练营第三阶段总结-silent12rt/Pasted image 20241112151551.png>)

抢占式调度算法CFS(Completely Fair Scheduler)

![![[Pasted image 20241112151735.png]]](<2024年开源操作系统训练营第三阶段总结-silent12rt/Pasted image 20241112151735.png>)