栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

linux内核make menuconfig执行过程

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

linux内核make menuconfig执行过程

  近两年一直有着写linux内核相关的想法,比如从Makefile执行 make menuconfig、make,到x86架构的引导启动过程。由于网上有较多相关的文章,便有些羞涩于自己动手写。现在想着无论自己水平如何,用自己的思路去追溯代码并记录代码,应该强于融入别人的思想。
  本次采用5.9版本内核,通过代码分析、strace跟踪等形式按照自己的理解来写,写的不对的地方请跳过。

make menuconfig

  示例在x86_64架构的Centos8.2虚拟机中进行,现在开始进入正题。
  打开Makefile文件:

# SPDX-License-Identifier: GPL-2.0
VERSION = 5
PATCHLEVEL = 9
SUBLEVEL = 0
EXTRAVERSION =
NAME = Kleptomaniac Octopus

  在开始的地方定义了linux版本信息,这些将在后面多次使用。

  …

$(if $(filter __%, $(MAKECMDGOALS)), 
          $(error targets prefixed with '__' are only for internal use))

  MAKECMDGOALS属执行make时传入的参数(暂存到这个变量),比如输入make test,将会匹配到,执行 $(error targets prefixed with ‘__’ are only for internal use)),导致make停止执行

  …

 PHONY := __all
   __all:

  当make时没有传入参数规则,将默认执行__all流程

  …

ifneq ($(sub_make_done),1)

  判断子级make配置是否完成,如果还没有完成执行条件内的语句

  …

unexport LC_ALL
LC_COLLATE=C
LC_NUMERIC=C
export LC_COLLATE LC_NUMERIC

  不让LC_ALL变量传入子级make(使用),传入LC_COLLATE LC_NUMERIC

  …

ifeq ("$(origin V)", "command line")
  KBUILD_VERBOSE = $(V)
endif
ifndef KBUILD_VERBOSE
  KBUILD_VERBOSE = 0
endif

  如果KBUILD_VERBOSE等于0,则上述命令将被隐藏;如果KBUILD_VERBOSE等于1,则显示上述命令;如果KBUILD_VERBOSE等于2,请给出重建每个目标的原因。
  这里默认执行KBUILD_VERBOSE = 0(quiet=quiet_,Q = @,只打印执行结果)

  …

export quiet Q KBUILD_VERBOSE

  quiet Q KBUILD_VERBOSE变量传入子级make(使用)

  …

ifeq ("$(origin O)", "command line")
  KBUILD_OUTPUT := $(O)
endif

ifneq ($(KBUILD_OUTPUT),)
# Make's built-in functions such as $(abspath ...), $(realpath ...) cannot
# expand a shell special character '~'. We use a somewhat tedious way here.
abs_objtree := $(shell mkdir -p $(KBUILD_OUTPUT) && cd $(KBUILD_OUTPUT) && pwd)
$(if $(abs_objtree),, 
     $(error failed to create output directory "$(KBUILD_OUTPUT)"))

  通过(make) O=指定输出目录或者通过KBUILD_OUTPUT变量,O=优先级高级KBUILD_OUTPUT变量,默认值为当前目录

  …

abs_srctree := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))

  abs_srctree得到Makefile绝对路径(由MAKEFILE_LIST变量经过 lastword、dir、realpath执行得到)

  …

ifneq ($(abs_srctree),$(abs_objtree))

MAKEFLAGS += --include-dir=$(abs_srctree)
need-sub-make := 1
endif

  在make menuconfig中abs_srctree与abs_objtree相同,未设置need-sub-make,need-sub-make=0

  …

this-makefile := $(lastword $(MAKEFILE_LIST))

  this-makefile=Makefile

  …

export sub_make_done := 1

  子级make配置完成

  …

ifeq ($(need-sub-make),1)
PHONY += $(MAKECMDGOALS) __sub-make

$(filter-out $(this-makefile), $(MAKECMDGOALS)) __all: __sub-make
        @:

__sub-make:
        $(Q)$(MAKE) -C $(abs_objtree) -f $(abs_srctree)/Makefile $(MAKECMDGOALS)
...

  上述说过need-sub-make=0,这里的分支将不执行(不执行子级Makefile)

  …

ifeq ($(need-sub-make),)

MAKEFLAGS += --no-print-directory

  进入分支,设置输出信息

  …

ifeq ("$(origin C)", "command line")
  KBUILD_CHECKSRC = $(C)
endif
ifndef KBUILD_CHECKSRC
  KBUILD_CHECKSRC = 0
endif

  使用“make C=1”只允许检查重新编译的文件,使用“make C=2”来启用对所有源文件的检查;这里为0,执行KBUILD_CHECKSRC = 0

  …

ifeq ("$(origin M)", "command line")
  KBUILD_EXTMOD := $(M)
endif

$(if $(word 2, $(KBUILD_EXTMOD)), 
        $(error building multiple external modules is not supported))

export KBUILD_CHECKSRC KBUILD_EXTMOD

  设置外部模块(.ko)目录

  …

extmod-prefix = $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/)

  extmod-prefix默认为空

  …

ifeq ($(abs_srctree),$(abs_objtree))
        # building in the source tree
        srctree := .
        building_out_of_srctree :=
else
        ifeq ($(abs_srctree)/,$(dir $(abs_objtree)))
                # building in a subdirectory of the source tree
                srctree := ..
        else
                srctree := $(abs_srctree)
        endif
        building_out_of_srctree := 1
endif

  abs_srctree与abs_objtree目录相同,srctree为当前目录,building_out_of_srctree为空

  …

objtree         := .
VPATH           := $(srctree)

  objtree为当前目录,VPATH为空

  …

export building_out_of_srctree srctree objtree VPATH

  building_out_of_srctree srctree objtree VPATH变量传入子级make(使用)

  …

version_h := include/generated/uapi/linux/version.h
old_version_h := include/linux/version.h

clean-targets := %clean mrproper cleandocs
...

  定义version_h、old_version_h路径,clean-targets清除规则等配置

  …

ifeq ($(KBUILD_EXTMOD),)
        ifneq ($(filter %config,$(MAKECMDGOALS)),)
                config-build := 1
                ifneq ($(words $(MAKECMDGOALS)),1)
                        mixed-build := 1
                endif
        endif
endif

  默认config-build := 1

  …

include scripts/Kbuild.include

# Read KERNELRELEASE from include/config/kernel.release (if it exists)
KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION

include scripts/subarch.include

  包含Kbuild.include,KERNELRELEASE和KERNELVERSION为5.9.0,包含subarch.include

  …

ARCH            ?= $(SUBARCH)

  获取当前系统架构,默认x86

  …

KCONFIG_ConFIG  ?= .config

  设置KCONFIG_ConFIG=.config(配置文件保存名称)

  …

export KCONFIG_ConFIG

export KBUILD_DEFConFIG := defconfig

  KCONFIG_ConFIG KBUILD_DEFCONFIG变量传入子级make(使用),KBUILD_DEFCONFIG用于make defconfig

  …

...
USERINCLUDE    := 
                -I$(srctree)/arch/$(SRCARCH)/include/uapi 
                -I$(objtree)/arch/$(SRCARCH)/include/generated/uapi 
                -I$(srctree)/include/uapi 
                -I$(objtree)/include/generated/uapi 
                -include $(srctree)/include/linux/kconfig.h

  跳过gcc等一些编译相关信息,USERINCLUDE为-I./arch/x86/include/uapi -I./arch/x86/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/kconfig.h

  …

LINUXINCLUDE    := 
                -I$(srctree)/arch/$(SRCARCH)/include 
                -I$(objtree)/arch/$(SRCARCH)/include/generated 
                $(if $(building_out_of_srctree),-I$(srctree)/include) 
                -I$(objtree)/include 
                $(USERINCLUDE)

  LINUXINCLUDE为-I./arch/x86/include -I./arch/x86/include/generated -I./include -I./arch/x86/include/uapi -I./arch/x86/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/kconfig.h

  …

export KBUILD_LDS_MODULE := $(srctree)/scripts/module-common.lds
...
export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL

  导入较多变量供子级make使用

  …

PHONY += outputmakefile

  PHONY为__all scripts_basic outputmakefile

  …

PHONY += scripts_basic
scripts_basic:
        $(Q)$(MAKE) $(build)=scripts/basic
        $(Q)rm -f .tmp_quiet_recordmcount

  执行scripts_basic内分支(__all scripts_basic outputmakefile,这三个为需要执行的分支)

  …

outputmakefile:

  执行outputmakefile内分支,make menuconfig只是经过一下这里

  …

%config: outputmakefile scripts_basic FORCE
        $(Q)$(MAKE) $(build)=scripts/kconfig $@

  执行scripts/kconfig/Makefile文件

  …

$(foreach f, mconf.o $(lxdialog), 
  $(eval HOSTCFLAGS_$f = $$(shell . $(obj)/mconf-cfg && echo $$$$cflags)))

  编译mconf.c,lxdialog/checklist.c lxdialog/inputbox.c lxdialog/menubox.c lxdialog/textbox.c lxdialog/util.c lxdialog/yesno.c,生成mconf工具(menuconfig用到的视图工具,参考mconf源码)

  …

$(obj)/%conf-cfg: $(src)/%conf-cfg.sh FORCE
        $(call filechk,conf_cfg)

  在scripts/kconfig/文件夹内更新mconf-cfg脚本

  …

menuconfig: $(obj)/mconf
        $< $(silent) $(Kconfig)

  到这里,menuconfig编译过程分析完成了,在根Makefile设置变量及运行条件,然后跳转到scripts/kconfig/生成mconf,通过scripts/kconfig/mconf Kconfig启动视图界面。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/733444.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号