# The filename Kbuild has precedence over Makefile kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile) include $(kbuild-file)
链接vmlinux的过程很简单,就是调用一个shell脚本:
1 2
vmlinux: scripts/link-vmlinux.sh autoksyms_recursive $(vmlinux-deps) FORCE +$(call if_changed,link-vmlinux)
# Link of vmlinux # ${1} - optional extra .o files # ${2} - output file vmlinux_link() { local lds="${objtree}/${KBUILD_LDS}" local objects
if [ "${SRCARCH}" != "um" ]; then objects="--whole-archive \ ${KBUILD_VMLINUX_OBJS} \ --no-whole-archive \ --start-group \ ${KBUILD_VMLINUX_LIBS} \ --end-group \ ${1}"
/* Copy the setup code */ file = fopen(argv[1], "r"); if (!file) die("Unable to open `%s': %m", argv[1]); c = fread(buf, 1, sizeof(buf), file); if (ferror(file)) die("read-error on `setup'"); if (c < 1024) die("The setup must be at least 1024 bytes"); if (get_unaligned_le16(&buf[510]) != 0xAA55) die("Boot block hasn't got boot flag (0xAA55)"); fclose(file);
第二步,将vmlinux.binmmap到kernel:
1 2 3 4 5 6 7 8 9 10 11
/* Open and stat the kernel file */ fd = open(argv[2], O_RDONLY); if (fd < 0) die("Unable to open `%s': %m", argv[2]); if (fstat(fd, &sb)) die("Unable to stat `%s': %m", argv[2]); sz = sb.st_size; printf("System is %d kB\n", (sz+1023)/1024); kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0); if (kernel == MAP_FAILED) die("Unable to mmap '%s': %m", argv[2]);
第三步,将它们写入dest,即bzImage:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
dest = fopen(argv[4], "w"); if (!dest) die("Unable to write `%s': %m", argv[4]);
/* ---省略代码若干--- */
crc = partial_crc32(buf, i, crc); if (fwrite(buf, 1, i, dest) != i) die("Writing setup failed");
$(obj)/vmlinux.bin.gz: $(vmlinux.bin.all-y) FORCE $(call if_changed,gzip) $(obj)/vmlinux.bin.bz2: $(vmlinux.bin.all-y) FORCE $(call if_changed,bzip2) $(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y) FORCE $(call if_changed,lzma) $(obj)/vmlinux.bin.xz: $(vmlinux.bin.all-y) FORCE $(call if_changed,xzkern) $(obj)/vmlinux.bin.lzo: $(vmlinux.bin.all-y) FORCE $(call if_changed,lzo) $(obj)/vmlinux.bin.lz4: $(vmlinux.bin.all-y) FORCE $(call if_changed,lz4)
# Build modules # # A module can be listed more than once in obj-m resulting in # duplicate lines in modules.order files. Those are removed # using awk while concatenating to the final file.
ifdef CONFIG_MODULES modorder-target := $(obj)/modules.order endif # # Rule to create modules.order file # # Create commands to either record .ko file or cat modules.order from # a subdirectory modorder-cmds = \ $(foreach m, $(modorder), \ $(if $(filter %/modules.order, $m), \ cat $m;, echo kernel/$m;))
$(modorder-target): $(subdir-ym) FORCE $(Q)(cat /dev/null; $(modorder-cmds)) > $@
其中modorder定义在scripts/Makefile.lib:
1 2 3 4
# Determine modorder. # Unfortunately, we don't have information about ordering between -y # and -m subdirs. Just put -y's first. modorder := $(patsubst %/,%/modules.order, $(filter %/, $(obj-y)) $(obj-m:.o=.ko))
# When compiling out-of-tree modules, put MODVERDIR in the module # tree rather than in the kernel tree. The kernel tree might # even be read-only. export MODVERDIR := $(if$(KBUILD_EXTMOD),$(firstword$(KBUILD_EXTMOD))/).tmp_versions
# Stage 2 is handled by this file and does the following # 1) Find all modules from the files listed in $(MODVERDIR)/ # 2) modpost is then used to # 3) create one <module>.mod.c file pr. module # 4) create one Module.symvers file with CRC for all exported symbols # 5) compile all <module>.mod.c files # 6) final link of the module to a <module.ko> file
# We can go over command line length here, so be careful. quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules cmd_modpost = $(MODLISTCMD) | sed 's/\.ko$$/.o/' | $(modpost)$(MODPOST_OPT) -s -T -
PHONY += __modpost __modpost: $(modules:.ko=.o) FORCE $(call cmd,modpost)$(wildcard vmlinux)
# Declare generated files as targets for modpost $(modules:.ko=.mod.c): __modpost ;
# Step 6), final link of the modules with optional arch pass after final link quiet_cmd_ld_ko_o = LD [M] $@ cmd_ld_ko_o = \ $(LD) -r $(KBUILD_LDFLAGS) \ $(KBUILD_LDFLAGS_MODULE)$(LDFLAGS_MODULE) \ -o $@ $(real-prereqs) ; \ $(if$(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK)$@, true)
$(modules): %.ko :%.o %.mod.o FORCE +$(call if_changed,ld_ko_o)