资源

  1. ucore在线实验指导书
  2. 我的ucore实验代码

练习1:理解通过make生成执行文件的过程

详见《ucore lab1 exercise1》实验报告

练习2:使用qemu执行并调试lab1中的软件

详见《ucore lab1 exercise2》实验报告

练习3:分析bootloader进入保护模式的过程

详见《ucore lab1 exercise3》实验报告

练习4:分析bootloader加载ELF格式的OS的过程

详见《ucore lab1 exercise4》实验报告

练习5:实现函数调用堆栈跟踪函数

详见《ucore lab1 exercise5》实验报告

练习6:完善中断初始化和处理

详见《ucore lab1 exercise6》实验报告

扩展练习1:增加一用户态函数(待完成)

扩展proj4,增加syscall功能,即增加一用户态函数(可执行一特定系统调用:获得时钟计数值),当内核初始完毕后,可从内核态返回到用户态的函数,而用户态的函数又通过系统调用得到内核态的服务。

扩展练习2:用键盘实现用户模式内核模式切换(待完成)

用键盘实现用户模式内核模式切换。具体目标是:“键盘输入3时切换到用户模式,键盘输入0时切换到内核模式”。 基本思路是借鉴软中断(syscall功能)的代码,并且把trap.c中软中断处理的设置语句拿过来。

调Bug日志

【2019-1-3】Bug 2:lab1运行到pmm_init时失败

  1. 解决Bug1后,再次执行make qemu仍然失败,提示以下信息:
ebp:0x00007bf8 eip:0x00007d6e args:0xc031fcfa 0xc08ed88e 0x64e4d08e 0xfa7502a8
<unknow>: -- 0x00007d6d --
qemu-system-i386: Trying to execute code outside RAM or ROM at 0x457e0000
This usually means one of the following happened: (1) You told QEMU to execute a kernel for the wrong machine type, and it crashed on startup (eg trying to run a raspberry pi kernel on a versatilepb QEMU machine)
(2) You didn't give QEMU a kernel or BIOS filename at all, and QEMU executed a ROM full of no-op instructions until it fell off the end
(3) Your guest kernel has a bug and crashed by jumping off into nowhere This is almost always one of the first two, so check your command line and that you are using the right type of kernel for this machine.
If you think option (3) is likely then you can try debugging your guest with the -d debug options; in particular -d guest_errors will cause the log to include a dump of the guest register state at this point. Execution cannot continue; stopping here.
  1. 使用gdb单步跟踪,发现是在pmm_init函数中加载完gdt表后,执行mov %ax, %gs时异常结束了。我尝试将gs寄存器改为dx,则没有问题。这意味着gs等段寄存器此时不能被访问。

  2. 问题比较像是某些权限没设置好,导致无法访问段寄存器。应该是前面的步骤哪里没做好。发散思路:

    • [x] 梳理一遍从BIOS启动到pmm_init之间要做哪些事情,检查各个步骤是否OK,比如保护模式是否设置成功

      • [x] bootloader打开A20门、加载gdt、使能PE(没问题)
      • kern_init在执行pmm_init之前初始化(edata, end)这段内存
      • [x] kern_init在执行pmm_init之前打印字符串及调试信息(没影响)
    • 查找段寄存器无法访问的可能原因
    • 确认加载全局描述符表需要哪些操作,是否有遗漏操作或操作有误
    • 对比lab1和lab2,看下哪些步骤有区别
      • lab1的kernel加载地址为0x100000,lab2的kernel加载地址为0xC0100000
      • [x] lab1和lab2的movl %cr0, %eax对应的汇编代码不一致(使用gdb调试发现没问题,应该是objdump文件将二进制代码翻译成汇编代码时出现的问题)
  3. 最终发现是初始化(edata, end)这段内存导致的问题。这段内存包括.got.plt,.data.rel.local,.bss和.data.rel.ro.local四个段,我缩小为只初始化.bss段就没问题了。这个问题之前在做mit 6.828 lab时也遇到过,现在才想起来。

bin/kernel:     file format elf32-i386

Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00003955 00100000 00100000 00001000 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .rodata 000008a0 00103958 00103958 00004958 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .stab 00007bc1 001041f8 001041f8 000051f8 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .stabstr 000020cf 0010bdb9 0010bdb9 0000cdb9 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .data 00000950 0010e000 0010e000 0000f000 2**5
CONTENTS, ALLOC, LOAD, DATA
5 .got.plt 0000000c 0010e950 0010e950 0000f950 2**2
CONTENTS, ALLOC, LOAD, DATA
6 .data.rel.local 000000c6 0010e960 0010e960 0000f960 2**5
CONTENTS, ALLOC, LOAD, DATA
7 .data.rel.ro.local 0000006c 0010ea40 0010ea40 0000fa40 2**5
CONTENTS, ALLOC, LOAD, DATA
8 .bss 00001300 0010eac0 0010eac0 0000faac 2**5
ALLOC
9 .comment 0000002a 00000000 00000000 0000faac 2**0
CONTENTS, READONLY
  1. 那么为什么初始化.got.plt及data.rel.ro.local这些段会有问题?我从RELRO(Relocation Read Only)这个网页中找到了答案:.data.rel.ro.local这个段顾名思义就知道是只读的,现在想将其memset为0,自然会导致问题。

  2. 那么为什么lab2没有问题?对比两个lab的tools/kernel.ld文件,发觉lab2的链接脚本汇总在定义edata前,先用ALIGN命令将位置设置在能被0x1000整除的位置,这样恰好将.got.plt, data.rel.ro.local这些段跳过了,因此(edata, end)这段内存恰好只包含.bss段,这时memset就没问题了!

    . = ALIGN(0x1000);
.data.pgdir : {
*(.data.pgdir)
} PROVIDE(edata = .);

顺便贴上lab2的bin/kernel的这几个段的信息:

 5 .got.plt      0000000c  c0118950  c0118950  00019950  2**2
CONTENTS, ALLOC, LOAD, DATA
6 .data.rel.local 000000c6 c0118960 c0118960 00019960 2**5
CONTENTS, ALLOC, LOAD, DATA
7 .data.rel.ro.local 00000088 c0118a40 c0118a40 00019a40 2**5
CONTENTS, ALLOC, LOAD, DATA
8 .data.rel 00000004 c0118ac8 c0118ac8 00019ac8 2**2
CONTENTS, ALLOC, LOAD, DATA
9 .data.pgdir 00002000 c0119000 c0119000 0001a000 2**12
CONTENTS, ALLOC, LOAD, DATA
10 .bss 00000f28 c011b000 c011b000 0001c000 2**5
ALLOC
  1. 总结:定位问题的常规方法:收集信息、理解原理、推测原因(将所有可能的原因都列举出来,逐一排查)。如果不是之前做mit 6.828 lab遇到过同样的Bug,估计定位起来更艰难,因为我差别就放弃怀疑memset语句有问题了。这个问题的棘手之处也在于:memset时没立即出错,等到后面初始化GDT时才出错。总之,经验很重要,以及不能随便放过任何一个可能。

【2019-1-3】Bug 1:bootblock链接失败

  1. 从陈渝老师的github代码库clone了一份干净的代码到本地,进入labcodes_answer/lab1_result目录,执行make qemu时失败了,提示以下信息:
ld -m    elf_i386 -nostdlib -N -e start -Ttext 0x7C00 obj/boot/bootasm.o obj/boot/bootmain.o -o obj/bootblock.o
600 >> 510!!
'obj/bootblock.out' size: 600 bytes
make: \*\*\* [bin/bootblock] Error 255
  1. 根据提示信息,可知是链接后的obj/bootblock.out文件大于512字节,导致检查不通过。这个检查是在哪里设置的呢?在代码库里搜索,发现是在tools/sign.c中设置的:
    printf("'%s' size: %lld bytes\n", argv[1], (long long)st.st_size);
if (st.st_size > 510) {
fprintf(stderr, "%lld >> 510!!\n", (long long)st.st_size);
return -1;
}
  1. 怎么解决?先确认一下是不是每个lab都有这个问题。进入labcodes_answer/lab2_result目录,执行make qemu成功了,说明lab2是正常的。

  2. 为什么lab1和lab2的现象不一样呢?有两种可能:一是链接脚本不同,lab2增加了某些链接选项,使得链接后的文件可以变小;二是代码文件不同,lab1的代码文件比lab2大。于是首先比较两个lab的链接脚本,发现基本相同。然后比较两个lab的diamante文件,发现boot/nootmain.c有以下两处差异:

// lab1
unsigned int SECTSIZE = 512 ;
struct elfhdr * ELFHDR = ((struct elfhdr *)0x10000) ; // scratch space // lab2
#define SECTSIZE 512
#define ELFHDR ((struct elfhdr *)0x10000) // scratch space
  1. 可以推测lab2的写法是比lab1省内存的,因为使用宏代替了全局变量。但这点差异足够大到lab1链接不通过吗?先将lab2的写法同步到lab1,再make一把,发现果然可以了,boot/bootblock.out的size由600字节减少到488字节,少了112字节。真神奇,两个全局变量竟会导致增加了112字节!

  2. 总结:定位问题的一种思路:如果有两份代码,一份有问题,另一份正常,那么可以使用对比法。

《ucore lab1》实验报告的更多相关文章

  1. [操作系统实验lab3]实验报告

    [感受] 这次操作系统实验感觉还是比较难的,除了因为助教老师笔误引发的2个错误外,还有一些关键性的理解的地方感觉还没有很到位,这些天一直在不断地消化.理解Lab3里的内容,到现在感觉比Lab2里面所蕴 ...

  2. Ucore lab1实验报告

    练习一 Makefile 1.1 OS镜像文件ucore.img 是如何一步步生成的? + cc kern/init/init.c + cc kern/libs/readline.c + cc ker ...

  3. ucore操作系统学习(三) ucore lab3虚拟内存管理分析

    1. ucore lab3介绍 虚拟内存介绍 在目前的硬件体系结构中,程序要想在计算机中运行,必须先加载至物理主存中.在支持多道程序运行的系统上,我们想要让包括操作系统内核在内的各种程序能并发的执行, ...

  4. 《ucore lab3》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 练习1:给未被映射的地址映射上物理页 题目 完成do_pgfault(mm/vmm.c)函数,给未被映射的地址映射上物理页.设置访问权限的时候需 ...

  5. 《ucore lab1 exercise5》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 题目:实现函数调用堆栈跟踪函数 我们需要在lab1中完成kdebug.c中函数print_stackframe的实现,可以通过函数print_s ...

  6. 《ucore lab8》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 练习1: 完成读文件操作的实现(需要编码) 题目 首先了解打开文件的处理流程,然后参考本实验后续的文件读写操作的过程分析,编写在sfs_inod ...

  7. 《ucore lab7》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 练习1: 理解内核级信号量的实现和基于内核级信号量的哲学家就餐问题(不需要编码) 题目 完成练习0后,建议大家比较一下(可用meld等文件dif ...

  8. 《ucore lab6》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 练习1: 使用 Round Robin 调度算法(不需要编码) 题目 完成练习0后,建议大家比较一下(可用kdiff3等文件比较软件) 个人完成 ...

  9. 《ucore lab5》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 练习1: 加载应用程序并执行(需要编码) 题目 do_execv函数调用load_icode(位于kern/process/proc.c中) 来 ...

  10. 《ucore lab4》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 练习1:分配并初始化一个进程控制块 题目 alloc_proc函数(位于kern/process/proc.c中) 负责分配并返回一个新的str ...

随机推荐

  1. BZOJ3551 Peaks加强版 [Kruskal重构树,主席树]

    BZOJ 思路 我觉得这题可持久化线段树合并也可以做 我觉得这题建出最小生成树之后动态点分治+线段树也可以做 还是学习一下Kruskal重构树吧-- Kruskal重构树,就是在做最小生成树的时候,如 ...

  2. Pytest权威教程22-优质集成实践

    目录 优质集成实践 使用pip安装包 Python测试发现的约定 选择测试布局结构/导入规则 在应用程序代码外测试 测试作为应用程序代码的一部分 tox 返回: Pytest权威教程 优质集成实践 使 ...

  3. 信竞四定律orz

    正常代码不写#define @zdx 平时刷题不写freopen @liuziwen 循环内部不写return 0 @asdfo123 主程序内不写char array @asdfo123 输出时间: ...

  4. Prometheus初体验(三)

    一.安装部署 Prometheus基于Golang编写,编译后的软件包,不依赖于任何的第三方依赖.用户只需要下载对应平台的二进制包,解压并且添加基本的配置即可正常启动Prometheus Server ...

  5. 三大框架 之 OGNL表达式

    目录 OGNL 什么是OGNL OGNL与EL表达式对比 OGNL功能 OGNL使用要素 OGNL入门 java程序使用ognl struts2中使用ONGL OGNL 什么是OGNL OGNL是Ob ...

  6. AUC,ROC我看到的最透彻的讲解

      版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/u013385925/article/d ...

  7. colormap是MATLAB里面用来设定和获取当前色图的函数。

    下面将举例.描述MATLAB内建的色图.用户除了可以编程指定MATLAB内建的色图,还可以使用Plot Tools图形用具界面的Figure Properties面板中的Colormap菜单来选择一种 ...

  8. Unity3D ACT动作游戏《武士2》项目源码附教程

    武士二源码亲测unity2018.3.6能运行 仅供学习附有教程 教程完整73课,网上大部分一般为65课, 教程大小27GB,mp4格式 整理不易 扫码时备注或说明中留下邮箱 付款后如未回复请至htt ...

  9. UE4虚幻引擎独立游戏制作教程 UE4编程教学 虚幻引擎4

    非常好的一套UE4入门教学课程,语言诙谐幽默,并且是中文语音中文语音中文语音 赠送[精通Unreal引擎技术——关卡设计艺术]PDF版 目录 FLV格式,大小5G,中文语音 扫码时备注或说明中留下邮箱 ...

  10. 正则表达式检测IP地址与端口号是否合法

    正则表达式检测IP地址与端口号是否合法,代码如下: 正则表达式检测IP地址 public static bool CheckAddress(string s) { bool isLegal = fal ...