From 4a6a6c6853d67cfab481f3390ba2038cdd24a486 Mon Sep 17 00:00:00 2001 From: Zhiyuan Shao Date: Fri, 23 Jul 2021 10:01:22 +0800 Subject: [PATCH] aa --- chapter2_installation.md | 151 +++++++++++---------------- pictures/experiment_organization.png | Bin 0 -> 14826 bytes 2 files changed, 59 insertions(+), 92 deletions(-) create mode 100644 pictures/experiment_organization.png diff --git a/chapter2_installation.md b/chapter2_installation.md index b04e52f..bf3fc7a 100644 --- a/chapter2_installation.md +++ b/chapter2_installation.md @@ -1,16 +1,20 @@ -# 第二章.实验环境的安装与使用 +# 第二章.实验环境配置与实验构成 ### 目录 -- [2.1 头歌平台](#educoder) -- [2.2 Ubuntu操作系统的配置](#ubuntu) -- [2.3 openEuler操作系统配置](#openeuler) -- [2.4 riscv-pke(实验)代码的获取](#preparecode) +- [2.1 实验环境安装](#environments) + - [2.1.1 头歌平台](#subsec_educoder) + - [2.1.2 Ubuntu操作系统环境](#subsec_ubuntu) + - [2.1.3 openEuler操作系统环境](#subsec_openeuler) +- [2.2 riscv-pke(实验)代码的获取](#preparecode) +- [2.3 PKE实验构成](#pke_experiemnts) + +## 2.1 实验环境安装 - + -## 2.1 头歌平台 +### 2.1.1 头歌平台 PKE实验在[头歌平台](https://www.educoder.net/)上进行了部署,但因为仍在测试阶段,所以没有开放全局选课(感兴趣的读者可以尝试邀请码:2T8MA)。PKE实验(2.0版本)将于2021年秋季在头歌平台重新上线,届时将开放全局选课。 @@ -22,17 +26,21 @@ PKE实验在[头歌平台](https://www.educoder.net/)上进行了部署,但因 - + -## 2.2 Ubuntu环境 +### 2.1.2 Ubuntu操作系统环境 实验环境我们推荐采用Ubuntu 16.04LTS或18.04LTS(x86_64)操作系统,我们未在其他系统(如arch,RHEL等)上做过测试,但理论上只要将实验中所涉及到的安装包替换成其他系统中的等效软件包,就可完成同样效果。另外,我们在EduCoder实验平台(网址:https://www.educoder.net )上创建了本书的同步课程,课程的终端环境中已完成实验所需软件工具的安装,所以如果读者是在EduCoder平台上选择的本课程,则可跳过本节的实验环境搭建过程,直接进入通过终端(命令行)进入实验环境。 -PKE实验涉及到的软件工具有:RISC-V交叉编译器、spike模拟器,以及PKE源代码三个部分。假设读者拥有了Ubuntu 16.04LTS或18.04LTS(x86_64)操作系统的环境,以下分别介绍这三个部分的安装以及安装后的检验过程。需要说明的是,为了避免耗时耗资源的构建(build)过程,一个可能的方案是从https://toolchains.bootlin.com 下载,**但是要注意一些依赖包(如GCC)的版本号**。 +PKE实验涉及到的工具软件有: -**我们强烈建议读者在新装环境中完整构建(build)RISC-V交叉编译器,以及spike模拟器**。如果强调环境的可移植性,可以考虑在虚拟机中安装完整系统和环境,之后将虚拟机进行克隆和迁移。 +- RISC-V交叉编译器(及附带的主机编译器、构造工具等); +- spike模拟器; -### 2.1.1 RISC-V交叉编译器 + +以下分别介绍这两个部分的安装过程。对于新安装的Ubuntu操作系统,**我们强烈建议读者在新装环境中完整构建(build)RISC-V交叉编译器,以及spike模拟器**。(对于熟练用户)为了避免耗时且耗资源的构建(build)过程,一个可能的方案是从https://toolchains.bootlin.com 下载,**但是要注意一些依赖包(如GCC)的版本号**。如果强调环境的可移植性,可以考虑在虚拟机中安装完整系统和环境,之后将虚拟机进行克隆和迁移。 + +#### 2.1.1 RISC-V交叉编译器 RISC-V交叉编译器是与Linux自带的GCC编译器类似的一套工具软件集合,不同的是,x86_64平台上Linux自带的GCC编译器会将源代码编译、链接成为适合在x86_64平台上运行的二进制代码(称为native code),而RISC-V交叉编译器则会将源代码编译、链接成为在RISC-V平台上运行的代码。后者(RISC-V交叉编译器生成的二进制代码)是无法在x86_64平台(即x86_64架构的Ubuntu环境下)直接运行的,它的运行需要模拟器(我们采用的spike)的支持。 @@ -78,7 +86,7 @@ RISC-V交叉编译器的构建需要一些本地支撑软件包,可使用以 以上命令设置了RISCV环境变量,指向在第三步中的安装目录,并且将交叉编译器的可执行文件所在的目录加入到了系统路径中。这样,我们就可以在PKE的工作目录调用RISC-V交叉编译器所包含的工具软件了。 -### 2.1.2 spike模拟器 +#### 2.1.2 spike模拟器 接下来,安装spkie模拟器。首先取得spike的源代码,有两个途径:一个是从github代码仓库中获取: @@ -98,99 +106,44 @@ RISC-V交叉编译器的构建需要一些本地支撑软件包,可使用以 在以上命令中,我们假设RISCV环境变量已经指向了RISC-V交叉编译器的安装目录。如果未建立关联,可以将$RISCV替换为2.1.1节中的[your.RISCV.install.path]。 -### 2.1.3 PKE - -到github下载课程仓库: - -`$ git clone https://github.com/MrShawCode/pke.git` - -克隆完成后,将在当前目录看到pke目录。这时,可以到pke目录下查看pke的代码结构,例如: - -`$ cd pke` - -`$ ls` -你可以看到当前目录下有如下(部分)内容 -. - -├── app - -├── gradelib.py - -├── machine - -├── Makefile + -├── pk +### 2.1.3 openEuler操作系统 -├── pke-lab1 - -├── pke.lds - -└── util - -● 首先是app目录,里面存放的是实验的测试用例,也就是运行在User模式的应用程序,例如之前helloworld.c。 - -● gradelib.py、与pke-lab1是测试用的python脚本。 - -● machine目录,里面存放的是机器模式相关的代码,由于本课程的重点在于操作系统,在这里你可以无需详细研究。 - -● Makefile文件,它定义的整个工程的编译规则。 - -● pke.lds是工程的链接文件。 - -● util目录下是各模块会用到的工具函数。 +PKE实验将提供基于华为openEuler操作系统的开发方法,*具体的华为云使用方法待续*,但在openEuler操作系统环境中的交叉编译器安装方法,以及其他环节都可参考[2.2 Ubuntu环境](#ubuntu)的命令进行。 -● pk目录,里面存放的是pke的主要代码。 -即使未开始做PKE的实验,我们的pke代码也是可构建的,可以采用以下命令(在pke目录下)生成pke代理内核: -`$ make` + -以上命令完成后,会在当前目录下会生产obj子目录,里面就包含了我们的pke代理内核。pke代理内核的构建过程,将在2.2节中详细讨论。 +## 2.2 riscv-pke(实验)代码的获取 -### 2.1.4 环境测试 +以下讨论,我们假设读者是使用的Ubuntu/openEuler操作系统,且已按照[2.1.2](#subsec_ubuntu)的说明安装了需要的工具软件。对于头歌平台而言,代码已经部署到实验环境,读者可以通过头歌网站界面或者界面上的“命令行”选项看到实验代码,所以头歌平台用户无须考虑代码获取环节。 -全部安装完毕后,你可以对环境进行测试,在pke目录下输入: +#### 代码获取 -`$ spike ./obj/pke ./app/elf/app1_2` +在Ubuntu/openEuler操作系统,可以通过以下命令下载riscv-pke的实验代码: -将得到如下输出: +(克隆代码仓库) ``` -PKE IS RUNNING -user mode test illegal instruction! -you need add your code! +`$ git clone https://gitee.com/hustos/riscv-pke-prerelease.git +Cloning into 'riscv-pke-prerelease'... +remote: Enumerating objects: 195, done. +remote: Counting objects: 100% (195/195), done. +remote: Compressing objects: 100% (195/195), done. +remote: Total 227 (delta 107), reused 1 (delta 0), pack-reused 32 +Receiving objects: 100% (227/227), 64.49 KiB | 335.00 KiB/s, done. +Resolving deltas: 100% (107/107), done.` ``` -以上命令的作用是首先采用spike模拟一个RISC-V机器,该机器支持RV64G指令集,并在该机器上运行./app/elf/app1_2应用(它的源代码在./app/app1_2.c中)。我们知道,应用是无法在“裸机”上运行的,所以测试命令使用./obj/pke作为应用的代理内核。代理内核的作用,是对spike模拟出来的RISC-V机器做简单的“包装”,使其能够在spike模拟出来的机器上顺利运行。 - -这里,代理内核的作用是只为特定的应用服务(如本例中的./app/elf/app1_2应用),所以可以做到“看菜吃饭”的效果。因为我们这里的应用非常简单,所以pke就可以做得极其精简,它没有文件系统、没有物理内存管理、没有进程调度、没有操作终端(shell)等等传统的完整操作系统“必须”具有的组件。在后续的实验中,我们将不断提升应用的复杂度,并不断完善代理内核。通过这个过程,读者将深刻体会操作系统内核对应用支持的机制,以及具体的实现细节。 - - -## 2.3 openEuler操作系统 - -PKE实验将提供基于华为openEuler操作系统的开发方法,*具体的华为云使用方法待续*,但在openEuler操作系统环境中的交叉编译器安装方法,以及其他环节都可参考[2.2 Ubuntu环境](#ubuntu)的命令进行。 - - +克隆完成后,将在当前目录应该能看到riscv-pke-prerelease目录。这时,可以到riscv-pke目录下查看文件结构,例如: - - -## 2.4 riscv-pke(实验)代码的获取 - -获取riscv-pke代码前,需要首先确认你已经按照[第二章](chapter2_installation.md)的要求完成了开发环境的构建(这里,我们假设环境是基于Ubuntu或者openEular,头歌环境下更多的是界面操作,所以无需通过命令行获取代码)。 - -环境构建好后,通过以下命令下载实验1的代码: - -(克隆代码仓库) -`$ git clone https://gitee.com/hustos/riscv-pke.git` +`$ cd riscv-pke-prerelease` -克隆完成后,将在当前目录应该能看到riscv-pke目录。这时,可以到riscv-pke目录下查看文件结构,例如: - -`$ cd riscv-pke` - -(切换到lab1_1_syscall分支) +切换到lab1_1_syscall分支(因为lab1_1_syscall是默认分支,这里也可以不切换) `$ git checkout lab1_1_syscall` `$ tree -L 3` @@ -202,6 +155,7 @@ PKE实验将提供基于华为openEuler操作系统的开发方法,*具体的 ├── LICENSE.txt ├── Makefile ├── README.md +├── grade.py ├── kernel │   ├── config.h │   ├── elf.c @@ -262,11 +216,12 @@ PKE实验将提供基于华为openEuler操作系统的开发方法,*具体的 - user目录包含了实验给定应用(如lab1_1中的app_helloworld.c),以及用户态的程序库文件(如lab1_1中的user_lib.c); - util目录包含了一些内核和用户程序公用的代码,如字符串处理(string.c),类型定义(types.h)等。 -在代码的根目录输入以下命令: -`$ make` -进行构造(build),在环境已配好(特别是交叉编译器已加入系统路径)的情况下,输出如下: +#### 环境验证 + +对于Ubuntu/openEuler用户(对于头歌用户,可以通过选择“命令行”标签,进入shell环境、进入提示的代码路径,开始构造过程),可以在代码的根目录(进入riscv-pke-prerelease子目录后)输入以下构造命令,应看到如下输出: ``` +$ make compiling util/snprintf.c compiling util/string.c linking obj/util.a ... @@ -294,6 +249,8 @@ linking obj/app_helloworld ... User app has been built into "obj/app_helloworld" ``` +如果环境安装不对(如缺少必要的支撑软件包),以上构造过程可能会在中间报错,如果碰到报错情况,请回到[2.2](#environments)的环境安装过程检查实验环境的正确性。 + 构造完成后,在代码根目录会出现一个obj子目录,该子目录包含了构造过程中所生成的所有对象文件(.o)、编译依赖文件(.d)、静态库(.a)文件,和最终目标ELF文件(如./obj/riscv-pke和./obj/app_helloworld)。 这时,我们可以尝试借助riscv-pke内核运行app_helloworld的“Hello world!”程序: @@ -312,5 +269,15 @@ call do_syscall to accomplish the syscall and lab1_1 here. System is shutting down with exit code -1. ``` -自此,riscv-pke的代码获取(和验证)已完成。 +如果能看到以上输出,riscv-pke的代码获取(和验证)就已经完成,可以开始实验了。 + + + +## 2.3 PKE实验的组成 + + + +experiment_organization + + diff --git a/pictures/experiment_organization.png b/pictures/experiment_organization.png new file mode 100644 index 0000000000000000000000000000000000000000..4badea3ad57c36e0cf7e74d4dab7dccaed93e12a GIT binary patch literal 14826 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 W6%xK^<9vV(AO#uK7o}j+kpBTHs1?2d literal 0 HcmV?d00001