• Ucore lab1实验报告


    练习一 Makefile

    1.1 OS镜像文件ucore.img 是如何一步步生成的?

    + cc kern/init/init.c
    + cc kern/libs/readline.c
    + cc kern/libs/stdio.c
    + cc kern/debug/kdebug.c
    + cc kern/debug/kmonitor.c
    + cc kern/debug/panic.c
    kern/debug/panic.c: In function '__panic':
    kern/debug/panic.c:27:5: warning: implicit declaration of function 'print_stackframe' [-Wimplicit-function-declaration]
         print_stackframe();
         ^
    + cc kern/driver/clock.c
    + cc kern/driver/console.c
    + cc kern/driver/intr.c
    + cc kern/driver/picirq.c
    + cc kern/trap/trap.c
    + cc kern/trap/trapentry.S
    + cc kern/trap/vectors.S
    + cc kern/mm/pmm.c
    + cc libs/printfmt.c
    + cc libs/string.c
    + ld bin/kernel
    + cc boot/bootasm.S
    + cc boot/bootmain.c
    + cc tools/sign.c
    tools/sign.c: In function 'main':
    tools/sign.c:17:5: warning: unknown conversion type character 'l' in format [-Wformat=]
         printf("'%s' size: %lld bytes
    ", argv[1], (long long)st.st_size);
         ^
    tools/sign.c:17:5: warning: too many arguments for format [-Wformat-extra-args]
    tools/sign.c:19:9: warning: unknown conversion type character 'l' in format [-Wformat=]
             fprintf(stderr, "%lld >> 510!!
    ", (long long)st.st_size);
             ^
    tools/sign.c:19:9: warning: too many arguments for format [-Wformat-extra-args]
    + ld bin/bootblock
    'obj/bootblock.out' size: 480 bytes
    build 512 bytes boot sector: 'bin/bootblock' success!

    其中Makefile文件中include tools/function.mk  其中定义了一些Makefile中用到的函数

    生成ucore.img  需要kernel和bootblock 如下:

    # create ucore.img
    UCOREIMG    := $(call totarget,ucore.img)
    
    $(UCOREIMG): $(kernel) $(bootblock)
        $(V)dd if=/dev/zero of=$@ count=10000
        $(V)dd if=$(bootblock) of=$@ conv=notrunc
        $(V)dd if=$(kernel) of=$@ seek=1 conv=notrunc
    
    $(call create_target,ucore.img)

    kernel编译链接:

    # -------------------------------------------------------------------
    # kernel
    
    # kernel中头文件目录
    KINCLUDE    += kern/debug/ 
                   kern/driver/ 
                   kern/trap/ 
                   kern/mm/
    
    # kernel的源代码目录
    KSRCDIR        += kern/init 
                   kern/libs 
                   kern/debug 
                   kern/driver 
                   kern/trap 
                   kern/mm
    
    # 在编译选项中添加头文件包含目录
    KCFLAGS        += $(addprefix -I,$(KINCLUDE))
    
    # 调用function.mk中的add_files_cc函数,将kernel的全部源文件编译,将源文件和编译生成的OBJ文件加入kernel包(packet)中
    $(call add_files_cc,$(call listf_cc,$(KSRCDIR)),kernel,$(KCFLAGS))
    
    # 将KOBJS定义为编译生成的.o文件列表(大概??)
    KOBJS    = $(call read_packet,kernel libs)
    
    # create kernel target
    # (在kernel前面加上bin/目录名)
    kernel = $(call totarget,kernel)
    
    # kernel目标依赖于tools/kernel.ld文件
    $(kernel): tools/kernel.ld
    
    # kernel目标依赖于编译生成的OBJ文件
    $(kernel): $(KOBJS)
            # 输出"+ ld bin/kernel"到控制台
        @echo + ld $@
        # 即命令"ld -m    elf_i386 -nostdlib -T tools/kernel.ld -o bin/kernel  obj/kern/init/init.o ... obj/libs/printfmt.o"
        $(V)$(LD) $(LDFLAGS) -T tools/kernel.ld -o $@ $(KOBJS)
        # 将OBJ文件全部反编译为汇编文件
        @$(OBJDUMP) -S $@ > $(call asmfile,kernel)
        # 输出OBJ文件对应的符号表
        @$(OBJDUMP) -t $@ | $(SED) '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $(call symfile,kernel)
    
    # 将kernel包和OBJ文件添加到目标依赖
    $(call create_target,kernel)

    bootblock:

    # -------------------------------------------------------------------
    
    # create bootblock
    # bootfiles为boot/文件夹下的全部文件列表
    bootfiles = $(call listf_cc,boot)
    # 编译boot/文件夹下的全部文件
    $(foreach f,$(bootfiles),$(call cc_compile,$(f),$(CC),$(CFLAGS) -Os -nostdinc))
    
    # (在bootblock前面加上bin/目录名)
    bootblock = $(call totarget,bootblock)
    
    # bootblock目标的依赖项为源文件对应的OBJ文件和bin/sign
    $(bootblock): $(call toobj,$(bootfiles)) | $(call totarget,sign)
            # 输出"+ ld bin/bootblock"到控制台
            @echo + ld $@
            # 将OBJ文件链接为bin/bootblock
        $(V)$(LD) $(LDFLAGS) -N -e start -Ttext 0x7C00 $^ -o $(call toobj,bootblock)
        # 将bin/bootblock文件反编译
        @$(OBJDUMP) -S $(call objfile,bootblock) > $(call asmfile,bootblock)
        # 将bin/bootblock转换成bin/bootblock.out二进制文件
        @$(OBJCOPY) -S -O binary $(call objfile,bootblock) $(call outfile,bootblock)
        # 用链接出的bin/sign工具将bin/bootblock.out再转换回bin/bootblock二进制文件
        @$(call totarget,sign) $(call outfile,bootblock) $(bootblock)
    
    # 将bootblock包添加到bootblock目标
    $(call create_target,bootblock)

    sign:

    # -------------------------------------------------------------------
    
    # create 'sign' tools
    # 将tools/sign.c编译到OBJ文件,将源文件和中间文件添加到sign包
    $(call add_files_host,tools/sign.c,sign,sign)
    # 将sign包添加到sign目标
    $(call create_target_host,sign,sign)

    ucore.img:

    # -------------------------------------------------------------------
    
    # create ucore.img
    # 在ucore.img前面加上bin/
    UCOREIMG    := $(call totarget,ucore.img)
    
    $(UCOREIMG): $(kernel) $(bootblock)
            # 创建一个大小为10000字节的空白文件
        $(V)dd if=/dev/zero of=$@ count=10000
        # 向上述文件中拷贝bin/bootblock
        $(V)dd if=$(bootblock) of=$@ conv=notrunc
        # 向上述文件中继续(第二个块)拷贝bin/kernel
        $(V)dd if=$(kernel) of=$@ seek=1 conv=notrunc
    
    # 将ucore.img包添加到ucore.img目标
    $(call create_target,ucore.img)

    dd的一些参数的含义:(dd命令说明
    -if表示输入文件,如果不指定,那么会默认从stdin中读取输入
    -of表示输出文件,如果不指定,那么会stdout
    bs表示以字节为单位的块大小
    count表示被赋值的块数
    /dev/zero是一个字符设备,会不断返回0值字节
    conv = notrunc 不截短输出文件
    seek=blocks 从输出文件开头跳过blocks个块后再开始复制

    生成kernel的.obj实际命令:

    gcc -Ikern/init/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/init/init.c -o obj/kern/init/init.o
    gcc -Ikern/libs/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/libs/stdio.c -o obj/kern/libs/stdio.o
    gcc -Ikern/libs/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/libs/readline.c -o obj/kern/libs/readline.o
    gcc -Ikern/debug/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/debug/panic.c -o obj/kern/debug/panic.o
    gcc -Ikern/debug/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/debug/kdebug.c -o obj/kern/debug/kdebug.o
    gcc -Ikern/debug/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/debug/kmonitor.c -o obj/kern/debug/kmonitor.o
    gcc -Ikern/driver/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/clock.c -o obj/kern/driver/clock.o
    gcc -Ikern/driver/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/console.c -o obj/kern/driver/console.o
    gcc -Ikern/driver/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/picirq.c -o obj/kern/driver/picirq.o
    gcc -Ikern/driver/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/intr.c -o obj/kern/driver/intr.o
    gcc -Ikern/trap/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/trap/trap.c -o obj/kern/trap/trap.o
    gcc -Ikern/trap/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/trap/vectors.S -o obj/kern/trap/vectors.o
    gcc -Ikern/trap/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/trap/trapentry.S -o obj/kern/trap/trapentry.o
    gcc -Ikern/mm/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/mm/pmm.c -o obj/kern/mm/pmm.o
    gcc -Ilibs/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/  -c libs/string.c -o obj/libs/string.o
    gcc -Ilibs/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/  -c libs/printfmt.c -o obj/libs/printfmt.o

    参数及其意义:(gcc官方文档

      • -I:添加包含目录
      • -fno-builtin:只接受以“__builtin_”开头的名称的内建函数
      • -Wall:开启全部警告提示
      • -ggdb:生成GDB需要的调试信息
      • -m32:为32位环境生成代码,int、long和指针都是32位
      • -gstab:生成stab格式的调试信息,仅用于gdb
      • -nostdinc:不扫描标准系统头文件,只在-I指令指定的目录中扫描
      • -fno-stack-protector:生成用于检查栈溢出的额外代码,如果发生错误,则打印错误信息并退出
      • -c:编译源文件但不进行链接
      • -o:结果的输出文件

    链接生成kernel二进制文件的命令为:

      • ld -m    elf_i386 -nostdlib -T tools/kernel.ld -o bin/kernel  obj/kern/init/init.o obj/kern/libs/stdio.o obj/kern/libs/readline.o obj/kern/debug/panic.o obj/kern/debug/kdebug.o obj/kern/debug/kmonitor.o obj/kern/driver/clock.o obj/kern/driver/console.o obj/kern/driver/picirq.o obj/kern/driver/intr.o obj/kern/trap/trap.o obj/kern/trap/vectors.o obj/kern/trap/trapentry.o obj/kern/mm/pmm.o  obj/libs/string.o obj/libs/printfmt.o

        参数及其意义:(ld参数说明

        • -m elf_i386:使用elf_i386模拟器
        • -nostdlib:只查找命令行中明确给出的库目录,不查找链接器脚本中给出的(即使链接器脚本是在命令行中给出的)
        • -T tools/kernel.ld:将tools/kernel.ld作为链接器脚本
        • -o bin/kernel:输出到bin/kernel文件

        生成bootblock和sign工具所需全部OBJ文件的实际命令包括:

        gcc -Iboot/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Os -nostdinc -c boot/bootasm.S -o obj/boot/bootasm.o
        gcc -Iboot/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/ -Os -nostdinc -c boot/bootmain.c -o obj/boot/bootmain.o
        gcc -Itools/ -g -Wall -O2 -c tools/sign.c -o obj/sign/tools/sign.o
        gcc -g -Wall -O2 obj/sign/tools/sign.o -o bin/sign

        参数及其意义(重复的参数不再列出):

        • -Os:对输出文件大小进行优化,开启全部不增加代码大小的-O2优化
        • -g:以操作系统原生格式输出调试信息,gdb可以处理这一信息
        • -O2:进行大部分不以空间换时间的优化

        链接生成bootblock二进制文件的命令为:

        ld -m    elf_i386 -nostdlib -N -e start -Ttext 0x7C00 obj/boot/bootasm.o obj/boot/bootmain.o -o obj/bootblock.o
        'obj/bootblock.out' size: 488 bytes
        build 512 bytes boot sector: 'bin/bootblock' success!(这两行是sign的输出)

        参数及其意义:

          • -N:将文字和数据部分置为可读写,不将数据section置为与页对齐, 不链接共享库
          • -e start:将start符号置为程序起始点
          • -Ttext 0x7C00:链接时将".bss"、".data"或".text"置于绝对地址0x7C00

    1.2 一个被系统认为是符合规范的硬盘主引导扇区的特征是什么?

    tool/sign.c

    输入的主引导扇区记录小于等于510字节(446+64)

    最后两个字节是0x55AA

    练习2:

      使用Qemu和gdb调试lab1 实验目的:熟悉单步调试gdb方法 进一步了解os启动流程

    练习3:

      bootloader进入保护模式的过程

      BIOS通过读取硬盘主引导扇区到内存,并跳转到对应内存中的位置执行bootloader,从实模式转换到保护模式。

    bootloader启动过程主要工作:1切换到保护模式,启用分段机制

         2读磁盘中ELF执行文件格式的ucore到内存

         3显示字符串信息

         4把控制权交给ucore操作系统

    1.开启A20地址线

    2.初始化GDT表

    3.进入保护模式

    Talk is cheap,show me your code
  • 相关阅读:
    深入研究Servlet线程安全性问题
    Sun公司java语言编码规范
    JAVA的内省机制(introspector)与反射机制(reflection)[转]
    Oracle的悲观锁和乐观锁
    java中120个经典问题
    自定义Java异常
    Java事务处理总结
    Tomcat内存溢出的三种情况及解决办法分析
    .net基础
    C#.Net中的转义
  • 原文地址:https://www.cnblogs.com/likong/p/10983725.html
Copyright © 2020-2023  润新知