P7如何快速debug
P7如何快速debug现在,有很多同学苦于P7冗长而繁琐的debug,笔者在第一次P7上机前一周就写完了P7,并且成功在半天时间内找到所有bug,顺利通过课上强测,因此来讨论区分享分享自己的debug经验。 通过阅读本文,您大致可以学到:如何巧妙构造容易找到问题的测试数据;如何妥善利用课上课下课程组给出的报错;如何理解中断行为的处理等知识。 实现P7的过程中一些值得注意的细节本来是想完整的讲一遍P7要我们干什么,但是这样好像就是把教程复述了一遍,虽然那个教程本身也并不是很清晰。限于篇幅,这里讲一些笔者认为的在实现P7过程中一些小细节, 外设根据教程的要求,外设一共由计时器0、计时器1、中断发生器和系统桥组成。计时器是如何实现的,在CPU的角度看来其实不重要,CPU只需要与系统桥交互,获得信息,在需要的时候向系统桥传递信息即可,这也符合了高内聚低耦合的思想。 计时器这里带大家简要分析一下有关计时器的设计文档以及源码,方便大家理解。 教程里说了,计时器的主要功能,就是根据设定的时间来定时产生中断信号。参考计时器的设计文档和源码会发现,计时器的本质是一个状态机。其内部的部分信号值都...
hexo博客butterfly主题美化教程
写在前面: 博客魔改有风险,建议在修改代码时,将原代码注释而不是删除 鉴于每个人的根目录名称都不一样,本帖博客根目录一律以 [BlogRoot] 指代 因为.pug、.styl和.yml文件对于缩进的要求较为严格,故建议大家使用 VS Code进行修改 本帖的部分代码以diff代码块标识,在修改时别忘记删去前面的 + 和 - 符号 网站恶搞标题效果预览 在未选中该网页时,其呈现出这样的内容 在选中该网页的一段时间内,其呈现出这样的内容,之后恢复正常 修改方式 新建文件 [BlogRoot]\source\js\title.js,写入以下内容: 1234567891011121314151617//动态标题var OriginTitile = document.title;var titleTime;document.addEventListener('visibilitychange', function () { if (document.hidden) { //离开当前页面时标签显示内容 document.ti...
BUAA_OS_challenge_shell_实验报告
实验总览本次实验旨在对 MOS 操作系统中现有的 Shell 进行功能扩展,使其从一个基础的命令解释器演进为一个功能更加完善、用户体验更佳的交互式程序。实验内容主要包括: 路径管理:引入当前工作目录(CWD)的概念,支持相对路径,并实现 cd 和 pwd 内置命令。 环境变量:实现局部和全局环境变量的管理,包括 declare、unset 命令和 $ 变量展开。 输入与指令优化:实现指令自由输入、不带 .b 后缀指令、快捷键、历史指令、注释功能、 指令条件执行:实现 Linux shell 中的 && 和 ||。 更多指令:增加 touch, mkdir, rm 等常用文件系统操作命令和 exit 指令。 追加重定向:实现了追加重定向功能 限于篇幅,本报告并未给出全部修改的代码,仅给出了笔者认为比较关键,语言不能完全描述的部分代码。 实验设计与实现1. 支持相对路径与内置命令 cd、pwd1.1 设计思路为了支持相对路径,核心是为每个进程维护一个“当前工作目录”(CWD)的状态。 CWD 的存储: 最佳方案是利用共享内存。我分配了一个固定的虚拟地址 CWD_...
BUAA_OS_Lab6_实验报告
BUAA_OS_Lab6 实验报告思考题Thinking 6.1 示例代码中,父进程操作管道的写端,子进程操作管道的读端。如果现在想让父进程作为“读者”,代码应当如何修改? 修改如下 1234567891011121314151617switch (fork()) { case -1: break; case 0: /* 子进程 - 作为管道的写者 */ close(fildes[0]); /* 关闭不用的读端 */ write(fildes[1], "Hello world\n", 12); /* 向管道中写数据 */ close(fildes[1]); /* 写入结束,关闭写端 */ exit(EXIT_SUCCESS); default: /* 父进程 - 作为管道的写者 */ close(fildes[1]); /* 关闭不用的写端 */ read(fildes[0], buf, 100); /* 从管道中读数...
BUAA_OO_Unit4_单元总结
「BUAA OO」第四单元总结 本篇博客记录了笔者面向对象编程第四单元的学习过程与思考,以及对本课程四个单元学习的总结(源码与指导书可以参考Github) 第十三次作业题目要求实现一个能实现用户请求的图书馆系统。本单元代码作业简单、架构清晰、迭代量少,笔者在三次作业中均没有发现什么值得注意的问题。 类图 第十四次作业类图 第十五次作业类图 正向建模与开发正向建模与开发是一种**“从无到有”**的、系统化的产品创造过程。它从最初的需求和概念出发,通过系统性的设计、建模、仿真和验证,最终制造出符合预期的产品。 正向建模是正向开发流程中的核心环节之一,指的是在产品尚未实际存在之前,依据其功能需求、性能指标和设计规则,在数字世界中构建其虚拟模型的过程。这个模型是产品的“数字蓝图”。在本单元中,这个和我们先画类图再编写代码是相吻合的。 而正向开发则是一个更宏观的概念,它涵盖了从市场调研、概念提出、设计、建模、测试、生产到最终交付的全过程。正向建模是正向开发流程中的一个关键技术手段。 在本单元的练习中,我们主要用到了三种UML建模语言,分别是类图、状态图和顺序图 类图类图会描述系统的静态结...
BUAA_OS_Lab5_实验报告
BUAA-OS-Lab5 实验报告思考题Thinking 5.1 如果通过 kseg0 读写设备,那么对于设备的写入会缓存到 Cache 中。这是一种错误的行为,在实际编写代码的时候这么做会引发不可预知的问题。请思考:这么做这会引发什么问题?对于不同种类的设备(如我们提到的串口设备和 IDE 磁盘)的操作会有差异吗?可以从缓存的性质和缓存更新的策略来考虑。 当外部设备产生中断信号或者更新数据时,此时Cache中之前旧的数据可能刚完成缓存,那么完成缓存的这一部分无法完成更新,则会发生错误的行为。缓存机制的设计是为了提高效率,让数据发生改变的时候不立即写入内存,而是等Cache发生替换的时候才写进去。而对于串口设备这种读写频繁、实时交互的设备来说,如果写入 kseg0 部分,数据可能很久都不被真正写入内存中,引发错误。在相同的时间内,发生读写错误的概率远高于IDE磁盘。 Thinking 5.2 查找代码中的相关定义,试回答一个磁盘块中最多能存储多少个文件控制块?一个目录下最多能有多少个文件?我们的文件系统支持的单个文件最大为多大? 一个磁盘块的大小为4KB,一个文件控制块的大...
BUAA_OO_Unit3_单元总结
「BUAA OO」第三单元总结题目说明本次面向对象编程第三单元的主题是:「BUAA OO」第三单元总结 第九次作业:根据 JML 规格实现Person类、Tag类、Network类 第十次作业:根据 JML 规格实现OfficialAccount类 第十一次作业:根据 JML 规格实现Message类及其3个子类 三次迭代说明第九次作业本次作业主要是根据JML规格实现三个接口中的所有方法,按照JML规格严格实现理论上就是正确的,所以其实要多注意细节;但是完全按照JML实现显然是不行的,哈哈tle了吧 12345678910/*@ ensures \result == @ (\sum int i; 0 <= i && i < persons.length; @ (\sum int j; i < j && j < persons.length; @ (\sum int k; j < k && k <...
BUAA_OS_Lab4_实验报告
BUAA_OS_Lab4_实验报告思考题Thinking 4.1 思考并回答下面的问题: 内核在保存现场的时候是如何避免破坏通用寄存器的? 系统陷入内核调用后可以直接从当时的 $a0-$a3 参数寄存器中得到用户调用 msyscall留下的信息吗? 我们是怎么做到让 sys 开头的函数“认为”我们提供了和用户调用 msyscall 时同样的参数的? 内核处理系统调用的过程对 Trapframe 做了哪些更改?这种修改对应的用户态的变化是什么? 内核在保护现场的时候会调用SAVE_ALL宏,把通用寄存器的sp复制到$k0中。保存现场需要使用$v0作为协寄存器到内存的中转寄存器,写到内存时需要sp,所以在正式保存协寄存器和通用寄存器前先保存这两个寄存器。 可以的。因为内核在陷入内核、保存现场的过程中,寄存器 a0-a3 中的值都没有被破坏。用户在调用 msyscall 时,传入的参数会被保存在 a0-a3 寄存器和堆栈中。当陷入内核时,a0-a3 寄存器不会被破坏,并且会将用户栈中的相应参数复制取出到内核栈中。因此,sys_* 函数可以从寄存器和用户栈处获得用户调用 msys...
BUAA_OS_Lab3_实验报告
BUAA_OS_Lab3_实验报告思考题Thinking 3.1 请结合 MOS 中的页目录自映射应用解释代码中 e->env_pgdir[PDX(UVPT)] = PADDR(e->env_pgdir) | PTE_V 的含义。 e->env_pgdir 代表当前进程的页目录的基地址。在 MOS 中,每个进程都有自己的页目录,用于存储该进程的页表信息。 PADDR(e->env_pgdir) 代表这个函数获取页目录的物理地址。PADDR是一个宏,用于将内核虚拟地址转换为物理地址。 PTE_V :这是一个标志位,表示页表项有效。PADDR(e->env_pgdir) | PTE_V,表示给页目录的物理基地址加上权限位。 PDX(UVPT):这是一个宏,用于获取虚拟地址 UVPT 的页目录索引。 所以,这行代码的作用是将当前进程的页目录的物理地址映射到用户虚拟地址空间的UVPT地址处,并设置页表项为有效。这样,进程就可以在自己的地址空间中访问页表和页目录,提高了访问效率。 Thinking 3.2 elf_load_seg 以函数指针的形式,接受...
BUAA_OO_Unit2_单元总结
「BUAA OO」第二单元总结hw5写在动手之前在开始本次作业之前,需要明确几个问题: 1.需要哪些线程 首先自然是6个电梯6个线程,然后便是输入线程 2.有哪些共享对象 因为乘客都已经分配给某个电梯了,乘客自然就不能算共享对象,因为乘客只独属于某个电梯(线程)。那么还有什么算共享对象呢,笔者觉得应该是任务列表类。输入线程把读到的请求写到任务列表里面,6个电梯线程对任务列表进行读操作,获取属于各自的请求,完成请求后写回任务列表。 综上所述,整体框架就已经很明确了,在MainClass类里面,需要把6个电梯线程Elevator依次启动,再把输入线程InputThread启动,每个电梯线程有一个自己的任务列表QuestList,然后InputThread就根据请求的要求(电梯id)来把请求放到人物列表中,由电梯去完成 整体架构 第一次作业类图如图所示,整体按照生产者-消费者模型去搭建的,美中不足的一点是笔者没有写分配器类,这样这个作业的可迭代性就不好 同步块设计与锁第一次作业笔者只是用了synchronized关键字,并没有使用其他的锁。 如图所示,笔者只在QuestTable里面...