Mit6.S081:lab COW
实验:Lab: COW
实验开始之前需要将git分支切换到cow分支不然有些文件你是没有的
123$ git fetch$ git checkout cow$ make clean
COW简介普通fork的问题一个进程调用fork后会创建和父进程一样大的物理内存空间,并拷贝父进程的物理内存的内容。这样会造成物理空间的浪费,以shell程序为例运行一个命令首先会调用fork拷贝父进程,然后使用exec将程序重新写入子进程的空间。
在这种情况下,首先创建和父进程一样大的空间会造成空间的浪费,其次将父进程的内容拷贝到子进程有使用exec覆盖内存会浪费时间。
copy-on-write fork
copy-on-write fork是缺页(异常操作)的一种应用场景,几乎在所有操作系统中都实现了这个功能。
==COW==怎样解决上述普通fork的问题?
像是惰性分配(lazy allocation)的方式,先不创建物理页表而是进程,当进程需要使用这部分内存时再分配。
所以COW fork的具体实现就是,在使用fork创建子进程时,只是给子进程创建一个页表,将子进程的虚拟页映射到父进程的物理 ...
Mit6.S081:lab syscall
实验:Lab: System calls
实验开始之前需要将git分支切换到syscall分支不然有些文件你是没有的
123$ git fetch$ git checkout syscall$ make clean
1.GDB:参考链接
我的实验环境为ubuntu20.04,只有gdb-multiarch这个gdb调试工具,建议不要安装riscv64-linux-gdb因为特别难以下载且不好安装。
连接GDB Server
打开一个terminal,在xv6的文件夹中键入make qemu-gdb打开gdbserver。在课程演示中我们使用了CPUs=1这个选项以一个cpu运行xv6
再打开一terminal,同样在xv6文件夹中,键入gdb-multiarch这个命令就可以链接到gdb-server了,链接成功后如图所示
实验
如上述所说将gdb-server连接完毕
在syscall.c文件的syscall函数处添加断点,b=break
让程序运行,使用c=continue,当运行到syscall函数处就会发生中断。
使用backtrace查看栈信息,栈顶为sy ...
Mit6.S081:lab pgtbl
实验:Lab: System calls
实验开始之前需要将git分支切换到syscall分支不然有些文件你是没有的
123$ git fetch$ git checkout pgtbl$ make clean
Speed up system calls (easy)实验要求一些操作系统(例如Linux)通过在用户空间和内核之间共享只读区域中的数据来加快某些系统调用。这消除了执行这些系统调用时内核交叉的需要。为了帮助您了解如何将映射插入到页表中,第一个任务是为xv6中的getpid()系统调用实现此优化。
创建每个进程时,将一个只读页面映射到USYSCALL(在memlayout.h中定义的虚拟地址)。在该页的开始,存储一个usyscall结构(也在memlayout.h中定义),并初始化它以存储当前进程的PID。对于本实验,用户空间端提供了ugetpid(),它将自动使用usycall映射。如果ugetpid测试用例在运行pgtbltest时通过,您将获得这部分实验的全部学分。
HINS:
在kernel/proc.c中的proc_pagetable()中执行映射。
选择 ...
Mit6.S081:lab traps(详解)
实验:Lab: System traps
实验开始之前需要将git分支切换到traps分支不然有些文件你是没有的
123$ git fetch$ git checkout traps$ make clean
RISC-V assembly (easy)这个实验主要目的是帮助我们能够认识汇编代码,通过gdb调试user/call.c文件,回答相应问题。
GDB指令下述的指令格式表述为:全称/简写,下列展示的是实验中普遍使用的指令
12345678910111213141516171819202122232425261.break/b (*地址)/函数名 #设置断点,指令地址可以查看asm文件#除此之外通常可以使用b *$stvec,在trampoline处设置断点2.continue/c #运行到断点处然后停下3.stepi/si #运行单个汇编指令,进入函数4.n #运行一行c语言代码,不进入函数5.step/s #运行一行C语言代码,进入函数6.info/i reg/r #查看32个同一寄存器和PC寄存器的值7.info/i break/b #查看断点信息8.info/i fra ...
NVim配置
实验环境: VMware+Ubuntu20.4,配置参考
安装Ubuntu下安装neovim
1sudo apt install neovim
Python依赖安装
1sudo apt install python3-neovim
安装终端字体
进入nerdfonts,选择自己想要的字体,我选择的字体是Hack Nerd Font
解压字体,到用户字体文件夹中
1sudo unzip Hack -d /usr/share/fonts/Hack
使用命令安装字体
1234cd /usr/share/fonts/Hacksudo mkfontscale # 生成核心字体信息sudo mkfontdir # 生成字体文件夹sudo fc-cache -fv # 刷新系统字体缓存
在terminal中修改字体
配置nvim
文件目录树
core目录:放置一些常用键的映射(options.lua)文件,nvim一些选项的修改(缩进长度等)
plugins目录:一些插件的lua文件配置
plugin目录:插件包
初始化nvim文件在~/.config/nvim文件目录下新建一 ...
Lab4:Shards KV Service(未完善)
这个实验由于时间关系PartB部分只完成了一点,但是我后续还是会更新的,读者可以不介意的话可以观看
ban
Shards实验简述为何需要Shards?
Shard设计的目的简单来说就是为了并行性(parallel)、多个区域能够有Shards的副本能够加快访问就是是locally
在分布式的事务处理中数据通常情况不会放置到一个副本中,一个事务中通常情况下会包含许多的key分布在不同的副本中,为了保证分区的容错性副本也被设计为一个raft组,这样每个副本中的数据(数据库)就是一个Shard,如何操作这样一个事务具体实现也是和[[Spanner 论文笔记]]中的描述相同。
Sharded KV Service的组成
a set of replica groups: 每一个replica Group作为一个副本是Shards的子集,一个副本由一些服务器组成,这些服务器使用Raft来复制组间的Shards。
shard controller: shard controller是知道那个Raft Group含有客户请求的键,这些信息叫做Cofiguration,Cofiguration ...
Debugging by Pretty Printing
Debugging In Detributed SystemDebug官方博客Debugging by Pretty Printing ](https://blog.josejg.com/debugging-pretty/))
Go Side在文件util.go中进行修改
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364package raftimport ( "fmt" "log" "os" "strconv" "time")// Retrieve the verbosity level from an environment variablefunc getVerbosity() int { v := os.Getenv("VERBOSE&q ...
xv6:操作系统接口
系统调用在操作系统的简介中,说到为了方便程序使用硬件资源操作系统会提供一些应用接口。
如Figure1.1所示,在xv6中采取一个内核(kernel)空间的设计:一个特殊的程序提供服务给运行的程序。每个运行的程序我们称作为进程(Process)拥有指令、数据、栈。用户空间(user space): 抽象出的一个空间,用于用户运行应用程序,如shell(本质上是一个应用程序,功能就是读取命令并执行)、cat
指令(instruction):实现程序的计算
数据(data):一些计算的变量
栈(stack):组织的程序(C语言中的函数)的调用
当进程调用内核服务时我们就需要进行(invoke)系统调用,系统调用会进入内核,然后内核执行服务并返回,于是这样的一个进程会选择在用户空间与内核空间执行。
进程与内存进程(Process):
进程的概念:进程简单来说就是正在运行的程序,例如我们以及启动的word办公软件、游戏应用等应用程序。
我们为了实现一个系统能够同时运行多个程序,系统需要提供一种拥有多个CPU的假象,称作为虚拟化CPU
那为了实现这种技术我们采用了一种叫做时分(time ...
xv6:操作系统组成
O/S提供CPU等硬件资源分配以及安全的功能
时分(time-share)的机制:让CPU资源能够被合理的调度。进程调度
隔离性(isolation):进程的资源(如内存)与故障都不会相互干扰
复用(multiplexing):c语言的库文件
交互(interaction):进程之间的通讯,如管道pipe
xv6运行在多核RISC-V微处理器上,RISC-V是一个64位CPU.
xv6是一个用”LP64“C编写的内核(L-long,P-pointer),在c语言中long类型与pointer类型都是64位,int类型位32位。
qemu是一个c语言编写的模拟硬件的程序,但是我们在编写xv6时,应该qemu看作一块RISC-V主板,内含CPU、ROM、RAM、磁盘等等硬件,xv6就是运行在该主板上的操作系统。
抽象物理资源抽象
为什么要使用操作系统?
应用通过图1.2的系统调用接口(库)可以直接与硬件资源交互,方便程序设计者去编写程序
库方法的缺陷
有多个应用同时运行,应用必须保持良好的特性(不能有bug)。例如应用需要周期性的放弃CPU,让其他应用使用。这便是时分的调 ...
xv6:页表
页表:是一种最受欢迎的操作系统提供给进程私有空间地址和内存的机制。页表决定了内存地址的意义,以及可以访问的内存部分。
页表在xv6中的作用
隔离不同进程的地址空间
复用物理内存:共享库
内存与地址空间内存内存与CPU直接交互,由RAM组成,断电后数据就会丢失。在这里我们可以将内存看作一个[0,max]的字节数组(RISC-V加载与储存数据都是以字节为单位,取单字或双字),地址则是索引,那么CPU对内存进行读写也就和C语言中读写数组元素相似。
在第一章中,简述了进程是如何从磁盘加载到内存中的。那么下图就是内存中程序进程,分别由cat、sh、kernel等进程,那么按照内存是一个数组的假设,这些进程就会占据一段连续的空间。
WARNNING:在这种布局下,会出现一些问题。最明显的就是没有隔离性,在cat中使用指令那么我们就会修改sh的内存映像,更加危险的是会导致内核映像被修改。
(虚拟)地址空间于是我们提供了地址空间(address space)这个抽象,地址空间就是给每一个进程一个独立的地址空间(虚拟的空间,都是从0到n),给进程一种只有自己拥有整块内存空间的错觉。
如下图 ...