-
Notifications
You must be signed in to change notification settings - Fork 437
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
93 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
--- | ||
title:2024 秋冬季开源操作系统训练营第一二三阶段总结-卓堂越 | ||
date: 2024-12-05 21:07:52 | ||
categories: | ||
- report | ||
tags: | ||
- author: nusakom | ||
- repo: https://github.com/LearningOS/2024a-rcore-nusakom | ||
--- | ||
## 第一阶段实验总结 | ||
|
||
在本次实验中,我深入探讨了Rust编程语言中的多个高级概念,并通过实际操作加深了对这些特性的理解。实验的重点涉及了Rust的内存管理、类型系统、并发编程等方面,帮助我更好地掌握了Rust的独特设计思想。 | ||
|
||
首先,我学习了**Option类型**,通过实践我了解了如何使用`Some`和`None`来表示可能不存在的值。这个特性不仅帮助我更好地处理空值,还为后续的错误处理打下了基础。接下来,我研究了Rust中的**结构体**和**枚举**,这两者是Rust数据建模的核心工具。通过定义常规结构体、元组结构体和单元结构体,我体会到了Rust在数据表示上的灵活性。尤其是在枚举的使用中,我学会了如何通过模式匹配来处理不同类型的值,这让代码更加简洁且易于维护。 | ||
|
||
在处理**字符串**时,我深入了解了Rust中`String`与`str`类型的差异,以及它们在内存管理中的不同表现。我通过字符串切片、拼接等操作,进一步掌握了Rust如何高效地处理内存。对于Rust的**模块系统**,我学习了如何通过`pub`关键字控制模块的可见性,并使用`use`语句引入外部模块,逐步掌握了Rust的模块化管理和命名空间管理技巧。 | ||
|
||
通过操作**HashMap**,我加深了对哈希表这种数据结构的理解。尤其是在函数间传递哈希表时,我学习了如何处理生命周期问题,确保数据在访问时的安全性。在**错误处理**方面,我通过`Option`和`Result`类型的应用,掌握了Rust中优雅的错误处理机制,学习了如何通过模式匹配有效地捕捉和处理错误。 | ||
|
||
在学习**泛型**和**性状**时,我认识到泛型使得Rust的代码更加灵活和可复用,而性状则赋予了类型更多的行为定义能力。通过实现和使用性状,我体会到了Rust的面向对象编程思想与函数式编程思想的结合。**生命周期**的学习使我更清晰地理解了Rust的内存管理机制,特别是在避免悬空引用和内存泄漏方面,通过生命周期注解,我能够精确控制数据的有效期,确保内存的安全使用。 | ||
|
||
通过对**迭代器**和**智能指针**(如`Rc`、`Arc`、`Box`)的学习,我掌握了Rust如何高效地处理集合数据和内存管理,尤其是智能指针帮助我理解了如何管理共享内存和避免内存泄漏的问题。最后,**宏**的学习让我认识到宏在Rust中的重要性,它不仅简化了代码,还提高了代码的复用性和灵活性。**多线程编程**部分则让我进一步理解了Rust的线程模型,学会了如何在保证数据安全的前提下,进行并发操作。 | ||
|
||
总结来说,通过本次实验,我不仅强化了对Rust基础概念的理解,还深入学习了Rust在内存管理、类型系统以及并发编程方面的独特设计。通过实验中的实际操作,我能够更熟练地使用Rust编写健壮、高效的代码,进一步提升了我的编程能力。 | ||
|
||
## 第二阶段实验总结 | ||
|
||
### 引言 | ||
|
||
在操作系统的开发过程中,系统调用是操作系统与用户程序之间的接口,负责提供底层的服务与功能。在本次操作系统实验中,我们实现了几个核心系统调用,包括任务信息查询、内存映射、进程创建等功能。通过实现这些系统调用,我们可以深入理解操作系统的基本原理,如进程管理、内存管理和调度机制。此外,我们还探讨了如何利用不同的调度算法优化任务调度,尤其是通过实现 Stride 调度算法来确保系统中各个进程能够公平地获得 CPU 时间。本文将详细介绍这些系统调用的设计与实现思路。 | ||
|
||
### 任务信息查询:`sys_task_info` | ||
|
||
`sys_task_info` 系统调用的主要目的是提供关于当前正在运行的任务的详细信息。每当操作系统需要调试或监控任务时,可以通过调用这个系统调用来获取相关的任务状态、系统调用次数和任务运行时间等信息。操作系统维护每个进程的相关数据,包括进程的状态、系统调用的计数和执行时间等,而这些信息对于开发人员调试系统、分析性能至关重要。 | ||
|
||
为了实现 `sys_task_info`,我们首先需要获取当前进程的相关信息。这通常通过存储在进程控制块(PCB)中的数据实现,PCB 记录了每个进程的状态、CPU 寄存器的值、已执行时间以及系统调用计数等信息。当用户或系统调用 `sys_task_info` 时,操作系统会返回当前任务的这些信息,包括任务的运行状态(如就绪、运行、等待等),系统调用的数量,以及进程自启动以来已经占用的 CPU 时间。通过这些信息,开发人员可以判断进程的执行状态,分析是否存在性能瓶颈或资源争用等问题。 | ||
|
||
### 内存映射与取消映射:`sys_mmap` 和 `sys_munmap` | ||
|
||
在现代操作系统中,虚拟内存是每个进程独立的内存空间,而物理内存则是实际存在的硬件资源。为了有效地利用物理内存,操作系统采用虚拟内存与物理内存之间的映射机制。`sys_mmap` 系统调用的功能是将虚拟地址空间映射到物理内存上。通过 `mmap`,操作系统可以将某个文件的内容映射到进程的虚拟内存中,从而让程序可以像访问内存一样直接访问文件数据,而不需要每次都通过传统的 I/O 操作。 | ||
|
||
在实现 `sys_mmap` 时,操作系统首先检查请求的虚拟地址是否有效,并验证内存区域是否已经被映射。如果没有冲突,操作系统将通过页表将虚拟地址映射到物理地址。这需要操作系统处理页表的更新,并确保映射区域的权限设置正确。例如,映射的内存区域可能是可读、可写或可执行,操作系统需要为每个映射区域设置合适的访问权限,以避免非法访问或数据损坏。 | ||
|
||
与 `sys_mmap` 相对的 `sys_munmap` 系统调用则负责取消已经映射的虚拟内存区域。当进程不再需要某段内存时,可以调用 `munmap` 来解除映射。操作系统需要确保取消映射时,虚拟地址没有其他进程在使用,同时也需要回收该内存区域所占用的物理资源。为了实现这一点,操作系统会更新页表,释放相关的物理内存,并将其标记为可重用。通过这种方式,操作系统能够有效管理内存资源,避免内存泄漏和浪费。 | ||
|
||
### 进程创建:`sys_spawn` | ||
|
||
进程创建是操作系统中非常重要的一部分功能。通过 `sys_spawn` 系统调用,操作系统可以根据用户给定的程序路径创建一个新的进程,并将该进程添加到调度队列中。进程创建的过程涉及多个步骤,包括路径验证、程序加载、内存分配和任务调度等。 | ||
|
||
在实现 `sys_spawn` 时,操作系统首先需要验证用户提供的程序路径是否有效。这意味着操作系统必须能够访问到指定的文件,并确认该文件是一个有效的可执行文件。接着,操作系统会为新进程分配一个进程控制块(PCB),用于保存该进程的状态、寄存器信息、内存映射、文件描述符等关键数据。然后,操作系统将程序的内容加载到新进程的虚拟内存中,并为其分配栈、堆等内存区域。 | ||
|
||
一旦新进程的资源分配完成,操作系统会将其添加到调度队列中,等待 CPU 的调度。此时,进程已经具备了执行的基本条件,可以在操作系统的控制下执行。在实际的操作系统中,进程的创建还会涉及到权限管理、父子进程关系的维护以及资源继承等问题,这些都是确保系统稳定和安全运行的关键部分。 | ||
|
||
### Stride 调度算法 | ||
|
||
进程调度是操作系统中的一个核心任务,关系到系统性能和资源利用率。Stride 调度算法是一种基于权重的调度策略,旨在通过分配不同的权重来实现不同进程之间的公平调度。在 Stride 调度中,每个进程被分配一个 `stride` 值,该值与进程的优先级相关,优先级较高的进程将获得较小的 `stride` 值,而优先级较低的进程将获得较大的 `stride` 值。每个进程在执行时消耗一定的 `stride`,当它的 `stride` 值达到一定阈值时,该进程就会被调度执行。 | ||
|
||
Stride 调度算法的优点在于,它能够在多任务环境下有效地保证进程之间的公平性。每个进程的调度机会与其 `stride` 值成反比,这意味着优先级较高的任务会被调度得更频繁,而优先级较低的任务则会较少获得 CPU 时间。每当一个进程被调度执行后,操作系统会更新该进程的 `stride` 值,使得其调度机会逐渐减少,从而避免了高优先级进程过度占用 CPU 资源的问题。 | ||
|
||
通过实现 Stride 调度算法,操作系统能够根据每个进程的优先级动态地调整其调度频率。高优先级的任务能够更快速地完成,而低优先级的任务则能够平衡获得一定的执行时间,避免了优先级反转和过度竞争 CPU 的情况。这种方法提高了系统资源的使用效率,同时也保持了调度的公平性。 | ||
|
||
### 结语 | ||
|
||
本次操作系统实验通过实现多个核心功能,深入探讨了系统调用的原理与实现方法。通过任务信息查询、内存映射与取消映射、进程创建等功能的实现,我们不仅加深了对操作系统基本原理的理解,也锻炼了我们如何设计和实现高效的内核功能。同时,Stride 调度算法的实现则帮助我们理解了操作系统如何管理进程的调度和资源分配,以保证公平性和系统性能。 | ||
|
||
这些操作系统的核心机制为我们未来开发更复杂、更高效的操作系统打下了坚实的基础。在实际的操作系统开发过程中,继续优化调度算法、内存管理、进程调度等底层功能,是提高操作系统性能、稳定性和可扩展性的关键。通过这次实验,我们不仅掌握了这些技术的实现方法,还为我们在更大规模的操作系统设计中奠定了理论基础。 | ||
|
||
--- | ||
|
||
### 2024 秋冬季开源操作系统训练营第三阶段总结 - 卓堂越 | ||
|
||
通过第三阶段的学习,我深入理解了组件化操作系统内核的设计理念。这种思想强调以模块化方式构建内核,能够根据实际需求增量式地扩展功能,从而在不同场景下灵活构建各种模式的内核。具体而言,这种方法能够带来以下显著优势: | ||
|
||
1. **提高开发效率**:模块化设计减少了重复工作,使开发者可以快速实现复杂功能。 | ||
2. **降低维护难度**:各模块间解耦降低了修改与调试的成本。 | ||
3. **促进功能复用与协作**:组件化方法支持功能模块的复用与团队协作开发。 | ||
|
||
#### 学习成果回顾 | ||
|
||
**第一周** | ||
学习了 **Unikernel** 的增量开发方法。从一个简单的内核开始,逐步扩展了文件系统等模块。同时,完成了基础设施建设,包括实现 `HashMap` 和简单的内存分配算法,并掌握了终端控制的技巧。 | ||
|
||
**第二周** | ||
通过组件化设计,将 Unikernel 扩展为 **Monolithic Kernel**。深入学习了 RISC-V 架构,以及 Arceos 中的线程控制设计。除此之外,我还完成了缺页异常处理,并实现了基本的 Unix 工具功能。 | ||
|
||
**第三周** | ||
了解了虚拟化的基本原理,并基于模块化方法为 Arceos 添加了虚拟化支持。具体包括虚拟设备接口和多虚拟机支持,同时优化了系统性能与架构设计。 | ||
|
||
#### 收获与展望 | ||
|
||
本阶段的学习让我切身感受到组件化设计在操作系统开发中的强大优势。通过将复杂问题拆解为模块,开发变得更加高效,系统也更易于维护。未来,我希望能将这一思想应用于更多实际项目中,持续提升内核开发能力,打造高效且可靠的系统。 | ||
|
||
--- |