challenge1.1-ucore.img
ucore.img从何而来?
make
首先在lab1
目录中使用以下指令:
make "V=" | tee -a make.info
|
这样就成功把make "V="
的输出信息写入到make.info
文件中,方便查看原始命令执行;
Makefile
看一下toobj
、totarget
、liftf
等具体定义,在tools/function.mk
中:
toobj
toobj = $(addprefix $(OBJDIR)$(SLASH)$(if $(2),$(2)$(SLASH)),\ $(addsuffix .o,$(basename $(1))))
|
todep
、totarget
todep = $(patsubst %.o,%.d,$(call toobj,$(1),$(2)))
totarget = $(addprefix $(BINDIR)$(SLASH),$(1))
|
liftf
:
listf = $(filter $(if $(2),$(addprefix %.,$(2)),%),\ $(wildcard $(addsuffix $(SLASH)*,$(1))))
|
cc_compile
:
cc_compile = $(eval $(call do_cc_compile,$(1),$(2),$(3),$(4)))
define do_cc_compile $$(foreach f,$(1),$$(eval $$(call cc_template,$$(f),$(2),$(3),$(4)))) endef
define cc_template $$(call todep,$(1),$(4)): $(1) | $$$$(dir $$$$@) @$(2) -I$$(dir $(1)) $(3) -MM $$< -MT "$$(patsubst %.d,%.o,$$@) $$@"> $$@ $$(call toobj,$(1),$(4)): $(1) | $$$$(dir $$$$@) @echo + cc $$< $(V)$(2) -I$$(dir $(1)) $(3) -c $$< -o $$@ ALLOBJS += $$(call toobj,$(1),$(4)) endef
|
not the time to create ucore.img
在Makefile
文件中,存在:
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)
|
可以看到,ucore.img
作为target
,需要依赖kernel
和bootlock
;
create kernel
在Makefile
文件中,存在:
KINCLUDE += kern/debug/ \ kern/driver/ \ kern/trap/ \ kern/mm/
KSRCDIR += kern/init \ kern/libs \ kern/debug \ kern/driver \ kern/trap \ kern/mm
KCFLAGS += $(addprefix -I,$(KINCLUDE))
$(call add_files_cc,$(call listf_cc,$(KSRCDIR)),kernel,$(KCFLAGS))
KOBJS = $(call read_packet,kernel libs)
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)
|
可以看到,生成kernel
依赖于kern文件夹
下的许多目标文件和kernel.ld
工具;
- 这些文件通过一下指令来生成:
$(call add_files_cc,$(call listf_cc,$(KSRCDIR)),kernel,$(KCFLAGS))
KOBJS = $(call read_packet,kernel libs)
$(V)$(LD) $(LDFLAGS) -T tools/kernel.ld -o $@ $(KOBJS)
|
kernel.ld
而实际上的命令为:
+ ld bin/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 dd if=bin/kernel of=bin/ucore.img seek=1 conv=notrunc
|
create bootlock
在Makefile
文件中,存在:
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)
|
可以看到这一句:
$(bootblock): $(call toobj,$(bootfiles)) | $(call totarget,sign)
|
由蓝色背景部分可以得知,该步将依赖:
- boot文件夹中的编译而成目标文件,即bootasm.o和bootmain.o;
bootfiles = $(call listf_cc,boot)
$(foreach f,$(bootfiles),$(call cc_compile,$(f),$(CC),$(CFLAGS) -Os -nostdinc))
|
实际的命令为:
// cat make.info | grep "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
// cat make.info | grep "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
|
- target sign;
$(call add_files_host,tools/sign.c,sign,sign) $(call create_target_host,sign,sign)
|
实际的命令为:
// cat make.info | grep "sign" 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
|
依赖文件都生成后,将生成bootblock.o
;
// cat make.info | grep "bootblock.o"
+ 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!
|
可以看到生成了依赖的二进制文件bootblock
create ucore.img now
对依赖文件进行写入,生成镜像文件;
// make V=
dd if=**/dev/zero** of=bin/ucore.img count=10000 10000+0 records in 10000+0 records out 5120000 bytes (5.1 MB, 4.9 MiB) copied, 0.0340812 s, 150 MB/s
dd if=**bin/bootblock** of=bin/ucore.img conv=notrunc 1+0 records in 1+0 records out 512 bytes copied, 0.000153858 s, 3.3 MB/s
dd if=**bin/kernel** of=bin/ucore.img seek=1 conv=notrunc 146+1 records in 146+1 records out 74828 bytes (75 kB, 73 KiB) copied, 0.00263467 s, 28.4 MB/s
|
可以看到生成了一个有10000个块的文件,每个块默认512bytes,使用0填充,共5120000bytes;
将bootblock写入第一个块,小于等于512bytes 才符合要求;
从第二个块开始,写入kernel,共74828bytes;