首页
关于
Search
1
2023 年保研经验贴 [计算机-末九Rank50%-入北计清深-北计直博]
1,104 阅读
2
FreeBSD Kernel-编译环境搭建
411 阅读
3
Linux Kernel-THP阅读分析[Hang up]
402 阅读
4
Linux Kernel-编译调试环境搭建
319 阅读
5
Linux Kernel-源码阅读环境搭建
305 阅读
内核
源码分析
阅读笔记
Rust
语法
习题
读书笔记
深入理解计算机系统
论文
技术之外
开发
rcore-arm
登录
Search
yyi
累计撰写
49
篇文章
累计收到
2
条评论
首页
栏目
内核
源码分析
阅读笔记
Rust
语法
习题
读书笔记
深入理解计算机系统
论文
技术之外
开发
rcore-arm
页面
关于
搜索到
2
篇与
的结果
2024-02-24
rCore-Tutorial #1 应用程序与基本执行环境[WIP]
概述第一章就一个基本目标,说起来很快,实际上难度不小:隔离应用与硬件。更像一堆库函数,为硬件提供一层简单接口,让应用可以通过这层接口访问硬件。阶段一的OS称为LibOS这个系统的bootloader由RustSBI完成,OS负责为APP初始化加载环境,然后就跳转到app执行,app通过函数调用获得OS提供的输出字符串等服务。移除标准库依赖我跳过了第一节,老知识了,需要的同学自行查阅吧。本节目标是构建一个最小环境,使得程序可以打印Hello, world。在之前的编程里,我们都是通过Rust std实现的,我们要扔掉std(std本身也依赖于系统调用),直达硬件。移除println!我们首先准备一个干净的环境,在原来基础上checkout到我们自己的分支git checkout -b my_ch1 rm -rf os # 新建我们的项目 cargo new os # 修改编译target arch cd os && mkdir .cargo echo '# os/.cargo/config [build] target = "riscv64gc-unknown-none-elf"' \ >> .cargo/config此时编译,会出现找不到std的问题当然,预料之中,我们在main的开头加上\#![no_std],告诉Rust不要用Rust标准库。Rust会自动使用不依赖os的core库我们需要提供panic_handler,来处理致命系统错误,按教程提供后,现在应该长这样:移除main中的println,再次编译的时候出现了新的错误(这个错误和教程不太一样)虽然不太一样但是意思是一致的,main本身是依赖标准库的,如果你熟悉实际上的C编程,会有印象大部分的linux ELF会有个.init,然后调用libc_start_main,才进入真正的main函数。main只是对编译器有意义罢了,并不是说我们一定必须进去。所以,我们把main删掉,按编译提示加入no_main注解。此时的程序终于可以通过编译了,不过也有点可怜接下来会二进制分析已经编译出的程序,看看我们应该怎么办入口点是0,0显然不会是一个可执行的代码地址内核的第一条指令这节分为基础篇和实践篇,我们从基础篇的第二节开始,看看Qemu是怎么执行的。(其他知识已经很熟了,我这边先行跳过,同学有需要可以自行查阅)Qemu启动qemu会把bootloader和内核镜像分别加载到0x80000000 (虚拟设备内存起始地址)和0x80200000(我们指定的地址),具体如何boot是由rustsbi帮我们完成的。正常的Boot会有Bios引导,先把bootloader加载到内存,然后控制权转交给bootloader,bootloader对CPU初始化,把OS加载到内存,最后把控制权流转给内核。但是我们这不是个正常的boot,由qemu负责把bootloader和os都加载到内存,再把控制权流转给bootloader,不管怎么样,我们知道RustSBI帮我们初始化了一些事,只要我们能控制0x80200000,我们就能获得CPU控制权了。编写第一条指令 # os/src/entry.asm .section .text.entry .globl _start _start: li x1, 100它只执行了一条简单的指令,即l(oad)i(mm) x1, 100把立即数100赋值给寄存器x1这里还定义了全局符号_start,并声明这段代码应该在.text.entry上,我们把这段汇编嵌入到rust中。并通过它检测qemu是否正确的把控制权流转给了我们的代码当然,做到这还不够,我们希望指令出现在0x80200000,熟悉编译的同学都知道,这个最后在哪是链接器决定的,所以通过修改cargo配置文件,我们使用自定义链接器。 // os/.cargo/config [build] target = "riscv64gc-unknown-none-elf" [target.riscv64gc-unknown-none-elf] rustflags = [ "-Clink-arg=-Tsrc/linker.ld", "-Cforce-frame-pointers=yes" ]// os/src/linker.ld OUTPUT_ARCH(riscv) ENTRY(_start) BASE_ADDRESS = 0x80200000; SECTIONS { . = BASE_ADDRESS; skernel = .; stext = .; .text : { *(.text.entry) *(.text .text.*) } . = ALIGN(4K); etext = .; srodata = .; .rodata : { *(.rodata .rodata.*) *(.srodata .srodata.*) } . = ALIGN(4K); erodata = .; sdata = .; .data : { *(.data .data.*) *(.sdata .sdata.*) } . = ALIGN(4K); edata = .; .bss : { *(.bss.stack) sbss = .; *(.bss .bss.*) *(.sbss .sbss.*) } . = ALIGN(4K); ebss = .; ekernel = .; /DISCARD/ : { *(.eh_frame) } }配置过程文档里都有,我不赘述了这块的意思就是把所有目标文件的.text.entry段、.text段,.text.*段都放到最后链接完毕的文件的.text段中,这里的*统统是通配符,括号外代表目标文件,括号内代表目标文件的段。按从上到下的顺序组织,以BASE_ADDRESS为基准偏移。小功告成!此时我们是不是可以直接扔给qemu了呢?别急还有点早。因为qemu会把整个ELF load到它的物理内存里。我们的代码段之前是存在一些其他的元信息的,通过objcopy直接获得程序真正的部分rust-objcopy --strip-all target/riscv64gc-unknown-none-elf/release/os \ -O binary target/riscv64gc-unknown-none-elf/release/os.bin
2024年02月24日
84 阅读
0 评论
0 点赞
2024-02-23
rCore-Tutorial #0 实验环境配置
当你看到这个标题,是的,我要开个大坑了,而且难度很高,貌似没有什么现成的资料。ipads著名的chcore是基于arm架构的,但是是C开发的,清华著名的rcore是RISCV架构的,但是是Rust开发的。我想搞一个Rust+AArch64的Kernel,显然,我既不怎么会Rust,又不怎么会ARM,我也就只剩一颗想做的心了。当然,如果最后真的搞不下去,我也想至少把rCore-RISCV这个Lab做完做好。我不知道是迁移chcore更难,还是迁移rcore更难,先选一个吧,迁移chcore面对的是Rust的大量特质要重构,迁移rcore面对的是架构差异,从引导、中断到分页都要重构。但是毕竟是给人写的嘛。这个环境配置Chapter我可能还会慢慢的更新,也可能更的不全,有的小依赖可能随手就安了忘记更新,只能说尽量做吧。希望真的能把这个项目做到最后。0 环境配置 参考链接Rust开发环境配置export RUSTUP_DIST_SERVER=https://mirrors.ustc.edu.cn/rust-static export RUSTUP_UPDATE_ROOT=https://mirrors.ustc.edu.cn/rust-static/rustup curl https://sh.rustup.rs -sSf | sh source "$HOME/.cargo/env" > rustc 1.76.0 (07dca489a 2024-02-04)文档中说必须要nightly版本,关于Nightly版本是什么:Rust版本说明我们也切换到nightlyrustup install nightly rustup default nightly这里出现了个小插曲,VM空间不够了,稍稍扩容一下,没想到扩容也没那么简单插曲这里df -h可以看到sda3已经满了fdisk -l在VMWare的图形化界面操作后运行fdisk /dev/sda 并跟着输入n,然后一路回车,最后p一下n是新建分区,p是打印如果正确新建了一个Linux filesystem分区,按w写入分区表,然后reboot下我发现这么搞太麻烦了,反正我有快照,如果直接干掉sda3的分区表,新建分区,能行么,大胆操作一下fdisk里生效了,df里没生效,根据我搞FreeBSD的经验,要growfs一下resize2fs /dev/sda3插曲结束,大功告成。安装完nightly之后,应该有如下输出(版本号不对无所谓)❯ rustc --version rustc 1.78.0-nightly (3406ada96 2024-02-21)crates换源,不赘述安装rust软件包的时候,原文档只给了 riscv64gc-unknown-none-elf 作为交叉编译的target,我们还要加一个aarch64-unknown-nonerustup target add riscv64gc-unknown-none-elf rustup target add aarch64-unknown-none cargo install cargo-binutils # 后面这俩我这时候不能用清华源 rustup component add llvm-tools-preview rustup component add rust-src这俩都是Tier2的Support,应该不会有太大问题 Platform SupportQEMU环境这东西对我来说比较熟悉,可能会简略一点sudo apt-get install autoconf automake autotools-dev curl libmpc-dev libmpfr-dev libgmp-dev \ gawk build-essential bison flex texinfo gperf libtool patchutils bc \ zlib1g-dev libexpat-dev pkg-config libglib2.0-dev libpixman-1-dev libsdl2-dev \ git tmux python3 python3-pip ninja-build别管有没有了安装一把梭其实纠结了一下,Tutoial给定的是qemu 7.0.0 实验,但是本文撰写时qemu已经是这个状态了:搜了一下,看到了这个:我超,可能是要硬着头皮上Qemu8了,一步到位!(虽然我知道这大概率不是一个明智的选择,比起很低概率会用上的新支持,更大概率是会遇到和教程版本不一致导致的问题,但是谁管呢?真的有人不喜欢用新的东西么?)wget https://download.qemu.org/qemu-8.2.1.tar.xz # 可能会有点慢,有条件上proxy吧 tar xJvf qemu-8.2.1.tar.xz 此时要参考一下qemu的官方文档,看看我们选择啥targets,当然不嫌费劲可以直接全部编译可能不用参考了,就选这四个吧./configure --target-list=riscv64-softmmu,riscv64-linux-user,aarch64-linux-user,aarch64-softmmu make -j16在编译目录的./build目录下即可看到编译完的qemu,添加到PATH中跑起来!git clone git@github.com:rcore-os/rCore-Tutorial-v3.git cd os make run
2024年02月23日
145 阅读
0 评论
0 点赞