• 【操作系统·Operating System】操作系统


    6.828

    两个神级教学项目: nand2tetris 与 MIT6.828
    class : MIT 6.828
    refers: inline assembly | I/O Ports | 8086寄存器略解 | x86-64架构寄存器详解
    notes: [MIT] 6.828 操作系统工程导读 | MIT6.828-神级OS课程

    Lab1

    Exercise 2: BIOS
    make gdb
    [root@VM-0-8-centos lab]# make gdb
    The target architecture is assumed to be i8086
    [f000:fff0]    0xffff0: ljmp   $0xf000,$0xe05b
    0x0000fff0 in ?? ()
    + symbol-file obj/kern/kernel
    (gdb) si
    [f000:e05b]    0xfe05b: cmpl   $0x0,%cs:0x6ac8
    0x0000e05b in ?? ()
    (gdb) si
    [f000:e062]    0xfe062: jne    0xfd2e1
    0x0000e062 in ?? ()
    (gdb) si
    [f000:e066]    0xfe066: xor    %dx,%dx
    0x0000e066 in ?? ()
    (gdb) si
    [f000:e068]    0xfe068: mov    %dx,%ss
    0x0000e068 in ?? ()
    (gdb) si
    [f000:e06a]    0xfe06a: mov    $0x7000,%esp
    0x0000e06a in ?? ()
    (gdb) si
    [f000:e070]    0xfe070: mov    $0xf34c2,%edx
    0x0000e070 in ?? ()
    (gdb) si
    [f000:e076]    0xfe076: jmp    0xfd15c
    0x0000e076 in ?? ()
    (gdb) si
    [f000:d15c]    0xfd15c: mov    %eax,%ecx
    0x0000d15c in ?? ()
    (gdb) si
    [f000:d15f]    0xfd15f: cli
    0x0000d15f in ?? ()
    (gdb) si
    [f000:d160]    0xfd160: cld
    0x0000d160 in ?? ()
    (gdb) si
    [f000:d161]    0xfd161: mov    $0x8f,%eax
    0x0000d161 in ?? ()
    (gdb) si
    [f000:d167]    0xfd167: out    %al,$0x70    //屏蔽NMI中断信号
    0x0000d167 in ?? ()
    (gdb) si
    [f000:d169]    0xfd169: in     $0x71,%al
    0x0000d169 in ?? ()
    (gdb) si
    [f000:d16b]    0xfd16b: in     $0x92,%al
    0x0000d16b in ?? ()
    (gdb) si
    [f000:d16d]    0xfd16d: or     $0x2,%al
    0x0000d16d in ?? ()
    (gdb) si
    [f000:d16f]    0xfd16f: out    %al,$0x92    //开启A20地址线
    0x0000d16f in ?? ()
    (gdb) si
    [f000:d171]    0xfd171: lidtw  %cs:0x6ab8    //设置中断描述表
    0x0000d171 in ?? ()
    (gdb) si
    [f000:d177]    0xfd177: lgdtw  %cs:0x6a74    //设置全局描述表
    0x0000d177 in ?? ()
    (gdb) si
    [f000:d17d]    0xfd17d: mov    %cr0,%eax    //CPU控制寄存器cr0
    0x0000d17d in ?? ()
    (gdb) si
    [f000:d180]    0xfd180: or     $0x1,%eax
    0x0000d180 in ?? ()
    (gdb) si
    [f000:d184]    0xfd184: mov    %eax,%cr0    //PE位置1,保护模式
    0x0000d184 in ?? ()
    (gdb) si
    [f000:d187]    0xfd187: ljmpl  $0x8,$0xfd18f
    0x0000d187 in ?? ()
    (gdb) si
    The target architecture is assumed to be i386
    => 0xfd18f:     mov    $0x10,%eax
    0x000fd18f in ?? ()
    (gdb) si
    => 0xfd194:     mov    %eax,%ds
    0x000fd194 in ?? ()
    (gdb) si
    => 0xfd196:     mov    %eax,%es
    0x000fd196 in ?? ()
    (gdb) si
    => 0xfd198:     mov    %eax,%ss
    0x000fd198 in ?? ()
    (gdb) si
    => 0xfd19a:     mov    %eax,%fs
    0x000fd19a in ?? ()
    (gdb) si
    => 0xfd19c:     mov    %eax,%gs
    0x000fd19c in ?? ()
    (gdb) si
    => 0xfd19e:     mov    %ecx,%eax
    0x000fd19e in ?? ()
    (gdb) si
    => 0xfd1a0:     jmp    *%edx
    0x000fd1a0 in ?? ()
    (gdb) si
    => 0xf34c2:     push   %ebx
    0x000f34c2 in ?? ()
    (gdb) si
    => 0xf34c3:     sub    $0x2c,%esp
    0x000f34c3 in ?? ()
    (gdb) si
    => 0xf34c6:     movl   $0xf5b5c,0x4(%esp)
    0x000f34c6 in ?? ()
    (gdb) si
    => 0xf34ce:     movl   $0xf447b,(%esp)
    0x000f34ce in ?? ()
    (gdb) si
    => 0xf34d5:     call   0xf099e
    0x000f34d5 in ?? ()
    (gdb) si
    => 0xf099e:     lea    0x8(%esp),%ecx
    0x000f099e in ?? ()
    (gdb) si
    => 0xf09a2:     mov    0x4(%esp),%edx
    0x000f09a2 in ?? ()
    (gdb) si
    => 0xf09a6:     mov    $0xf5b58,%eax
    0x000f09a6 in ?? ()
    (gdb) si
    => 0xf09ab:     call   0xf0574
    0x000f09ab in ?? ()
    (gdb) si
    => 0xf0574:     push   %ebp
    0x000f0574 in ?? ()
    (gdb) si
    => 0xf0575:     push   %edi
    0x000f0575 in ?? ()
    (gdb) si
    => 0xf0576:     push   %esi
    0x000f0576 in ?? ()
    (gdb) si
    => 0xf0577:     push   %ebx
    0x000f0577 in ?? ()
    (gdb) si
    => 0xf0578:     sub    $0xc,%esp
    0x000f0578 in ?? ()
    (gdb) si
    => 0xf057b:     mov    %eax,0x4(%esp)
    0x000f057b in ?? ()
    (gdb) si
    => 0xf057f:     mov    %edx,%ebp
    0x000f057f in ?? ()
    (gdb) si
    => 0xf0581:     mov    %ecx,%esi
    0x000f0581 in ?? ()
    
    Ecercise 3: the Boot Loader
    questions
    • At what point does the processor start executing 32-bit code? What exactly causes the switch from 16- to 32-bit mode?

    ljmp $PROT_MODE_CSEG, $protcseg
    设置了A20地址线

    • What is the last instruction of the boot loader executed, and what is the first instruction of the kernel it just loaded?

    boot/main.c中 ELFHDR->e_entry 0x7d61

    • Where is the first instruction of the kernel?

    kernel: 0x10018

    • How does the boot loader decide how many sectors it must read in order to fetch the entire kernel from disk? Where does it find this information?

    Part 3: The Kernel

    我们将会开始稍微细节地研究JOS的内核的最小部分,(而且我们终于即将开始写一些代码)。像bootloader一样,Kernel也从一些汇编代码开始,设置好环境以便C语言可以方便地运行。
    
    使用虚拟内存来位置依赖工作
    boot loader的链接地址和加载地址是完美一致的,但kernel的链接地址和加载地址就有分歧了。
    操作系统内核通常被在高虚拟地址被链接和运行,例如0xf0100000,这是为了给用户程序留下处理器的低虚拟地址空间来运行。下个lab会更加清晰。
    很多机器没有这么多的物理空间,所以不能指望把kernel放在那里。替代地,我们会使用处理器内存管理硬件来讲虚拟地址映射到物理地址。这样,kernel的虚拟地址就足够高而留给用户程序足够地址空间了。kernel被加载到物理空间0x00100000,1MB位置,就在BIOS ROM之上。
    现在我们只需要映射4MB的物理地址就足够了。我们通过一个手写的、静态初始化的kern/entrypgdir.c里的页目录和页表来实习。现在,我们不需要理解这些工资的细节,只需了解到这项可以达成的结果。指导kern/entry.S设置CR0_PG标志之后,内存引用才被当作物理地址,而且我们也不会改变这个。一旦CR0_PG被设定,内存引用就是被虚拟内存硬件从虚拟地址翻译到的物理地址了。entrypgdir将0xf0000000到0xf04000000的虚拟地址翻译成0x00000000到0x00400000的物理地址(反之亦然)。任何超出范围的虚拟地址都会造成硬件异常,而且因为我们还没有设置终端处理,进而会造成QEMU抛出机器状态和退出。
    
    Exercise 7:
    • Use QEMU and GDB to trace into the JOS kernel and stop at the movl %eax, %cr0. Examine memory at 0x00100000 and at 0xf0100000. Now, single step over that instruction using the stepi GDB command. Again, examine memory at 0x00100000 and at 0xf0100000. Make sure you understand what just happened.
    kernel
    => 0x10001d:    mov    %cr0,%eax
    0x0010001d in ?? ()
    (gdb) info registers
    eax            0x110000 1114112
    ecx            0x0      0
    edx            0x9d     157
    ebx            0x10094  65684
    esp            0x7bec   0x7bec
    ebp            0x7bf8   0x7bf8
    esi            0x10094  65684
    edi            0x0      0
    eip            0x10001d 0x10001d
    eflags         0x46     [ PF ZF ]
    cs             0x8      8
    ss             0x10     16
    ds             0x10     16
    es             0x10     16
    fs             0x10     16
    gs             0x10     16
    (gdb) si
    => 0x100020:    or     $0x80010001,%eax
    0x00100020 in ?? ()
    (gdb) info registers
    eax            0x11     17
    ecx            0x0      0
    edx            0x9d     157
    ebx            0x10094  65684
    esp            0x7bec   0x7bec
    ebp            0x7bf8   0x7bf8
    esi            0x10094  65684
    edi            0x0      0
    eip            0x100020 0x100020
    eflags         0x46     [ PF ZF ]
    cs             0x8      8
    ss             0x10     16
    ds             0x10     16
    es             0x10     16
    fs             0x10     16
    gs             0x10     16
    (gdb) si
    => 0x100025:    mov    %eax,%cr0
    0x00100025 in ?? ()
    (gdb) info registers
    eax            0x80010011       -2147418095
    ecx            0x0      0
    edx            0x9d     157
    ebx            0x10094  65684
    esp            0x7bec   0x7bec
    ebp            0x7bf8   0x7bf8
    esi            0x10094  65684
    edi            0x0      0
    eip            0x100025 0x100025
    eflags         0x86     [ PF SF ]
    cs             0x8      8
    ss             0x10     16
    ds             0x10     16
    es             0x10     16
    fs             0x10     16
    gs             0x10     16
    (gdb) x/8x 0x00100000
    0x100000:       0x1badb002      0x00000000      0xe4524ffe      0x7205c766
    0x100010:       0x34000004      0x0000b812      0x220f0011      0xc0200fd8
    (gdb) x/8x 0xf0100000
    0xf0100000 : 0x00000000      0x00000000      0x00000000      0x00000000
    0xf0100010 :   0x00000000      0x00000000      0x00000000      0x00000000
    (gdb) si
    => 0x100028:    mov    $0xf010002f,%eax
    0x00100028 in ?? ()
    (gdb) si
    => 0x10002d:    jmp    *%eax
    0x0010002d in ?? ()
    (gdb) si
    => 0xf010002f :      mov    $0x0,%ebp
    relocated () at kern/entry.S:74
    74              movl    $0x0,%ebp                       # nuke frame pointer
    (gdb) x/8x 0x00100000
    0x100000:       0x1badb002      0x00000000      0xe4524ffe      0x7205c766
    0x100010:       0x34000004      0x0000b812      0x220f0011      0xc0200fd8
    (gdb) x/8x 0xf0100000
    0xf0100000 : 0x1badb002      0x00000000      0xe4524ffe      0x7205c766
    0xf0100010 :   0x34000004      0x0000b812      0x220f0011      0xc0200fd8
    
    
    • What is the first instruction after the new mapping is established that would fail to work properly if the mapping weren't in place? Comment out the movl %eax, %cr0 in kern/entry.S, trace into it, and see if you were right.
      将CR0最高位置1,paging可以了,然后通过*%rax进入0xf010002f。
    qemu fatal
    [root@VM-0-8-centos lab]# make qemu-gdb
    + as kern/entry.S
    + ld obj/kern/kernel
    ld: warning: section `.bss' type changed to PROGBITS
    + mk obj/kern/kernel.img
    ***
    *** Now run 'make gdb'.
    ***
    qemu-system-i386 -drive file=obj/kern/kernel.img,index=0,media=disk,format=raw -serial mon:stdio -gdb tcp::                                                                                                                              25000 -D qemu.log  -S
    VNC server running on `::1:5900'
    qemu: fatal: Trying to execute code outside RAM or ROM at 0xf010002c
    
    EAX=f010002c EBX=00010094 ECX=00000000 EDX=0000009d
    ESI=00010094 EDI=00000000 EBP=00007bf8 ESP=00007bec
    EIP=f010002c EFL=00000086 [--S--P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
    ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
    CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
    SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
    DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
    FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
    GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
    LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
    TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
    GDT=     00007c4c 00000017
    IDT=     00000000 000003ff
    CR0=00000011 CR2=00000000 CR3=00110000 CR4=00000000
    DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
    DR6=ffff0ff0 DR7=00000400
    CCS=00000084 CCD=80010011 CCO=EFLAGS
    EFER=0000000000000000
    FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
    FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
    FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
    FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
    FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
    XMM00=00000000000000000000000000000000 XMM01=00000000000000000000000000000000
    XMM02=00000000000000000000000000000000 XMM03=00000000000000000000000000000000
    XMM04=00000000000000000000000000000000 XMM05=00000000000000000000000000000000
    XMM06=00000000000000000000000000000000 XMM07=00000000000000000000000000000000
    make: *** [qemu-gdb] Aborted
    
    格式化输出到控制台
    在OS kernel中,我们需要自己完成所有类似 printf() 的I/O函数。
    通读kern/printf.c, lib/printfmt.c 和 kern/console.c,了解它们之间的关系。之后你会更清晰为什么printfmt.c在于单独的lib目录。
    
    Exercise 8.
    • We have omitted a small fragment of code - the code necessary to print octal numbers using patterns of the form "%o". Find and fill in this code fragment.

    Process Management

    内存中的进程|操作系统内的进程表示PCB
    进程调度

    graph LR; A(job queue)-->B(ready queue) A-->C(device queue)

    IPC

    Memory Management

    Storage Management

    from Chu
  • 相关阅读:
    Oracle的数据伪列(ROWNUM)
    数据库的多表查询(详细案例分析)
    计算1至n的k次方的和
    位数对调(代码重构)
    java实现汉诺塔算法
    线程与进程详解
    java中properties的使用实例
    java中同步(synchronized)详解
    文件的拷贝操作
    文件的读取操作
  • 原文地址:https://www.cnblogs.com/chubuyu/p/15137689.html
Copyright © 2020-2023  润新知