ucore lab1

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

问题一:操作系统镜像文件ucore.img是如何一步一步生成的?(需要比较详细地解释Makefile中每一条相关命令和命令参数的含义,以及说明命令导致的结果)

在Makefile中生成ucore.img的代码如下:

# 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)

首先先创建一个大小为10000字节的块儿,然后再将bootblock拷贝过去。
生成ucore.img需要先生成kernelbootblock

通过make V=指令得到执行的具体命令如下:

# 编译 init.c 文件,生成 init.o 
+ cc kern/ern/init/init.c
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

# 编译 readline.c 文件,生成 readline.o
+ cc kern/libs/readline.c
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

# 编译 stdio.c 文件,生成 stdio.o
+ cc kern/libs/stdio.c
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

# 编译 kdebug.c 文件,生成 kdebug.o
+ cc kern/debug/kdebug.c
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

# 编译 kmonitor.c 文件,生成 kmonitor.o
+ cc kern/debug/kmonitor.c
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

# 编译 panic.c 文件,生成 painc.o
+ cc kern/debug/panic.c
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

# 编译一系列 .c 文件
+ cc kern/driver/clock.c
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
+ cc kern/driver/console.c
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
+ cc kern/driver/intr.c
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
+ cc kern/driver/picirq.c
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
+ cc kern/trap/trap.c
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
+ cc kern/trap/trapentry.S
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
+ cc kern/trap/vectors.S
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
+ cc kern/mm/pmm.c
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
+ cc libs/printfmt.c
gcc -Ilibs/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/  -c libs/printfmt.c -o obj/libs/printfmt.o
+ cc libs/string.c
gcc -Ilibs/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc  -fno-stack-protector -Ilibs/  -c libs/string.c -o obj/libs/string.o

# 链接生成的所有目标文件,并生成 kernel 二进制文件
+ ld bin/kernel
ld -m    elf_i386 -nostdlib -T tools/kernel.ld -o bin/kernel  obj/kern/init/init.o obj/kern/libs/readline.o obj/kern/libs/stdio.o obj/kern/debug/kdebug.o obj/kern/debug/kmonitor.o obj/kern/debug/panic.o obj/kern/driver/clock.o obj/kern/driver/console.o obj/kern/driver/intr.o obj/kern/driver/picirq.o obj/kern/trap/trap.o obj/kern/trap/trapentry.o obj/kern/trap/vectors.o obj/kern/mm/pmm.o  obj/libs/printfmt.o obj/libs/string.o

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

# 生成 sign 文件
gcc -g -Wall -O2 obj/sign/tools/sign.o -o bin/sign

# 链接生成 bootblock 二进制文件
+ ld bin/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!

# 生成ucore.img文件
dd if=/dev/zero of=bin/ucore.img count=10000
10000+0 records in
10000+0 records out
5120000 bytes (5.1 MB) copied, 0.0325965 s, 157 MB/s
dd if=bin/bootblock of=bin/ucore.img conv=notrunc
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.000118495 s, 4.3 MB/s
dd if=bin/kernel of=bin/ucore.img seek=1 conv=notrunc
146+1 records in
146+1 records out
74923 bytes (75 kB) copied, 0.00055858 s, 134 MB/s

根据其中可以看到,要生成kernel,需要用GCC编译器将kern目录下所有的.c文件全部编译生成的.o文件的支持。同样,要生成bootblock,首先需要生成bootasm.o、bootmain.o、sign

GCC 编译选项详解:

编译选项 含义
-I 指定库文件包含路径(① 指定值 ② 环境变量 ③ 标准系统搜索路径)
-fno-builtin 只识别以 __builtin_为前缀的 GCC 內建函数,禁用大多数內建函数,防止与其重名
-Wall 编译后显示所有警告信息
-ggdb 使用 GDB 加入调试信息
-m32 生成 32位机器代码,int long pointer 都是 32 位,指定x86处理器特定选项处理器依赖选项
-gstabs 产生 stabs 格式的调试信息,不包含 GDB 扩展
-nostdinc 不搜索标准系统目录的头文件,只搜索 -I / -iquote / -isystem / -dirafter指定的头文件, 目录选项
-fno-stack-protector 禁用堆栈保护机制,工具选项
-c 编译或汇编源文件,但是不进行链接。将.c/.i/.s等后缀的文件编译成 .o 后缀。输出类型控制
-O 优化生成的代码,-Os 仅仅是优化生成代码的大小,它开启了所有的-O2优化选项,除了那些会使代码尺寸增大的选项。 优化选项

LD 编译选项详解:

编译选项 含义
-m 指定生成文件的格式,默认使用 LDEMULATION环境变量,如果没有这个环境变量,则依赖与linker 的默认配置。通过 ld -V 可以查看它支持的 emulation
-nostdlib 只搜索命令行中显示制定的库目录,链接脚本里面制定的目录被忽略,包括命令行中制定的链接脚本。
-N 设置 text and data section 可读写,数据段不进行页对其,不链接动态链接库
-e entry 指定程序开始执行的入口函数,而不是默认的入口点。
-Tbss=org / -Tdata=org / -Ttext=org 通过 org 制定一个 section 在输出文件中的绝对地址。

dd 磁盘维护命令详解:

Linux dd命令用于读取、转换并输出数据。dd可从标准输入或文件中读取数据,根据指定的格式来转换数据,再输出到文件、设备或标准输出。

if = 文件名:输入文件名,缺省为标准输入。
of = 文件名:输出文件名,缺省为标准输出。
	ibs = bytes:一次读入bytes个字节,即指定一个块大小为bytes个字节。(默认 512 字节)
	obs = bytes:一次输出bytes个字节,即指定一个块大小为bytes个字节。(默认 512 字节)
	bs = bytes:同时设置读入/输出的块大小为bytes个字节。
	cbs = bytes:一次转换bytes个字节,即指定转换缓冲区大小。
skip = blocks:从输入文件开头跳过blocks个块后再开始复制。
seek = blocks:从输出文件开头跳过blocks个块后再开始复制。
count = blocks:仅拷贝blocks个块,块大小等于ibs指定的字节数。
conv = <关键字>,关键字可以有以下11种:
	conversion:用指定的参数转换文件。
	ascii:转换ebcdic为ascii
	ebcdic:转换ascii为ebcdic
	ibm:转换ascii为alternate ebcdic
	block:把每一行转换为长度为cbs,不足部分用空格填充
	unblock:使每一行的长度都为cbs,不足部分用空格填充
	lcase:把大写字符转换为小写字符
	ucase:把小写字符转换为大写字符
	swab:交换输入的每对字节
	noerror:出错时不停止
	notrunc:不截短输出文件
	sync:将每个输入块填充到ibs个字节,不足部分用空(NUL)字符补齐。

N and BYTES may be followed by the following multiplicative suffixes:
c =1, w =2, b =512, kB =1000, K =1024, MB =1000*1000, M =1024*1024, xM =M
GB =1000*1000*1000, G =1024*1024*1024, and so on for T, P, E, Z, Y.

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

回答:硬盘主引导扇区的 size = 512 Bytes,并且最后两个字节为0x55AA

在 sign.c 作了如下检查:

    //检查主引导扇区大小
		if (size != 512) {
   
        fprintf(stderr, "write '%s' error, size is %d.\n", argv[2], size);
        return -1;
    }
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值