zoukankan      html  css  js  c++  java
  • ucore操作系统实验学习笔记2

    1.实验一

    实验一主要是关注操bootloader的作用,同时练习QEMU和gdb的联合调试。

    1.1练习1

    1. 操作系统镜像ucore.img是如何一步一步生成的?
      通过分析 Makefile的指令可以看出,ucore.img 里面包含了两部分内容:第一部分是 bootloader, 这部分的大小是512bytes,这部分内容就是 bin/bootblock 文件; 主要由三个源文件文件编译链接而成:asm.h, bootasm.S, bootmain.c。第二部分是 kernel, 这部分大小是74868 bytes.这部分就是ucore的内容,主要由源文件 kern/ 下面的文件编译连接而成(分别将每个子目录下的文件生成.o文件,然后将所有.o文件使用 ld 命令链接起来形成kernel文件), 生成的二进制文件是 /bin/kernel。 ucore.img 的大小是 512 X 10000 bytes. 初始时里面全部填充为 0. 使用 dd 命令分别将 bootblock 和 kernel 这个两个文件复制进入 ucore.img 中。

    2. 一个被系统认为是符合规范的硬盘主引导扇区的特征是什么?
      首先一个主引导扇区的大小只能是512 bytes. 其次,这512字节的最后两个bytes 分别是 0x55, 0xaa。

    1.2练习2

    1. 从CPU加电后执行的第一条指令开始,单步跟踪BIOS的执行。
      BIOS是固化在系统ROM中的一段固件,早期的系统使用是的BIOS,现代计算机早已经用UEFI取代了BIOS。BIOS完成了系统硬件初始化和加载主引导扇区的功能,BIOS(UEFI)是由厂商的提供的,在系统一上电就开始执行,因此我们操作系统课程里面的编写的代码和BIOS没有关系。查阅资料可知,QEMU使用的是一个叫 seabios 的项目中的代码,可以在 github 中查看seabios 的源码: https://github.com/qemu/seabios , 同时 seabios 的项目主页上也提供调试seabios的方法: https://www.seabios.org/Debugging

    想要单步执行 seabios 的话,可以先从在一个命令行中输入:

    $qemu-system-i386 -fda ./myimage.img -S -s

    此时可以观察到qemu 启动了一个窗口,但是处于等待状态,没有任何输出。可以在另外一个终端输入:
    $gdb

    $set architecture i8086

    $target remote localhost:1234

    此时便可以在gdb中打印和查看BIOS的指令了。

    1.3练习3

    1. 为何开启A20,以及如何开启A20
      由于在保护模式下需要访问4GB的内存空间,所以需要将A20地址线enable。
      在bootasm.S 代码中,使能A20的代码段如下:
      seta20.1
      inb $0x64, %al #从port 64读取状态寄存器信息到 al
      testb $0x2, %al #测试input bufffer 是否有数据
      jnz seta20.1
      movb $0xd1, %al
      outb %al, $0x64
      seta20.2
      inb $0x64,%al
      testb $0x2, %al
      jnz seta20.2
      movb $0xdf, %al
      outb %al, $0x60

    2. 如何初始化GDT表
      建立GDT的函数如下(在 asm.h 中):

    #define SEG_ASM(type,base,lim)
    .word (((lim) >> 12) & 0xffff), ((base) & 0xffff);
    .byte (((base) >> 16) & 0xff), (0x90 | (type)),
    (0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff)

    在bootasm.S中调用上述函数建立GDT:

    gdt:
    SEG_NULLASM # null seg
    SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff) # code seg for bootloader and kernel
    SEG_ASM(STA_W, 0x0, 0xffffffff) # data seg for bootloader and kernel

    1. 如何使能和进入保护模式
      进入保护模式即为将CR0寄存器的 bit0 设置为 1.

    1.4练习4

    1. bootloader如何读取硬盘扇区的?
      对硬盘扇区的读取主要由 bootmain.c 文件中的2个函数实现: readsect 和 readseg
      readsect 每次读一个扇区
      readseg 则指定了要读取的字节数

    2. bootloader是如何加载ELF格式的OS?
      bootloader通过验证ELFHDR->e_magic来确认读取的是否为elf格式文件。

    1.5练习5

    1.6练习6

    1. 中断描述符表(也可简称为保护模式下的中断向量表)中一个表项占多少字节?其中哪几位代表中断处理代码的入口?
      中断描述符表(Interrupt Descriptor Table, IDT)中的每个表项占据 8-byte (according to Intel i386 programmer manual).
      根据中断描述符的定义:最低16位 和 最高的16位组成的 offset 是指向中断处理函数的地址。

    2. 请编程完善kern/trap/trap.c中对中断向量表进行初始化的函数idt_init。在idt_init函数中,依次对所有中断入口进行初始化。使用mmu.h中的SETGATE宏,填充idt数组内容。每个中断的入口由tools/vectors.c生成,使用trap.c中声明的vectors数组即可。

    extern uintptr_t __vectors[];
    int i;
    for (i = 0; i < 256; i++) {
    SETGATE(idt[i], 0, GD_KTEXT, __vectors[i], 0);

    SETGATE(idt[T_SWITCH_TOK], 0, GD_KTEXT, __vectors[T_SWITCH_TOK], 0);

    lidt(&idt_pd);

    1. 请编程完善trap.c中的中断处理函数trap,在对时钟中断进行处理的部分填写trap函数中处理时钟中断的部分,使操作系统每遇到100次时钟中断后,调用print_ticks子程序,向屏幕上打印一行文字”100 ticks”。

    只需要在函数 trap_dispatch() 中添加以下语句即可:
    ticks++;
    if (ticks % TICK_NUM == 0)
    print_ticks();

  • 相关阅读:
    Adobe flash player更新失败
    配置NAT回流导致外网解析到了内网IP
    Android下海康实时视频解码
    红米无线不稳定问题
    TP-Link路由器刷dd-wrt的linux,无线信号增强不少
    发布FTP服务,防火墙配置
    SQL SERVER 实现分组合并实现列数据拼接
    MyGeneration 数据库驱动为空
    WIND2003 安装Zend studio 报错
    TOAD FOR MYSQL 进行数据插入时乱码的解决办法---MariaDB 5.5
  • 原文地址:https://www.cnblogs.com/wangxiaoyong/p/12568349.html
Copyright © 2011-2022 走看看