ucore lab1练习1

练习1:理解通过make生成执行文件的过程。(要求在报告中写出对下述问题的回答)

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

执行make v=后的结果(做了过滤处理)

#编译kern
+ cc kern/init/init.c
+ cc kern/libs/stdio.c
+ cc kern/libs/readline.c
+ cc kern/debug/panic.c
+ cc kern/debug/kdebug.c
+ cc kern/debug/kmonitor.c
+ cc kern/driver/clock.c
+ cc kern/driver/console.c
+ cc kern/driver/picirq.c
+ cc kern/driver/intr.c
+ cc kern/trap/trap.c
+ cc kern/trap/vectors.S
+ cc kern/trap/trapentry.S
+ cc kern/mm/pmm.c
+ cc libs/string.c
+ cc libs/printfmt.c
+ ld bin/kernel     //这条指令进行连接

#编译bootblock与sign.c文件
+ cc boot/bootasm.S
+ cc boot/bootmain.c
 #编译后的sign.c用于执行,不用于链接,把boot文件变为有效的
+ cc tools/sign.c 
+ ld bin/bootblock

#sign文件处理bootblock,使其变为符合规范的硬盘主引导扇区
#这里bootblock从492byte变成512byte
'obj/bootblock.out' size: 492 bytes
build 512 bytes boot sector: 'bin/bootblock' success!


#这里把kernel和bootblock装载到img文件里面(dd命令)
#count=n选项是装载到第N块停止,一块默认位512字节
#if参数:输入 of:输出
#这里先把0填充进img文件
dd if=/dev/zero of=bin/ucore.img count=10000

# conv = notrunc 不截断输出文件。
# seek=blocks:从输出文件开头跳过blocks个块后再开始复制。
dd if=bin/bootblock of=bin/ucore.img conv=notrunc
dd if=bin/kernel of=bin/ucore.img seek=1 conv=notrunc

知道了编译过程,分析makefile中的指令吧。

这里首先第一步:生成ucore.img的命令:

# 源代码第199到209行
# create ucore.img
UCOREIMG	:= $(call totarget,ucore.img)

$(UCOREIMG): $(kernel) $(bootblock) $(kernel_nopage)
	$(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)

# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
这里逐行分析:
200行:UCOREIMG	:= $(call totarget,ucore.img)
    这里调用了totarget函数
    totarget没有在本文中定义,而是在第91行引入的function.mk中。
    17(mk):totarget = $(addprefix $(BINDIR)$(SLASH),$(1))
    4:SLASH	:= /    
    85:BINDIR	:= bin
    清楚的看出来,totarget的目的是在ucore.img前加上bin/前缀


59:生成UCOREIMG所需要的依赖
60:V定义在第6行,方便调试打印。
64:(call create_target,ucore.img)
    这里这个函数看的不是太懂,应该是一个调用关系

执行生成kernel的代码:(140-153行)

# create kernel target
kernel = $(call totarget,kernel)

$(kernel): tools/kernel.ld

$(kernel): $(KOBJS)
	@echo + ld $@
	$(V)$(LD) $(LDFLAGS) -T tools/kernel.ld -o $@ $(KOBJS)
	@$(OBJDUMP) -S $@ > $(call asmfile,kernel)
	@$(OBJDUMP) -t $@ | $(SED) '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $(call symfile,kernel)

$(call create_target,kernel)

# -------------------------------------------------------------------

逐行分析:

141:kernel = $(call totarget,kernel)  #加上bin前缀
143:$(kernel): tools/kernel.ld             #依赖文件,一个链接器
145:$(kernel): $(KOBJS)                        #这里用到KOBJS依赖
    138:KOBJS	= $(call read_packet,kernel libs)   #调用read_packet函数
    90(mk):read_packet = $(foreach p,$(call packetname,$(1)),$($(p)))
    20(mk):packetname = $(if $(1),$(addprefix $(OBJPREFIX),$(1)),$(OBJPREFIX))
    1(mk):OBJPREFIX	:= __objs_
    仅仅读这里执行出来的结果是:OBJPREFIX=__objs_kernel __objs_kernel_lib
    但是根据136行:$(call add_files_cc,$(call listf_cc,$(KSRCDIR)),kernel,$(KCFLAGS))
    #这部分是根据.c文件生成.o文件,不看了
146:打印参数列表
147:链接生成目标文件
148:objdump工具反汇编
149:用objdump工具来解析kernel目标文件得到符号表。

生成bootblock代码:155-170

# create bootblock
bootfiles = $(call listf_cc,boot)
$(foreach f,$(bootfiles),$(call cc_compile,$(f),$(CC),$(CFLAGS) -Os -nostdinc))

bootblock = $(call totarget,bootblock)

$(bootblock): $(call toobj,$(bootfiles)) | $(call totarget,sign)
	@echo + ld $@
	$(V)$(LD) $(LDFLAGS) -N -e start -Ttext 0x7C00 $^ -o $(call toobj,bootblock)
	@$(OBJDUMP) -S $(call objfile,bootblock) > $(call asmfile,bootblock)
	@$(OBJCOPY) -S -O binary $(call objfile,bootblock) $(call outfile,bootblock)
	@$(call totarget,sign) $(call outfile,bootblock) $(bootblock)

$(call create_target,bootblock)

#----------------------------------------------------------------

这段代码类似生成kernel代码

sign.c生成代码:173-174

# create 'sign' tools
$(call add_files_host,tools/sign.c,sign,sign)
$(call create_target_host,sign,sign)
# -------------------------------------------------------------------

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

    22: char buf[512];
    23:memset(buf, 0, sizeof(buf));
    24:FILE *ifp = fopen(argv[1], "rb");
    25:int size = fread(buf, 1, st.st_size, ifp);
    先把buf填充0,然后在读入bootblock
    31:buf[510] = 0x55;
    32:buf[511] = 0xAA;
    最后两位置位0x55AA

答:需要满足:520byte,有效部分在最前面,最后面是0x55AA,中间都是0

总结:

这个makefile好难搞啊,各种依赖好复杂,本来想完全弄明白,现在感觉难度太大了,先就这样吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值