一. 目标 all 或者 空

当在内核源码顶层目录下执行make的时候,编译的默认目标就是all。代码中的注释有对应的解释。

# The all: target is the default when no target is given on the
# command line.
# This allow a user to issue only 'make' to build a kernel including modules
# Defaults to vmlinux, but the arch makefile usually adds further targets
all: vmlinux

二. 目标 vmlinux

linux内核经过编译后会生成一个elf格式的可执行程序,叫vmlinux或vmlinuz,这个就是原始的未经任何处理加工的原版内核elf文件(后面博文会对它进行详细的讲解)。

三. 目标 modules

modules就是编译内核模块的。所以整个内核,可以简单的理解为 vmlinux + modules组成。

四. 目标 Image/zImage/uImage

1.Image和zImage的区别

内核编译(make)之后会生成两个文件,一个Image,一个zImage,其中Image为内核映像文件,而zImage为内核的一种映像压缩文件

2.uImage

uImage又是什么呢?
它是uboot专用的映像文件,它是在zImage之前加上一个长度为64字节的“头”,说明这个内核的版本、加载位置、生成时间、大小等信息;其偏移0x40之后与zImage没区别。

64字节的头结构如下:

typedef struct image_header {
uint32_tih_magic;
uint32_tih_hcrc;
uint32_tih_time;
uint32_tih_size;
uint32_tih_load;
uint32_tih_ep;
uint32_tih_dcrc; uint8_tih_os;
uint8_tih_arch;
uint8_tih_type;
uint8_tih_comp;
uint8_tih_name[IH_NMLEN];
} image_header_t;

所以,uImage和zImage都是压缩后的内核映像。而uImage是用mkimage工具根据zImage制作而来的。

u-boot里面的mkimage工具来生成uImage(u-boot源码包/tools/mkimage.c )
这里解释一下参数的意义:

-A ==> set architecture to 'arch'
-O ==> set operating system to 'os'
-T ==> set image type to 'type' “kernel或是ramdisk”
-C ==> set compression type 'comp'
-a ==> set load address to 'addr' (hex)
-e ==> set entry point to 'ep' (hex)(内核启动时在此位置查询完整的内核印象)
-n ==> set image name to 'name'
-d==> use image data from 'datafile'
-x ==> set XIP (execute in place,即不进行文件的拷贝,在当前位置执行)

对于ARM linux内核映象用法:

-A arm -------- 架构是arm,可取值参照uboot/common/image.c
-O linux -------- 操作系统是linux,可取值参照uboot/common/image.c
-T kernel -------- 类型是kernel,可取值参照uboot/common/image.c
-C none/bzip/gzip -------- 压缩类型,压缩方式参考uboot/common/image.c
-a 50008000 ---- image的载入地址(hex),通常为0x?00008000
-e 800080xx---- 内核的入口地址(hex),xx为0x40或者0x00
-n linux-xxx --- image的名字,随意
-d namexxx ---- 无头信息的image文件名,制作image的源文件
uImagexxx ---- 加了头信息之后的image文件名,随意

因为zImage是经过压缩而得到的,所以其自身就有解压缩代码。需要特别说明的是:
-a参数是内核的加载地址,-e参数是入口地址,两者可以一样,也可以不一样,依情况而定:

  • 如果我们没用mkimage对内核进行处理的话,那直接把内核下载到0x50008000(不同开发板不同)再运行就行,内核会自解压运行(不过内核运行需要一个tag来传递参数,而这个tag建议是由BootLoader提供的,在U-Boot下默认是由bootm命令建立的)。
  • 如果使用mkimage生成内核镜像文件的话,会在内核的前头加上了64byte的信息,供建立tag之用。bootm命令会首先判断bootm xxxx 这个指定的地址xxxx是否与-a指定的加载地址相同。
    [1]如果不同的话会从这个地址开始提取出这个64byte的头部,对其进行分析,然后把去掉头部的内核复制到-a指定的load地址中去运行之(此时-e 和-a应保持一致)。
    [2] 如果相同的话那就让其原封不同的放在那,但-e指定的入口地址会推后64byte,以跳过这64byte的头部(此时-e 和-a应不同)。

需要注意的是,因为uboot要重新搬运内核映像,所以要注意bootm xxxx的地址和-a之间的地址不要导致复制时的覆盖。

mkimage命令举例如下

./mkimage -n 'linux-2.6.38' -A arm -O linux -T kernel -C none -a 0x50008000 -e 0x50008000 -d zImage uImage

./mkimage -n 'linux-2.6.30' -A arm -O linux -T kernel -C none -a 0x50008000 -e 0x50008040 -d zImage uImage

五. 目标 M=drivers/xxx

这个可以看作是modules目标中的子集。比如:

make M=drivers/char


这条命令只会去编译mini6410_hello_module这个驱动,而不需要去运行对其他驱动代码的检测。对开发或者后期维护,都节省了相应的编译时间。

六. 目标 xxx.o

这是单独编译某个文件的,当你修改某个文件做开发的时候,你可以先单独编译你修改的文件确保没有语法错误,然后再编译内核或者是模块。

比如在/drivers/char目录中,更改了mem.o文件,那么你可以先运行

make M=drivers/char/mem.o

来确保单个文件的语法没有错误,然后再去编译整个模块。

七. 目标 xxx.s

这个作用是生成了指定文件的汇编代码。
make M=drivers/char/mem.s

这种编译会出生成c文件对应的汇编语言的文件。对于某些棘手问题,会很有用。但是通常内核出问题后,我还是习惯对vmlinux进行反汇编。

八. 目标 help

最后的最后,kbuild中提供了一个help的目标。当你不确定如何使用或者想知道还有哪些目标可以用那就执行
make help

你就可以知道都还有哪些用法了。

linux内核编译中常用的目标(二)的更多相关文章

  1. Linux内核编译中的各类错误示例

    1. do_gettimeofday()函数的使用 linux发行版:Ubuntu22.04 linux内核:5.15.0-52-generic 预编译内核:linux-6.0.1 添加在linux- ...

  2. 《Linux内核设计与实现》 第一二章学习笔记

    <Linux内核设计与实现> 第一二章学习笔记 第一章 Linux内核简介 1.1 Unix的历史 Unix的特点 Unix很简洁,所提供的系统调用都有很明确的设计目的. Unix中一切皆 ...

  3. Linux内核编译与安装

    2013-04-16    Linux内核介绍  Linux内核是一个用C语言写成的,符合POSIX标准的类Unix操作系统.内核是操作系统中最基本的一部分,提供了众多应用程序访问计算机硬件的机制.L ...

  4. 《Linux内核设计与实现》第一二章读书笔记

    第一章 Linux内核简介 1.Unix简介 (一)概念:支持抢占式多任务.多进程.虚拟内存.换页.动态链接和TCP/IP网络的现代化操作系统. (二)Unix特点(层次化结构): Unix很简洁,仅 ...

  5. 运行在TQ2440开发板上以及X86平台上的linux内核编译

    一.运行在TQ2440开发板上的linux内核编译 1.获取源码并解压 直接使用天嵌移植好的“linux-2.6.30.4_20100531.tar.bz2”源码包. 解压(天嵌默认解压到/opt/E ...

  6. Lab1:Linux内核编译及添加系统调用(详细版)

    实验一:Linux内核编译及添加系统调用(HDU) 花了一上午的时间来写这个,良心制作,发现自己刚学的时候没有找到很详细的,就是泛泛的说了下细节地方也没有,于是自己写了这个,有点长,如果你认真的看完了 ...

  7. Linux内核编译完整过程

    Linux内核编译完整过程 通过网上的资料我自己的实际内核编译,我把对Linux内核编译的过程写在这里,也许对其他的Linux爱好者的编译学习有些帮助,其中很大部分是网上的资料,另外就是我在实际编译过 ...

  8. Linux内核--网络栈实现分析(二)--数据包的传递过程--转

    转载地址http://blog.csdn.net/yming0221/article/details/7492423 作者:闫明 本文分析基于Linux Kernel 1.2.13 注:标题中的”(上 ...

  9. linux内核编译环境配置

    linux内核编译环境配置 如果不是编译内核,只需要安装与内核相匹配的kernel-devel开发包即可.即是/lib/modules/`uname -r`/build -> /usr/src/ ...

  10. 嵌入式C语言自我修养 02:Linux 内核驱动中的指定初始化

    2.1 什么是指定初始化 在标准 C 中,当我们定义并初始化一个数组时,常用方法如下: ] = {,,,,,,,,}; 按照这种固定的顺序,我们可以依次给 a[0] 和 a[8] 赋值.因为没有对 a ...

随机推荐

  1. LNMP搭建静态网页服务器

    chattr -i default/.user.ini LNMP搭建使用 1.安装screen,命令或者操作可以一直运行下去 yum install screen 2.获取及安装 LNMP wget ...

  2. C# 从0到实战 命名空间

    什么是命名空间 命名空间是C#为了解决类名冲突而产生的一种方案,通过特定的前缀来标识一个类,使得编程者可以在自己的命名空间中自由使用各种类名,这很类似于Java中的包. 一般新手学习C#都会使用一个 ...

  3. RK3568用户自定义开机画面功能

    RK方案中的开机画面处画逻辑 在RK的方案中,如RK1109,RK1126,RK3568这些嵌入式LINUX方案在开机画面的处理逻辑都是一致的. 用户的uboot,kernel开机画面都是同dts,k ...

  4. Html 设置标题栏顶部固定

    如何设置标题栏一直置顶固定显示? 只需要给标题栏所在的容器,以下设置:   position: fixed;   top: 0px;   left: 0px;   width: 100%; 位置固定在 ...

  5. 【有问必答】搭建uniapp项目流程手把手教学

    前言 缘由 博友有问,狗哥必答 前段时间,博友加本狗微信,询问uniapp的学习方法.本狗资历浅薄,没有专门学过uniapp,只能将自己日常开发uniapp的基本流程和步骤进行分享,希望可以略尽绵薄之 ...

  6. [C++基础入门] 3、 运算符

    文章目录 3 运算符 3.1 算术运算符 3.2 赋值运算符 3.3 比较运算符 3.4 逻辑运算符 3 运算符 **作用:**用于执行代码的运算 本章我们主要讲解以下几类运算符: 运算符类型 作用 ...

  7. Python 函数传递任意数量的实参

    函数传递任意数量的实参 *形参名,形参名中的星号让python创建了一个空元组,并将收到的所有值都封装到这个元组中 # 案例 *toppings 形参名中的星号让python创建了一个空元组,并将收到 ...

  8. 互异关系容斥&集合幂级数小记

    最近碰见了一些互异关系容斥的题目,而这类题目往往要配合集合幂级数的一些技术使用,所以简单记记. 内容很杂,行文很乱,作者水平很低,酌情观看. 互异关系容斥 思想其实很基本,应用范围其实很广. 原论文. ...

  9. P2482 [SDOI2010] 猪国杀

    方法论 这是一道复杂的模拟题.由于游戏规则的条目很多,我们需要仔细考虑程序的组织.否则,在编写程序的过程中极容易陷入停滞的状态(不知道下一步应该怎么做),或在发现程序出问题时,难以快速定位到错误点,对 ...

  10. 【Vue2】NavigationDuplicated: Avoided redundant navigation to current location:xxxxx

    翻译过来就是,导航重复:避免了到当前位置的冗余导航. 简单来说就是重复跳转了相同路径 原因 触发这种情况是因为vue-router中引入了primise,当传递了多次重复的参数就会抛出异常,而这种问题 ...