Linux系统移植:Kernel 顶层 Makefile(下)

2023-11-19

Linux系统移植:Kernel 顶层 Makefile(下)
继续分析 Linux 内核源码顶层 Makefile 执行过程

一、make defconfig 过程
与 uboot 的顶层 makefile 相同,在编译源码前,要用 make xxx_defconfig 配置 Linux 内核,代码首先配置

config-targets
mixed-targets
dot-config
这三个参数

这段代码执行后,值改变如下:

config-targets= 1
mixed-targets= 0
dot-config= 1
1
2
3
后面的代码就是根据这三个值来选择执行,config-targets=1 执行代码如下:

这段代码主要的就是引用 arch/arm/Makefile 这个文件(zImage、uImage 等文件就是由 arch/arm/Makefile 生成),然后导出 KBUILD_DEFCONFIG、KBUILD_KCONFIG,

然后因为 “%config” 与前面的匹配,因此执行后面的代码,“%config” 依赖于 scripts_basic、outputmakefile 和 FORCE

scripts_basic 代码如下:

build 定义在文件 scripts/Kbuild.include 中,值为 build := -f $(srctree)/scripts/Makefile.build obj

展开就是:

scripts_basic:
    make -f ./scripts/Makefile.build obj=scripts/basic 
    rm -f . tmp_quiet_recordmcount 
1
2
3
所以 %config 下面的命令展开就是:

make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig
1
编译 xxx_defconfig

二、Makefile.build 脚本分析
所以一中最终会执行两个脚本

#scripts_basic 依赖执行的
make -f ./scripts/Makefile.build obj=scripts/basic
#%config 执行的
make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig
1
2
3
4
他们都执行了 Makefile.build 这个脚本,这两个 Makefile.build 执行有不同的效果:

scripts_basic 目标的作用就是编译出 scripts/basic/fixdep 和 scripts/basic/bin2c 这两个软件

而第二行代码会与下面的展开代码进行匹配

%_defconfig: scripts/kconfig/conf
    scripts/kconfig/conf --defconfig=arch/arm/configs/%_defconfig Kconfig
1
2
代码依赖与 scripts/kconfig/conf,会编译 scripts/kconfig/conf.c 生成 conf 软件,此软件就会将 %_defconfig 中的配置输出到.config 文件中,最终生成 Linux kernel 根目录下的.config 文件

三、make 过程
输入 make 后默认编译全部,代码如下:

然后 all 依赖于 vmlinux

vmlinux 依赖 scripts/link-vmlinux.sh $(vmlinux-deps) FORCE,vmlinux-deps 定义如下:

vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN)
1
其中参数在前面都有定义

KBUILD_VMLINUX_INIT= $(head-y) $(init-y)
KBUILD_VMLINUX_MAIN = $(core-y) $(libs-y) $(drivers-y) $(net-y)
KBUILD_LDS= arch/$(SRCARCH)/kernel/vmlinux.lds
1
2
3
其中 SRCARCH=arm,所以 vmlinux 实际的依赖为:

scripts/link-vmlinux.sh、$(head-y) 、$(init-y)、$(core-y) 、$(libs-y) 、$(drivers-y) 、$(net-y)、arch/arm/kernel/vmlinux.lds 和 FORCE
1
head-y
定义在文件 arch/arm/Makefile 中

head-y := arch/arm/kernel/head$(MMUEXT).o
1
不使能 MMU 的话 MMUEXT=-nommu,如果使能 MMU 的话为空,这里使能了

init-y、drivers-y、net-y
这三个参数定义如下:

三个参数带入后如下:

init-y = init/built-in.o
drivers-y = drivers/built-in.o sound/built-in.o firmware/built-in.o
net-y = net/built-in.o
1
2
3
libs-y
相关代码如下:

libs-y := lib/
......
libs-y1 := $(patsubst %/, %/lib.a, $(libs-y))
libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y))
libs-y := $(libs-y1) $(libs-y2)
1
2
3
4
5
在 arch/arm/Makefile 文件下:

libs-y := arch/arm/lib/ $(libs-y)
1
所以 libs-y 最终值如下:

libs-y = arch/arm/lib/lib.a lib/lib.a arch/arm/lib/built-in.o lib/built-in.o
1
core-y
顶层 Makefile 中有如下代码

core-y := usr/
...
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
1
2
3
在 arch/arm/Makefile 中对 core-y 进行追加

代码根据不同的配置向 core-y 追加不同的值,如使能 VFP 的话就会在 .config 中有 CONFIG_VFP=y 这一行,那么 core-y 就会追加 arch/arm/vfp/

然后 makefile 后面的代码还有追加

core-y := $(patsubst %/, %/built-in.o, $(core-y))
1
如果使能 CONFIG_VFP,最终参数就如下:

core-y = usr/built-in.o arch/arm/vfp/built-in.o \
        arch/arm/vdso/built-in.o arch/arm/kernel/built-in.o \
        arch/arm/mm/built-in.o arch/arm/common/built-in.o \
        arch/arm/probes/built-in.o arch/arm/net/built-in.o \
        arch/arm/crypto/built-in.o arch/arm/firmware/built-in.o \
        arch/arm/mach-imx/built-in.o kernel/built-in.o\
        mm/built-in.o fs/built-in.o \
        ipc/built-in.o security/built-in.o \
        crypto/built-in.o block/built-in.o
1
2
3
4
5
6
7
8
9
这些变量都是一些 built-in.o 或.a 等文件,将相应目录中的源码文件进行编译,在各自目录下生成 built-in.o 文件,有些生成了.a 库文件,最终将这些 built-in.o 和.a 文件进行链接即可形成 ELF 格式的可执行文件,也就是 vmlinux,链接文件为 arch/arm/kernel/vmlinux.lds,链接过程是由 shell 脚本 scripts/link-vmlinux.sh 来完成

四、built-in.o 文件编译生成过程
上节知道 built-in.o 和 .a 库文件由 link-vmlinux.sh 文件链接后生成 vmlinux,下面看一下 built-in.o 如何编译生成的

因为 vmliux 依赖 vmlinux-deps,

vmlinux-deps= $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN)
1
KBUILD_LDS 是链接脚本,KBUILD_VMLINUX_INIT 和 KBUILD_VMLINUX_MAIN 是各个子目录下的 built-in.o、.a 文件,最终值如下:

makefile 有个函数对 vmlinux-deps 的字符串列表进行排序,去掉重复的单词,函数依赖于 vmlinux-dirs

(sort $(vmlinux-deps)): $(vmlinux-dirs)
1
vmlinux-dirs 是一个关键参数

vmlinux-dirs    := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
             $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
             $(net-y) $(net-m) $(libs-y) $(libs-m)))
1
2
3
保存参数如下:

同时顶层 Makefile 中有如下代码:

vmlinux-dirs 依赖 prepare 和 scripts,然后执行

make -f ./scripts/Makefile.build obj=$@
1
正是这个函数将 vmlinux-dirs 中的这些目录全部带入到命令中编译生成 .o 文件

五、 make zImage 过程
上文提到的 vmlinux,除此之外还有几个比较重要的文件,简单说明一下他们:

vmlinux:

vmlinux 是编译出来的最原始的内核文件,未经过压缩处理,如正点原子提供的 Linux 源码编译出来的 vmlinux 差不多有 16MB

Image:

Image 是 Linux 内核镜像文件,仅包含可执行的二进制数据,是使用 objcopy 取消掉 vmlinux 中的一些其他信息获得的

zImage:

zImage 是经过 gzip 压缩后的 Image

uImage:

uImage 是老版本 uboot 用的下载镜像文件,uImag 是在 zImage 前面加了一个长度为 64 字节的头部信息,这个头信息描述了该镜像文件的类型、加载位置、生成时间、大小等信息,目前新的 uboot 已经支持了zImage 启动,不在需要 uImage

在 arch/arm/Makefile 中有如下代码

变量 BOOT_TARGETS 输出 zImage,Image,xipImage 等镜像文件,其依赖于 vmlinux,具体编译指令展开后如下:

make -f ./scripts/Makefile.build obj=arch/arm/boot MACHINE=arch/arm/boot/zImage
————————————————
版权声明:本文为CSDN博主「Top嵌入式」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_45396672/article/details/123264161

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux系统移植:Kernel 顶层 Makefile(下) 的相关文章

  • 如何修改s_client的代码?

    我正在玩apps s client c in the openssl源代码 我想进行一些更改并运行它 但是在保存文件并执行操作后 我的更改没有得到反映make all or a make 例如 我改变了sc usage函数为此 BIO pr
  • 访问 Linux 线程(pthreads)的本地堆栈

    我目前正在实现一个使用多线程但对总内存消耗有要求的应用程序 我希望有一个主线程执行 I O 并有几个工作线程执行计算 目前 我在主堆栈上有几个可供工作人员访问的数据结构 我使用 OpenMP 进行工作分配 由于主 工作者模式不能很好地与 O
  • Linux shell 命令逐块读取/打印文件

    是否有一个标准的 Linux 命令可以用来逐块读取文件 例如 我有一个大小为 6kB 的文件 我想读取 打印第一个 1kB 然后是第二个 1kB 看来猫 头 尾在这种情况下不起作用 非常感谢 你可以这样做read n在循环中 while r
  • 操作系统崩溃的常见原因[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有兴趣了解 操作系统崩溃 不限于Windows崩溃 最常见的技术原因 从操作系统编程的角度 有哪些 我正在寻找一个不像 打开太多应用
  • sed 仅最后一个匹配模式

    我想sed仅文本文件的最后一个匹配模式 输入文件 boy boy girl boy 输出文件 boy boy girl boys 一种方法是反转文件 仅替换第一个匹配项 然后再次反转 tac
  • bash双括号问题

    我对 bash 脚本非常陌生 在使用双括号时遇到了问题 我似乎无法让它们在 Ubuntu Server 11 10 中工作 我的下面的脚本位于 if test sh 中 bin bash if 14 14 then echo FOO fi
  • 对 sf:: 的未定义引用

    我想用 C 制作 GUI 应用程序 发现 SFML 是一个不错的选择 幸运的是 我使用的是 Linux 所以 SFML 2 4 已经安装在我的系统上 所以我开始搜索一些教程并找到了一个制作简单窗口的教程 但是当我运行代码时 出现错误 提示未
  • xdotool 类型需要很长时间并导致整个桌面冻结

    我一直在使用xdotool type过去只能在快捷方式上输入耸肩xdotool type 这可行 但总是需要相当长的时间 并导致整个桌面冻结 完全冻结 而不仅仅是输入 几秒钟 不过并没有太打扰我 现在我需要一种方法来从文件中读取内容 对其进
  • 测试linux下磁盘空间不足

    我有一个程序 当写入某个文件的磁盘空间不足时 该程序可能会死掉 我不确定是否是这种情况 我想运行它并查看 但我的测试服务器不会很快耗尽空间 有什么办法可以嘲笑这种行为吗 看起来没有任何方法可以在 Ubuntu 中设置文件夹 文件大小限制 并
  • 如何使用 bash 脚本关闭所有终端,在每个终端中有效地按 Ctrl+Shift+Q

    我经常打开许多终端 其中一些正在运行重要的进程 例如服务器 而另一些则没有运行任何东西并且可以关闭 如果您按 重要 则会弹出确认提示Cntrl Shift Q在其中 如下所示 我想要一个 bash 脚本 它可以关闭所有终端 但将 重要 终端
  • 使用netcat将unix套接字传输到tcp套接字

    我正在尝试使用以下命令将 unix 套接字公开为 tcp 套接字 nc lkv 44444 nc Uv var run docker sock 当我尝试访问时localhost 44444 containers json从浏览器中 它不会加
  • 原生 Linux 应用程序可像 ResHacker 一样编辑 Win32 PE

    我想运行自动修改 dll服务 用户提交特定的 dll 我在服务器上修改它 然后用户可以下载 dll的修改版本 是否有任何本机 Linux 应用程序提供常见的 Win32 PE 修改功能 例如图标 字符串 加速器 对话等 至少提供命令行或脚本
  • 退出 bash 脚本但保持进程运行

    我正在运行服务器 需要使用参数执行以下命令 这些脚本目前工作得很好 但问题是当我运行脚本时我无法返回到控制台 它在控制台中保持运行 如果我强行停止它 那么该过程也会停止 我想继续运行该进程并返回到控制台 bin sh php home st
  • 将 stdout 作为命令行 util 的文件名传递?

    我正在使用一个命令行实用程序 该实用程序需要传递文件名以将输出写入 例如 foo o output txt 它唯一写入的东西stdout是一条消息 表明它运行成功 我希望能够通过管道传输写入的所有内容output txt到另一个命令行实用程
  • 是否有可能通过 mmap 匿名内存“打孔”?

    考虑一个使用大量大致页面大小的内存区域 例如 64 kB 左右 的程序 每个内存区域的寿命都相当短暂 在我的特定情况下 这些是绿色线程的替代堆栈 如何最好地分配这些区域 以便一旦该区域不再使用 它 们的页面可以返回到内核 天真的解决方案显然
  • 通过 SSH 将变量传递给远程脚本

    我正在通过 SSH 从本地服务器在远程服务器上运行脚本 首先使用 SCP 复制该脚本 然后在传递一些参数时调用该脚本 如下所示 scp path to script server example org another path ssh s
  • UDP 广播发送失败:在 Linux 2.6.30 上“网络无法访问”

    我用udp广播写了一个程序 代码段如下 struct sockaddr in broadcast addr socklen t sock len sizeof broadcast addr bzero broadcast addr sock
  • grails 上的同步块在 Windows 上有效,但在 Linux 上无效

    我有一个 grails 应用程序 它依赖于服务中的同步块 当我在 Windows 上运行它时 同步按预期工作 但当我在 ams linux 上运行时 会出现 StaleObjectStateException 该问题在以下示例中重现 cla
  • 使用脚本自动输入 SSH 密码

    我需要创建一个自动向 OpenSSH 输入密码的脚本ssh client 假设我需要通过 SSH 进入myname somehost用密码a1234b 我已经尝试过 bin myssh sh ssh myname somehost a123
  • Gradle 1.3:build.gradle 不构建类

    这里有一个新问题 我有一个 build gradle 文件apply plugin java在其中 并与 java 项目 包关联 当我跑步时gradle build从命令行我得到 compileJava UP TO DATE process

随机推荐

  • python 使用 openpyxl 打开及读取 excel 表格

    python 使用 openpyxl 打开及读取 excel 表格 openpyxl简介 安装openpyxl 打开及读取表格内容 1 打开 Excel 表格并获取表格名称 2 通过 sheet 名称获取表格 3 获取表格的尺寸大小 几行几
  • Spring创建Bean实例的方式

    目录 简介 源码分析 resolveBeforeInstantiation创建Bean实例 doCreateBean创建Bean实例 Supplier创建实例 FactoryMethod创建实例 自动装配构造函数创建实例 无参构造函数创建实
  • nslookup命令详解

    nslookup命令用于查询DNS的记录 查看域名解析是否正常 在网络故障的时候用来诊断网络问题 nslookup的用法相对来说还是蛮简单的 主要是下面的几个用法 1 直接查询 这个可能大家用到最多 查询一个域名的A记录 nslookup
  • 解决Proteus仿真时候提示Could not load simulator DLL错误

    之前在进行Proteus仿真时候 弹出来三个错误 分别是 1 Could not load simulator DLL E Program Files x86 BIN PROSPICE DLL 2 Could not find or run
  • 二阶电路的零状态响应

    二阶电路零状态响应公式推导 下图所示电路在 时电容和电感上储能都为零 即 t 0 时开关闭合 电压源 Us 开始对电路供电 现讨论 时响应的变化规律 电路的 KVL 方程为换路后电路的初始状态为 0 即 这是二阶线性非齐次微分方程 它的解由
  • vue中点击第一次没有触发按钮怎么操作_vue如何触发某个元素的单击事件?

    我来回答一波吧 因为没复习 导致知识点结合不紧密 原生的中 我们的写法是这样的 王蒿大爷 function myFunction document getElementById demo innerHTML Hello World wind
  • 程序员简历应该怎么写?

    说到程序员简历 这两个月 我看过不下10 000份简历 答主不是HR 也不是技术负责人 但是在网站的运营工作中 每天最开心的事情就是研究候选人的简历了 这些人中 有BAT的资深大牛程序员 也有90后程序员小鲜肉 有人到中年的程序员渴望去创业
  • MyBatis参数传入集合之foreach动态sql

    foreach的主要用在构建in条件中 它可以在SQL语句中进行迭代一个集合 foreach元素的属性主要有item index collection open separator close item表示集合中每一个元素进行迭代时的别名
  • 期货反向跟单--交易员的培养问题

    根据我们统计的数据显示 今年做国内期货反向跟单的团队 无论是从赢利金额 稳定性 还是成功概率 都比做国际期货的团队要高 尤其是最近纯碱 焦煤焦炭 PTA 红枣等几个品种的行情 更是频繁拉爆了很多盘手的账户 本文转发自公众号 反跟单交易 转载
  • 【Mysql】Communications link failure,The last packet sent successfully to the server was 0 millisecond

    项目背景是数据库和项目不在同一台服务器下 在启动时 突然遇到以下错误 Exception in thread main com mysql jdbc exceptions jdbc4 CommunicationsException Comm
  • Java图书馆

    io流用的不是很熟练 还有Book类的应用出了点问题 越改越错 从2个错误改到102个QAQ 孩子想哭 问了好多人也没改成 最后勉强成型 而且上个星期内分泌系统出了点小问题 天天往医院跑 开始敲的太晚了 现在要备战期末考 等期末考结束再改改
  • Linux系统编程:多线程交替打印ABC

    引言 分享关于线程的一道测试题 因为网上基本都是Java的解决方法 决定自己写一篇来记录一下线程的学习 问题描述 编写一个至少具有三个线程的程序 称之为线程 A B 和 C 其中线程 A 输出字符 A 线程 B 输出字符 B 线程 C 输出
  • Spring源码深度解析:文章目录

    文章目录 序号 内容 链接地址 1 一 Spring整体架构和源码环境搭建 https blog csdn net wts563540 article details 126686645 2 二 手写模拟Spring https blog
  • Windows server 2016 部署 AD域

    AD域的简单介绍 为什么要使用域 假设你是协会的系统管理员 管理高职部所有的机房 如果你要为每台电脑设置登录帐户 设置权限 比如是否允许登录帐户安装软件 那你要分别坐在所有电脑前一一设置 如果你要做一些改变 你也要分别在这所有电脑上修改 相
  • 【论文解读】NLP重铸篇之Word2vec

    论文标题 Efficient Estimation of Word Representations in Vector Space论文链接 https arxiv org pdf 1301 3781 pdf复现代码地址 https gith
  • mysql出现“ You can't specify target table '表名' for update in FROM clause”解决方法

    You can t specify target table 表名 for update in FROM clause 翻译为 不能先select出同一表中的某些值 再update这个表 在同一语句中 实例 表 result 表studen
  • (java 基础知识) Java打印---javax.print

    package com print import java io import javax print import javax print attribute import javax print attribute standard p
  • 华为OD机试 - 快递运输(Java)

    题目描述 一辆运送快递的货车 运送的快递放在大小不等的长方体快递盒中 为了能够装载更多的快递 同时不能让货车超载 需要计算最多能装多少个快递 注 快递的体积不受限制 快递数最多1000个 货车载重最大50000 输入描述 第一行输入每个快递
  • React Native_综合练习(react-navigation)

    据说 react natvigation是官方推荐使用的 搞不懂为啥官方放弃更新natigator了 所以在上篇文章的基础上使用react natvigation 1 StackNavigator 用来跳转页面和传递参数 2 TabNavi
  • Linux系统移植:Kernel 顶层 Makefile(下)

    Linux系统移植 Kernel 顶层 Makefile 下 继续分析 Linux 内核源码顶层 Makefile 执行过程 一 make defconfig 过程 与 uboot 的顶层 makefile 相同 在编译源码前 要用 mak