一. 目标 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. 解决IDEA创建项目时无法引入依赖问题:Cannot resolve **.**.**(已解决)

    今天在创建SpringBoot整合MyBatis项目时出现报错: Cannot resolve org.springframework:spring-tx:5.3.26 Cannot resolve ...

  2. Cmder: 懒癌必备!从此告别记事本记命令的日子

    前言 平时开发中遇到这样那样的命令需要记下来,一般做法是这样. 新建记事本 将需要记下的关键命令保存. 每次需要使用时,粘贴复制即可. 好像没什么毛病!直到遇到了 Cmder... 当看到同事分析问题 ...

  3. 尝试CentOS8---部署集群(生产环境7.9为好)

    一.LVS集群简介 什么是集群 通过网络将很多服务器集中起来,提供同一种服务,在客户端看来就像是只有一个服务器 二.LVS-NAT集群 1.环境准备 启动3台虚拟机,禁用selinux和firewal ...

  4. 这是一篇记录——django-xadmin重新开发记录

    利用下面的代码把django的版本换成和xadmin2适配的版本,注意xadmin最新版本出了3.0但是就是一个纯前端的框架,和之前的版本差异较大. 因为此时距离ddl不到24小时,所以使用旧的版本. ...

  5. 【深入浅出Spring原理及实战】「源码调试分析」深入源码探索Spring底层框架的的refresh方法所出现的问题和异常

    学习Spring源码的建议 阅读Spring官方文档,了解Spring框架的基本概念和使用方法. 下载Spring源码,可以从官网或者GitHub上获取. 阅读Spring源码的入口类,了解Sprin ...

  6. 基于Java开发的全文检索、知识图谱、工作流审批机制的知识库

    一.项目介绍 一款全源码,可二开,可基于云部署.私有部署的企业级知识库云平台,应用在需要进行常用文档整理.分类.归集.检索的地方,适合知识密集型单位/历史文档丰富的单位,或者大型企业.集团. 为什么建 ...

  7. 【leetcode】258. 各位相加

    [leetcode]258. 各位相加 C++解法: class Solution { public: int addDigits(int num) { string s;//用来将num转换成字符串 ...

  8. 带你简单了解Chatgpt背后的秘密:大语言模型所需要条件(数据算法算力)以及其当前阶段的缺点局限性

    带你简单了解Chatgpt背后的秘密:大语言模型所需要条件(数据算法算力)以及其当前阶段的缺点局限性 1.什么是语言模型? 大家或多或少都听过 ChatGPT 是一个 LLMs,那 LLMs 是什么? ...

  9. 2020-09-01:mysql里什么是检查点、保存点和中间点?

    福哥答案2020-09-01: 检查点checkpoint:批量刷盘.在一定程度上代表了刷到磁盘时日志所处的日志序列号(LSN)位置.标记重做日志中已经完成刷到磁盘的位置点,如果缓冲池中有很多重做日志 ...

  10. 2021-03-26:给定一个正整数N,表示有N份青草统一堆放在仓库里。有一只牛和一只羊,牛先吃,羊后吃,它俩轮流吃草。不管是牛还是羊,每一轮能吃的草量必须是:1,4,16,64…(4的某次方)。谁最先把草吃完,谁获胜。假设牛和羊都绝顶聪明,都想赢,都会做出理性的决定。根据唯一的参数N,返回谁会赢。

    2021-03-26:给定一个正整数N,表示有N份青草统一堆放在仓库里.有一只牛和一只羊,牛先吃,羊后吃,它俩轮流吃草.不管是牛还是羊,每一轮能吃的草量必须是:1,4,16,64-(4的某次方).谁最 ...