2023年秋季开源操作系统训练营:第一阶段

[toc]

初识rust

认识cargo

  • rust的包管理:cargo

  • cargo的编译和运行

    1
    $ cargo run --release
  • cargo代码检查 cargo check ==快速的检查一下代码能否编译通过。因此该命令速度会非常快,能节省大量的编译时间。==

    1
    $ cargo check
  • cargo toml lock文件的作用

    toml 项目数据描述文件

    lock 项目依赖详细清单

认识rust语言

  • 声明变量:

    • 不必和变量类型一起声明
  • if 语句:

    可以放在let语句的右侧

    1
    let number if condition {5} else {6};
  • loop循环和标签

    • break使用 break+标签可以break指定循环(用于嵌套loop中)
    • break+loop中的变量相当于return一个变量
  • rust的所有权(??)

    • 所有权的基本规则:
      • 每一个==值==都有一个称为其“所有者”的==变量==
      • 每一个值有且仅有一个变量
      • 当所有者离开作用域的时候值也没有了

所有权感觉上是对指针的管理,rust不允许指向同一个地址的指针被多个变量同时所表示。所以rust就不可能存在指针空悬的情况(以及重复释放);

rust如何实现这种特性?

当值的所有权第一次移交的时候原变量就会变成未初始化的变量,新的变量就会被赋值为原变量的值(这些静态分析由编译器完成!)

image-20231011165303106

image-20231011165317153

  • 引用和借用
    • 可变引用

如何去理解OPTION 概念

Some()是个什么玩意儿!:crying_cat_face: 相关内容 as follow:

在Some判断的时候括号中的变量的所有权似乎也会改变

OK是个什么玩意儿

rustlings 练习

rustlings的练习有些还是一知半解

RISC-V学习

rCore

编写一个原生的不依赖的程序

前置

将rustc 的默认target生成的目标为一个没有任何依赖的平台riscv64gc-unknown-none-elf

第一步,执行内核第一条指令

  • 移除println!宏

默认函数上添加#![no_std];待标准库移除后还要添加panic宏,(既然移除了,所以得自己写【】)

  • 写一个简陋的panic

缺少一个start 语义项。第三方库和标准库在执行之前需要进行初始化【默认的!】。如果不想使用这个功能(就像在当前的情况下)可以添加#![no_main]特性

start 语义项代表了标准库 std 在执行应用程序之前需要进行的一些初始化工作。

  • 编写系统的入口自定义链接动作(编译系统前)
  • 系统编译后将初始的含有额外信息的头去掉,交给bootloader内核的加载就完成了

第二步,为内核支持函数调用

不过为了将控制权转交给我们使用 Rust 语言编写的内核入口函数,我们确实需要手写若干行汇编代码进行一定的初始化工作.

这些汇编代码放在 entry.asm 中,并在控制权被转交给内核相关函数前最先被执行

实现步骤:

  • 在entry.asm中设置栈空间
  • 调用rust编写的内核入口函数

相关知识:

riscv的跳转指令:jal jalr

所有的riscv的指令长度一样都是4字节。

  • 调用者保存寄存器:调用者来保证在调用后该寄存器中的内容不变
  • 被调用者保存寄存器:同理

开场和结尾动作(由编译器帮我们完成)

==调用规范==

过程调用再学习。

IA-32的函数调用规范:

  • 被调用函数q保存调用者寄存器
  • q将p的参数保存到==栈里面==
  • q将返回地址保存到栈里面
  • p将q的EBP保存到栈中,并将EBP设置为当前指向(当前保存q的ebp的指针)【EBP也是一个被调用者保存寄存器】
  • 做其他事情
  • 。。。

riscv调用规范

ra是一个被调用者保存寄存器,每个过程在其栈中保存的是自己结束后的下一个指令的地址,在ret之间要将这个内容放到ra中???

entry.asm解读:

初始化栈

在entry中设置初始的栈空间大小,栈的起始地点。

清零bss段