rust写操作系统 rCore tutorial 学习笔记:实验指导四 进程与线程

本文是os summer of code 2020项目的一部分,记录了学习rCore Tutorial Lab4的过程,内容涉及线程和进程的概念、线程的创建与切换、内核栈以及简单的调度器实现。通过建立线程上下文,实现了线程的执行与切换,探讨了内核栈在中断处理中的作用,并设计了一个初步的调度器。
摘要由CSDN通过智能技术生成

这是 os summer of code 2020 项目每日记录的一部分:
每日记录github地址(包含根据实验指导实现的每个阶段的代码):https://github.com/yunwei37/os-summer-of-code-daily

这里参考的是rCore tutorial的第三版:https://github.com/rcore-os/rCore-Tutorial

lab4 学习报告

lab4 涉及:

  • 线程和进程的概念以及运行状态的表示
  • 线程的切换
  • 对 CPU 进行抽象在上面完成对线程的调度

lab4 的代码将会在 lab3 完成的代码上面继续进行改动;

线程和进程

  • 程序(Program):从源代码经过编译器一系列处理(编译、链接、优化等)得到的可执行文件
  • 进程(Process):正在运行并使用计算机资源的程序
  • 线程 (Thread) :借助 CPU 和栈的执行流

首先,进程得到了操作系统提供的资源:程序的代码、数据段被加载到内存中,程序所需的虚拟内存空间被真正构建出来。同时操作系统还给进程分配了程序所要求的各种其他资源,如我们上面几个章节中提到过的页表、文件的资源。一个进程可以有多个线程,也可以如传统进程一样只有一个线程。

  • 资源的分配单位:进程
  • 执行的调度单位:线程

线程的表示

在这里我们提供一种基础的实现,每个线程会包括:

  • 线程 ID
  • 运行栈
  • 线程执行上下文 ( Context 类型 )
  • 所属进程的记号
  • 内核栈

新建一个 process 文件夹:

先添加一个 mod.rs:


mod config;
mod kernel_stack;
#[allow(clippy::module_inception)]
mod process;
mod processor;
mod thread;

use crate::interrupt::*;
use crate::memory::*;
use alloc::{sync::Arc, vec, vec::Vec};
use spin::{Mutex, RwLock};

pub use config::*;
pub use kernel_stack::KERNEL_STACK;
pub use process::Process;
pub use processor::PROCESSOR;
pub use thread::Thread;

再添加

os/src/process/thread.rs:

包含线程的数据结构:

//! 线程 [`Thread`]

use super::*;
use crate::fs::*;
use core::hash::{Hash, Hasher};

/// 线程 ID 使用 `isize`,可以用负数表示错误
pub type ThreadID = isize;

static mut THREAD_COUNTER: ThreadID = 0;

/// 线程的信息
pub struct Thread {
    /// 线程 ID
    pub id: ThreadID,
    /// 线程的栈
    pub stack: Range<VirtualAddress>,
    /// 所属的进程
    pub process: Arc<RwLock<Process>>,
    /// 用 `Mutex` 包装一些可变的变量
    pub inner: Mutex<ThreadInner>,
}

/// 线程中需要可变的部分
pub struct ThreadInner {
    /// 线程执行上下文
    ///
    /// 当且仅当线程被暂停执行时,`context` 为 `Some`
    pub context: Option<Context>,
    /// 是否进入休眠
    pub sleeping: bool,
    /// 是否已经结束
    pub dead: bool,
    /// 打开的文件
    pub descriptors: Vec<Arc<dyn INode>>,
}

进程的表示

进程只需要维护页面映射,并且存储一点额外信息:

  • 用户态标识:我们会在后面进行区分内核态线程和用户态线程。
  • 访存空间 MemorySet:进程中的线程会共享同一个页表,即可以访问的虚拟内存空间(简称:访存空间)。

创建:os/src/process/process.rs

进程的数据结构:

//! 进程 [`Process`]

use super::*;
use xmas_elf::ElfFile;

/// 进程的信息
pub struct Process {
    /// 是否属于用户态
    pub is_user: bool,
    /// 进程中的线程公用页表 / 内存映射
    pub memory_set: MemorySet,
}

实际上这部分有一些代码和第五章的部分内容交织在了一起。

线程的创建

第一个目标就是创建一个线程并且让他运行起来。

一个线程要开始运行,需要这些准备工作:

  • 建立页表映射,需要包括以下映射空间:
    • 线程所执行的一段指令
    • 线程执行栈
    • 操作系统的部分内存空间
  • 设置起始执行的地址
  • 初始化各种寄存器,比如 sp
  • 可选:设置一些执行参数(例如 argc 和 argv等 )

思考:为什么线程即便与操作系统无关,也需要在内存中映射操作系统的内存空间呢?

  • 简单来说,需要使用内核来处理中断。
  • 我们会为每个进程的页表映
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值