读核感悟-kbuild系统-make bzImage的过程

关于解决Linux内核配置过程make bzImage中出现的问题 --个人笔记 查询之后得知,出现的原因是在之前下载未完成时久将窗口关闭,然而apt-get进程没没有结束导致,或者是搜索一个不存在的安装包,apt进程返回结果后你很快地再次使用apt命令,就造成进程阻塞现象。显示“无法获得锁”,“无法获得dpkg前端锁”,搜索资料,https://blog.youkuaiyun.com/weixin_37769711/article/details/88759474。考虑到之前的进程锁,怀疑这次也是相同的问题,于是按照上边清除了两次,然后重新install,还是会有“无法定位软件位置” 阅读详情

文章来源:http://www.top-e.org/jiaoshi/class/

 

从以上例子中可以看到,内核的编译系统kbuild是个很庞大的系统。但是,它所使用的make和我们平时用的make是一模一样的。kbuild只是通过预定义一些变量(obj-m,obj-y等等)和目标(bzImage ,menuconfig等等),使内核的编译和扩展变得十分方便。我们不妨yy一下kbuild的一些功能:

1.考虑到Linux能够方便地移植到各个硬件平台,kbuild也必须很容易添加对某个新的平台的支持,同时上层的Makefile不需要做大的改动。

2.Linux下有众多驱动设备。它们的Makefile希望能够尽可能简洁。简洁到只要指定要编译的.o文件就行。(这方面kbuild定义了很多有用的变量如obj-m obj-y,<module>-objs等等,用户只要为这些变量赋值,kbuild会自动把代码编译到内核或者编译成模块)

3.要有方便的可定制性。很多参数可以让用户指定。这方面kbuild也提供了大量的变量如EXTRA_CFLAGS,用户如果想include自己的头文件或者加其它编译参数,只要设置一下EXTRA_CFLAGS就可以。

4.有能力递归地调用Makefile。因为内核是一个庞大的软件。它的源代码的目录层次很深。要提供一种简洁的机制,使上层的Makefile能方便地调用下层的Makefile。在这过程中,面向对象的思想也许值得借鉴。

5.在配置内核时,要提供友好的用户界面。这方面kbuild也提供了不少工具,如常用的make menuconfig等等。

我们完全可以把kbuild想象成一个类库,它为普通的内核开发人员提供了接口(obj-m obj-y EXTRA_CFLAGS等等),为用户提供了定制工具(make menuconfig)

如果想了解kbuild的使用方法,可以参阅源代码自带的文档:

Documentation/kbuild/makefiles.txt

Documentation/kbuild/modules.txt

一般情况下是不需要知道具体的编译顺序的。除了在个别情况下,如do_initcalls()中就和函数在.initcall.init section中的顺序有关。不过喜欢寻根究底的我,还是想理一下编译内核时几个常用的命令,如make bzImage,make menuconfig等等,进而了解kbuild的架构。先看make bzImage吧。

它的大概脉络是怎样的呢?可以用以下命令查看。

make -n bzImage 

如果嫌内容太多,可以过滤掉多余的信息:

make -n bzImage | grep “make -f”

可以猜到:

先作一些准备工作

make -f scripts/Makefile.build obj=scripts/basic

然后依次递归地调用源代码中的Makefile

make -f scripts/Makefile.build obj=init

make -f scripts/Makefile.build obj=usr

make -f scripts/Makefile.build obj=arch/i386/kernel

make -f scripts/Makefile.build obj=arch/i386/kernel/acpi

make -f scripts/Makefile.build obj=arch/i386/kernel/cpu

make -f scripts/Makefile.build obj=arch/i386/kernel/cpu/cpufreq

make -f scripts/Makefile.build obj=arch/i386/kernel/cpu/mcheck

make -f scripts/Makefile.build obj=arch/i386/kernel/cpu/mtrr

make -f scripts/Makefile.build obj=arch/i386/kernel/timers

。。。

最后压缩内核,生成bzImage

make -f scripts/Makefile.build obj=arch/i386/boot arch/i386/boot/bzImage

make -f scripts/Makefile.build obj=arch/i386/boot/compressed IMAGE_OFFSET=0x100000 arch/i386/boot/compressed/vmlinux

好,我们从头开始。找make bzImage的入口:

第一反应,自然是在/usr/src/linux/Makefile中找

bzImage:

...

可惜没找到。

不过没关系,用lxr搜索一下,可知bzImage定义在arch/i386/Makefile,所以可以猜测,该makefile一定是被include了。果然,在/usr/src/linux/Makefile中有:

447 include $(srctree)/arch/$(ARCH)/Makefile

又因为在arch/i386/Makefile中定义有

141 zImage bzImage: vmlinux

142         $(Q)$(MAKE) $(build)=$(boot) $(KBUILD_IMAGE)

其中这个$(build)定义在/usr/src/linux/Makefile中

1335 build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj

我们在之前查看make -n bzImage信息和之后会经常看到。我们会发现kbuild通常不会直接去调用某个目录下的Makefile,而是让该目录作为scripts/Makefile.build 的参数。scripts/Makefile.build 会对该目录下的Makefile中的内容(主要是obj-m和obj-y等等)进行处理。由此看来 scripts/Makefile.build这个文件很重要。看看它做了什么:

由于scripts/Makefile.build后面没跟目标,所以默认为第一个目标:

007 .PHONY: __build

008 __build:

009 

010 # Read .config if it exist, otherwise ignore

011 -include .config

012 

013 include $(if $(wildcard $(obj)/Kbuild), $(obj)/Kbuild, $(obj)/Makefile)

014 

015 include scripts/Makefile.lib

这里可以看到,scripts/Makefile.build执行时会include .config文件。.config是make menuconfig后生成的内核配置文件。

里面有如下语句:

CONFIG_ACPI_THERMAL=y

CONFIG_ACPI_ASUS=m

CONFIG_ACPI_IBM=m

。。。

以前我一直对它的格式表示奇怪,现在很清楚了,它们是作为makefile的一部分,通过读取CONFIG_XXX的值就可以知道他们是作为模块还是作为内核的一部分而编译的。

此外,还包含了$(obj)/Makefile。这就是通过在make时传递目录名$(obj)间接调用Makefile的手法。对于内核普通代码所对应的Makefile而言,里面只是对obj-m obj-y,<module>-objs等变量进行赋值操作。

接下去是include scripts/Makefile.lib

。正如它的文件名所示,这类似于一个库文件。它负责对obj-m obj-y,<module>-objs等变量进行加工处理。从中提取出subdir-ym等变量,这是个很重要的变量,记录了需要递归调用的子目录。以后递归调用Makefile全靠它了。这里也充分体现了GNU make对字符串进行操作的强大功能。

回到Makefile.build。这时,重要变量$(builtin-target),$(subdir-ym)等都已经计算完毕。开始列依赖关系和具体操作了。

079 __build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) /

080          $(if $(KBUILD_MODULES),$(obj-m)) /

081          $(subdir-ym) $(always)

082         @:

$(builtin-target)是指当前目录下的目标文件,即$(obj)/built-in.o

如前文所说,$(subdir-ym)用来递归调用子目录的Makefile

306 # Descending

307 # ---------------------------------------------------------------------------

308 

309 .PHONY: $(subdir-ym)

310 $(subdir-ym):

311         $(Q)$(MAKE) $(build)=$@

通过这种方式,实现了对某个目录及其子目录的编译。

分析完Makefile.build,回过头来再看bzImage.从arch/i386/Makefile中可以看到,bzImage是在vmlinux基础上加以压缩拼接而成。从vmlinux到bzImage的过程在《读核感悟-Linux内核启动-内核的生成》中已经有介绍。现在看看vmlinux是如何生成的。

见/usr/src/linux/Makefile

728 vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE

729         $(call if_changed_rule,vmlinux__)

611 vmlinux-init := $(head-y) $(init-y)

612 vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)

613 vmlinux-all  := $(vmlinux-init) $(vmlinux-main)

614 vmlinux-lds  := arch/$(ARCH)/kernel/vmlinux.lds

vmlinux所依赖的目标$(vmlinux-lds) 是对arch/i386/kernel/vmlinux.lds.S进行预处理的结果:arch/i386/kernel/vmlinux.lds ,其它的依赖关系也都可以在/usr/src/linux/Makefile中查到。

所以,当用户在源代码目录下执行make bzImage。make会检查bzImage的依赖目标,然后不停地递归调用各个Makefile,最终生成一个bzImage文件。

如果我们换个角度,还可以归纳出不少有趣的东西。如果把make看成是一种脚本语言,那么Makefile就是代码。make就是解释器。make里也有函数,也有变量。通过定义目标,可以实现类似于函数的效果。而目标之间的依赖关系则类似于函数内部再调用其它函数。

如果我们考虑变量的作用域,还可以归纳出以下几点:

1.Makefile内部定义的变量作用域只限于那个Makefile中,如obj-m。

2.要使变量的作用域扩展到整个make命令的执行过程(包括递归调用的其它Makefile),需要使用export命令。

调用Makefile的方式也有很多种:

1.一种是隐式调用,如运行make,它会自动在当前目录寻找Makefile等。

2.一种是显式调用,如用make -f指定。

3.一种是用include 来调用。

更多来源:http://www.top-e.org/jiaoshi/class/

Linux kernel 分析之十四:kbuild系统-make bzImage的过程 从以上例子中可以看到,内核的编译系统kbuild是个很庞大的系统。但是,它所使用的make和我们平时用的make是一模一样的。kbuild只是通过预定义一些变量(obj-m,obj-y等等)和目标(bzImage ,menuconfig等等),使内核的编译和扩展变得十分方便。我们不妨yy一下kbuild的一些功能: 1.考虑到Linux能够方便地移植到各个硬件平台,kbuild也必须很容易添加对 阅读详情

相关推荐

信道估计之MMSE算法

信道估计之MMSE算法前言MMSE估计的原理总结 前言        前篇分析了LS信道估计算法,也说明了由于没有考虑SNR的影响,所以LS算法不适合在低信噪比的情况下使用。本篇来学习信道估计的另外一种常用的算法–MMSE。        为什么说LS没有考虑噪声大小的情况呢,因为LS算法使用的是实际观测量与估计观测量的误差,这并不能精确的代表估计量的真值与估计值的误

大白的博客 2万+

Linux学习记录--内核|内核模块编译

内核|内核模块编译 (对于内核的知识觉得了解不够,等学习完LFS再来详细整理下这方面的知识)   内核:系统上面的一个文件,这个文件包含了驱动主机各项硬件的检测程序和驱动模块。   计算机真正工作的是硬件,内核是用来控制这些硬件工作的(主要通过硬件驱动),如果我们需要硬件来完成某项工作时需要内核的帮助才能完成   内核模块:编译成模块的驱动程序。既然内核中已经包括了驱动程序,那么为什

StarFlex 1731

从原理到实践:详解RGBD相机深度与彩色图像对齐(D2C)算法

本文深入解析了RGBD相机深度与彩色图像对齐(D2C)算法的原理与实现。针对自组装相机中深度图与彩色图不匹配的核心痛点,文章从相机模型、坐标系变换等数学基础讲起,剖析了传统点映射算法的缺陷,并重点介绍了高效的矩形区域映射算法。该算法通过将深度像素视为矩形区域进行映射,有效解决了空洞和遮挡问题,并附有可直接复用的C++代码与优化技巧,为三维重建、机器人视觉等应用奠定坚实基础。

weixin_28363123的博客 241

海思hi3520dv400 kernel分析(0)——Kbuild原理分析

(一)前言 kbuild,即 kernel build,用于编译 Linux 内核文件。 kbuild 对 makefile 进行了功能上的扩充,使其在编译内核文件时更加高效,简洁。大部分内核中的 Makefile 都是使用 Kbuild 组织结构的 kbuild Makefile。 Kbuild 执行的几个步骤(大致): 根据内核配置生成文件 .config 将内核的版本号存储在 .........

Biao 2703

vscode运行.ipynb代码时提示需要安装ipykernel包的解决办法

此文目的是为了记录遇到的一些问题,也希望能帮助到和我一样遇到困难的同学。如需转载,请注明出处。在使用vscode运行.ipynb文件中提示需要安装ipykernel包的提示,在网上查询了很多方法之后也是终于解决了问题。写下这篇博客也希望能帮到大家。

qq_58018041的博客 4万+

从模态到颤振:深入解读Nastran的V-g/V-f图,判断你的机翼设计是否安全

本文深入解析Nastran中的V-g/V-f图在机翼颤振分析中的应用,帮助工程师准确判断设计安全性。通过模态分析到颤振边界的完整判读逻辑,结合气动弹性特性,指导优化机翼结构设计,确保飞行安全。

weixin_28732953的博客 470

linux kernel Kbuild 编译系统分析

从Linux内核2.6开始,Linux内核的编译采用Kbuild系统,这同过去的编译系统有很大的不同,尤其对于Linux内核模块的编译。在新的系统下,Linux编译系统会两次扫描Linux的Makefile:首先编译系统会读取Linux内核顶层的Makefile,然后根据读到的内容第二次读取Kbuild的Makefile来编译Linux内核。 Linux内核Makefile分类 ...

zgp2917的专栏 601

YOLOv11改进 - 卷积Conv | GCNet之金箍棒块GCBlock : 重参数化捕获全局依赖 | CVPR 2025

文介绍了GCBlock在YOLOv11中的结合应用。GCBlock是GCNet的核心组件,能高效捕获特征图中的全局依赖关系,融合了非局部网络和挤压 - 激励网络的优势,降低计算成本并保障模型性能。其遵循“上下文建模 - 特征变换 - 特征融合”框架,通过全局平均池化、全连接层等操作生成注意力权重。我们将GCBlock集成进YOLOv11,替代原有的部分卷积模块,实现更高效的全局上下文建模。实验证明,YOLOv11-GCBlock在目标检测任务中表现出色,展现了GCBlock在深度学习中的广泛应用前景。

魔改工程师的博客 905

读Kernel感悟-kbuild系统-make bzImage的过程

读Kernel感悟-kbuild系统-make bzImage的过程顶嵌(TOP-E)|嵌入式linux企业培训|嵌入式Linux就业实训|承接嵌入式项目开发   2009-04-02 09:44:27 作者:handsomeluo 来源:顶嵌开源 文字大小:[大][中][小]从以上例子中可以看到,内核的编译系统kbuild是个很庞大的系统。但是,它所使用的make

owenbbkp的专栏 554

YOLO26优化:特征融合 | 一种新颖的多尺度特征融合iAFF,适配小目标检测

在YOLO26中如何使用:iAFF加入Neck替代Concat;

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 269

高通MBIM拨号流程简述

高通平台MBIM流程简述

不秃头的程序猿Gabriel的博客 5070

读kernel感悟-kbuild系统-make bzImage的过程

<br /> <br />内核的编译系统kbuild是个很庞大的系统 ,但是,它所使用的make和我们平时用的make是一模一样的。kbuild只是通过预定义一些变量(obj-m,obj-y等等)和目标(bzImage ,menuconfig等等),使内核的编译和扩展变得十分方便。我们不妨yy一下kbuild的一些功能:<br />1.考虑到Linux能够方便地移植到各个硬件平台,kbuild也必须很容易添加对某个新的平台的支持,同时上层的Makefile不需要做大的改动。<br />2.Linux下有众多

y296144646q的专栏 860

汽车标定技术(五)--基于模型开发如何生成完整的A2L文件(1)

A2L文件的生成分为两章讲解:本文主要是讲模型开发,讲解如何把标定量、观测量放到链接文件中的指定位置。下一篇讲解如何使用matlab生成完整的A2L文件

认真搞搞汽车MCU 4615

[Android开发2]内核学习1-bio & 这两天的感悟 && 内核编译 && slab分配器blk层的切入点

接触一个全新的领域kernel编程 经过两天的摸索与前辈的指导,终于理清了一点 1 Kbuild(以后补)和 2 我即将要做的部分-blktrace相关 这两个部分的头绪。 今天开始,准备 1先学一些基础(block层IO流程-关注submit_bio()) 2 着手看我要做的那部分代码所做的修改部分。【这里基于 Android内核版本3.0.31(samsung)和3.4(goldfish)

292

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

linux kernel kbuild详解 之一

内核编译过程中会生成以下类型的文件 参见Documentation/kbuild/kbuild.txt modules.order:这个文件记录了Makefile中模块出现的顺序。modprobe通过它来确定解决多个模块匹配的别名(指定模块的绝对路径)。                                如:kernel//home/cjz/Desktop/test/d

崔建忠的专栏 1万+

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

bzImage是怎么来的

以x86架构32位机为例,即i386   从经典的helloworld程序开始 理解程序的编辑、编译、连接、运行的四个阶段 内核也是使用gcc、ld等工具编译连接出来的,并没有什么神秘之处 只不过文件繁多,代码树庞大而已,超出了大多数人的理解范围 就好像一般人对支配几千或几万块钱还是没有问题的 但是若突然让其支配上亿元时,一般人都是没有概念的   使用的工具make、gcc、ld

kernel_digger的专栏 3031

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

内核编译步骤

内核编译 .config编译内核配置项(make menuconfig中选中的项) Kconfig(make menuconfig选项提供者) Makefile编译规则 内核编译步骤 1、将/boot/config-2.3.18-53.e15xen 拷贝到linux2.6.29内核目录下     cp /boot/config-2.3.18-53.e15xen /home/linux-

karen_mo的专栏 811

make bzImage遇到的问题

“错误 : elf_i386: 没有那个文件或目录” 改arch/i386/kernel下面的Makefile文件,把-m elf_i386改成-m32即可  scripts/mod/sumversion.c: 在函数 'get_src_version'中 scripts/mod/sumversion.c:384:16: 错误:‘PATH_MAX’未声明(在此函数内第一次使用)

尺树寸泓 3172

uImage、zImage、bzImage、vlinzx区别

在网络中,不少服务器采用的是Linux系统。为了进一步提高服务器的性能,可能需要根 据特定的硬件及需求重新编译Linux内核。编译Linux 内核,需要根据规定的步骤进行,编译内核过程中涉及到几个重要的文件。比如对于RedHat Linux,在/boot目录下有一些与Linux内核有关的文件 .   编译过RedHat Linux内核的人对其中的System.map、vmlinuz、in...

yuanjinxiu 478

zImage和bzImage

vmlinuz是可引导的、压缩的内核。"vm"代表"Virtual Memory"。Linux 支持虚拟内存, 不像老的操作系统比如DOS有640KB内存的限制。Linux能够使用硬盘空间作为虚拟内存, 因此得名"vm"。vmlinuz是可执行的Linux内核,它位于/boot/vmlinuz,它一般是一个软 链接。 vmlinuz的建立有两种方式。一是编译内核时通过"make zImage"创建

HEN_MAN的专栏 2326

Linux Kbuild工作原理分析(以DVSDK生成PowerVR显卡内核模块为例)

Linux内核是一种单体内核,但是通过动态加载模块的方式,使它的开发非常灵活方便。那么,它是如何编译内核的呢?我们可以通过分析它的Makefile入手。以下是一个简单的hello内核模块的Makefile. ifneq ($(KERNELRELEASE),) obj-m:=hello.o else KERNELDIR:=/lib/modules/$(shell uname

GQB的专栏 5960

linux内核源码目录结构

linux内核源码目录结构如下所示: (1)Kbuild Kbuild是Kernel build的意思,就是内核编译的意思,这个文件就是linux内核特有的内核编译体系需要用到的文件。 (2)Makefile 这个是linux内核的总Makefile,整个内核工程是用这个Makefile来管理的。 (3)mk 这个文件是九鼎在移植时自己添加的,不是linux内核本身的东西。九鼎添加...

linuxweiyh的博客 7128

kbuild系统-内核模块的编译

  Linux内核是一种单体内核,但是通过动态加载模块的方式,使它的开发非常灵活方便。那么,它是如何编译内核的呢?我们可以通过分析它的Makefile入手。以下是一个简单的hello内核模块的Makefile.     ifneq ($(KERNELRELEASE),)  obj-m:=hello.o  else  KERNELDIR:=/lib/modules/$(shell

ruixj的专栏 1248
上一篇: 读Kernel感悟-kbuild系统-内核模块的编译
下一篇: Android核心模块及相关技术
TopEmbedded
博客等级 码龄18年 58粉丝 61原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值