未分类
1.7k 词
Lab: Copy-on-Write Fork for xv62021的lab没有了lazy lab作为COW的前置,虽然实验内容里提到了lazy lab。而且提示里少了一两条非常关键的信息,似乎默认了做过前面的lab。 在做这个lab之前先读一下fork的流程: 分配一个新进程np = allocproc() 把整个内存空间复制给新进程uvncopy(p->pagetable, np->pagetable, p->sz) 复制寄存器,设置函数返回值*(np->trapframe) = *(p->trapframe); np->trapframe->a0=0 所有进程已经打开的文件,链接数+1 设置基础数据,名称状态父级等 这里要优化的就是第二步:复制整个内存空间的操作太大。改为懒惰机制:只在有必要的时候复制物理内存。 改写uvmcopyuvmcopy目前的实现是直接分配一个物理内存mem=kalloc(),然后将其映射在新进程的内存空间里。现在,不直接分配一个物理内存而是将手上的物理内存pa映射给新进程。 两个进程前后走到的物理页的...
未分类
3.6k 词
问题 为什么需要虚拟内存? 早期在操作系统只能同时运行一个程序,操作系统只是一组库函数,在物理内存里存在,例如占据[0,64KB)的位置,然后运行的程序可以直接操作从64KB开始的物理内存。如果需要切换运行的用户程序,只需要将用户程序加载到64KB开始的位置,然后执行指令即可。 但是随着同时运行多个用户程序的需求产生,直接操作物理内存的弊端就露出来了:在之前只有一个用户程序的时候,损坏了操作系统部分的内存坏了就坏了,重启可以解决。如果有多个程序,错误地读(甚至写)操作系统或者其他用户程序的内存部分,就是一个很麻烦的事情了。 所以我们希望有隔离性:用户程序与用户程序之间(当然操作系统本身也是)不能互相覆盖。但是过强的隔离性也不行,用户程序之间应该有交流的方式。 其次就是易用性:虚拟内存空间是给用户程序单独所见的,所以他的排布方式可以是固定的,并且可以确定从0开始到一个最大值。虚拟内存空间不需要在物理内存里保持连续。 为什么需要有三级页表? 首先给虚拟内存空间机制下一个定义,他可以看作是一个函数:f(va)=pa,将一个虚拟地址转换为一个物理地址。 所以最简单的实现方式就是:记...
未分类
3k 词
多道程序批处理系统目前的缺陷是同一时刻只能执行一个程序。在一些场景下cpu会浪费,比如等待硬件的数据读取的时间里cpu要一直空转等待。所以很自然的一个新的需求就是:在操作系统上期望能“同时”运行多个程序。 接下来需要实现两个目标: 在内存中可以同时存在多个进程 在满足某些条件的情况下, 可以让执行流在这些进程之间切换 前者是之前在加载阶段做过的,程序就是一截指令序列,通过上下文赋予其意义。既然要运行多个自然就要有能加载多个的能力。 为什么需要使用不同的栈空间?思考一下目前阶段程序所使用的栈空间,是在am的链接脚本中定义的,他直接划分了硬件提供的内存空间:将前面一部分分配为栈区,后面全部为堆区。这个堆栈是am这个运行环境提供给在上面运行的nanos-lite使用的,而目前nanos-lite加载应用程序是直接的内存拷贝,运行应用程序是简单的函数调用,让pc指针走到内存中特定的位置然后加载指令 上下文切换之前在CTE里是通过栈指针恢复数据的:将当前的数据保存到栈上,恢复时让函数参数的寄存器指向这里,就能获取到当时保存的数据了。 对于多个进程的切换,在这里可以偷梁换柱:A进程的...
未分类
7.4k 词
最简单的操作系统批处理系统最简单的操作系统:一个后台程序,每次加载一个前台程序运行,结束了之后换另外一个。 目标: 用户程序结束执行之后,回到操作系统处继续运行 操作系统能加载在某些位置的用户程序执行 对于前者,需要有一个执行流切换机制,但是如果直接使用jal指令跳转的话就显得太随意了,在硬件上有对应的限制:如果执行了非当前权限的代码就会导致陷入操作系统内核然后交由操作系统执行。 穿越时空的旅程除了被动地进入操作系统之外,还需要主动地陷入操作系统:有的操作不应由用户程序执行,必须请求操作系统。当用户程序执行了一条自陷指令之后,跳转到操作系统预先设定好的位置执行特定的代码。大部分ISA不区分异常和自陷。 对于riscv32: 将当前pc写入mepc寄存器 在mcause寄存器中设置异常号 从mtvec寄存器中取出异常入口地址 跳转到异常入口地址 这部分由硬件完成。 特殊的原因? (建议二周目思考)如果由软件保存,用户程序可能可以写入特定的值来让操作系统执行特定的操作来破坏操作系统。 硬件提供的在操作系统和用户程序之间切换操作流的过程也是上下文切换。为了抽象上下文管理,操...
未分类
7.9k 词
不停计算的机器最简单的计算机TRM的运行方式: 12345while (1) { 从PC指示的存储器位置取出指令; 执行指令; 更新PC;} 具体地,cpu执行指令的方式是: 取指:从内存空间中读取出一条指令,具体位置由pc寄存器给出。 译码:读取出来的是一个字长的01串,cpu会查表翻译指令。 执行:根据译码的结果来执行具体的行为。 更新pc,指向下一条指令 回顾一下,用户程序是运行在模拟的硬件之上的,所以这里的任务是模拟一个cpu的执行,来支撑用户程序的执行。 :question: cpu一次只能执行一条指令吗 在这个模型里,如果细化到下去,在一个时刻cpu应该只能同时执行一条指令,这是一个重要的假设,当然这个假设不是谁规定的,他实际上从一开始编程就成了一种习惯:代码是一行一行执行,指令也应该是这样的。 但是现代的cpu似乎对这个事情有所打破,可能是一个叫微指令的概念 理解YEMU如何执行程序加法状态的状态机:把内存和寄存器的值作为状态。 两者的联系?cpu执行一条指令就是一次状态转移。 这个例子可以说明,只要有加法器和跳转功能,...
未分类
5.4k 词
fceux按照readme把内容下载下来之后运行可能会出现这个问题: 123456789/home/suzume/proj/ics2022/fceux-am/src/emufile.cpp: In member function ‘void EMUFILE_FILE::open(const char*, const char*)’:/home/suzume/proj/ics2022/fceux-am/src/emufile.cpp:33:22: error: array subscript 1 is above array bounds of ‘rom [1]’ [-Werror=array-bounds=] 33 | if (strcmp(roms[i].name, fname) == 0) { | ~~~~~~^In file included from /home/suzume/proj/ics2022/fceux-am/src/emufile.cpp:27:./nes/gen/roms.h:10:12: not...
未分类
505 词
installationos: Endeavouros/osx libreadline在哪里? 在aur上搜索到了,但是版本在8.0上下,考虑到ubuntu上的版本可能会有偏差?问题是ubuntu上下载到的是多少? 在ubuntu package search的网站上找到jammy的也是8.0上下,那就没问题直接下载了 另外sdl也可以直接下载,但是sdl似乎是pinned version?不太了解 llvm version?在网上搜索了一篇教导其他人如何在ubuntu上下载llvm的文章(他们到处都是!)得知版本为14。 但是这里有个小小的问题,当我直接llvm-config --version的时候发现版本为16, git log这个系统的一个i好处时,如果你还不习惯git的记录方式,他会自动帮你记录。但是我不是,同时我也不是nju的学生所以我选择直接关闭。这个功能开启之后你会有运行记录并且里面会携带你的修改内容,我觉得这样不舒服。 关于代码补全和跳转本人使用的是nvim+clangd作为lsp, 阅读clangd的文档有提到make这种组织方式推荐的方法是安装一...
未分类
367 词
Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub. Quick StartCreate a new post1$ hexo new "My New Post" More info: Writing Run server1$ hexo server More info: Server Generate static files1$ hexo generate More info: Generating Deploy to remote sites1$ hexo deploy More info: Deployment