Hi,大家好!我是CrazyCatJack。最近在学习Linux内核的配置、编译及Makefile文件。今天总结一下学习成果,分享给大家^_^

1.解压缩打补丁

  首先是解压缩你获取到的Linux内核。这里我用到的是linux.2.22.6版本的内核。在Linux下命令行通过tar xjf linux.2.22.6.tar.bz2解压内核。然后,如果你需要对这个内核打补丁的话,用patch命令:patch -px <../linux.2.22.6.patch。这里的px指的是忽略掉补丁文件中描述的第几个斜杠。也就是忽略前x个目录。

--- linux-2.6.22.6/arch/arm/configs/s3c2410_defconfig
+++ linux-2.6..6_jz2440/arch/arm/configs/s3c2410_defconfig

  如果你此刻就在内核的根目录下,即linux-2.6.22.6下,也就是说打补丁需要忽略掉一个斜杠的目录。那么打补丁的命令就是patch -p1 <../linux.2.22.6.patch。

2.配置内核

  现在补丁已经打好了,接下来就是配置内核了。这里配置有3种方法:

  1>直接进行make menuconfig。这是最麻烦的一种方法,所有的配置都需要你来操作。

  2>在默认配置上自己修改,也就是修改defconfig文件。使用 find -name "*defconfig*"查找你的架构对应的默认配置文件。我是在arch/arm/configs找到自己板子的默认配置文件。执行defconfig文件: make XXX_defconfig。XXX是你具体使用的板子型号。执行这一操作后,结果保存在.config文件。然后再执行make menuconfig命令。这时的配置就是在默认配置上稍加修改就可以了。

  3>使用厂家的配置文件。如果你的硬件有厂家提供的config文件那是最轻松的。直接cp XXX .config。然后执行make menuconfig。

  这里详细给大家讲一下内核的配置。Linux的内核配置,就是为了生成.config文件。因为在编译时需要用.config文件生成其他相关配置文件。我们的配置项大多是例如CONFIG_XXXDRIVER,这里的XXXDRIVER指的是各种驱动。我们需要告诉内核,这些驱动是编译进内核,还是编译成模块。通过查找CONFIG_XXXDRIVER,我们可以发现,它出现在四个地方:

  1>C源代码

  2>子目录Makefile:drivers/XXX/Makefile

  3>include/config/auto.conf

  4>include/linux/autoconf.h

    这里首先说明:.config文件在进行内核编译时(make uImage)生成了include/config/auto.conf和include/linux/autoconf.h。通过查看C源代码我们发现CONFIG_XXXDRIVER是一个宏定义,等于一个常量。在include/linux/autoconf.h中宏定义CONFIG_XXXDRIVER为一个常量,可能是0或1。那么现在有一个问题,就是CONFIG_XXXDRIVER到底被编译进内核还是编译成一个模块呢?这在C语言中是无法进行区分的,这种区分体现在哪里呢?这种区分体现在子目录的Makefile文件中。在子目录的Makefile中,若有 obj -y += XXX.o则表示XXX.c被编译进内核;obj -m +=XXX.o则表示XXX被编译成模块,为XXX.ko。include/config/auto.conf文件则是对CONFIG_XXXDRIVER进行赋值,为y时表示编译进内核,为m时表示编译成独立模块。

#这里是include/config/auto.conf的部分内容
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.22.6
# Sun Nov ::
#
CONFIG_CPU_S3C244X=y
CONFIG_CPU_COPY_V4WB=y
CONFIG_CRYPTO_CBC=y
CONFIG_CPU_S3C2410_DMA=y
CONFIG_CRYPTO_ECB=m
CONFIG_SMDK2440_CPU2440=y
#这里是drivers/i2c/Makefile
# Makefile for the i2c core.
# obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o
obj-$(CONFIG_I2C) += i2c-core.o
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
obj-y += busses/ chips/ algos/ ifeq ($(CONFIG_I2C_DEBUG_CORE),y)
EXTRA_CFLAGS += -DDEBUG
endif

3.编译内核
  通过上面的描述,我们可以知道,在每个driver下,都有一个Makefile文件。来定义这个驱动是编译进内核还是编译成模块。这里稍稍提一下。上面我们讲到了在Makefile中单个文件怎样编译进内核和编译成模块。但是如果有两个以上的文件该如何书写呢?这里举个例子:obj -y += a.o b.o就表示将a.c和b.c编译进内核。

obj -m += ab.o

ab -objs := a.o b.o

就可以表示将a.c和b.c共同编译成为一个模块。过程就是 a.c生成a.o , b.c生成b.o。a.o 和b.o共同生成ab.ko。在以往的对uboot启动内核的代码分析中,我们提到过编译内核生成的uImage是由两部分组成的:头部+Linux内核。这个头部包含了很多初始化的参数信息,例如内核的加载地址和入口地址。在编译内核时,我们直接执行make uImage即可。那么在文件中是怎样定义uImage的呢?又是怎样生成uImage的呢?

  首先,我们通过查找Makefile,发现uImage在arch/arm/Makefile中,而这个架构目录下的Makefile被包含进顶层目录的Makefile中。这样我们在执行 make uImage时,顶层目录的Makefile就可以调用架构子目录下的Makefile,实现对内核的编译,生成uImage。

顶层目录下Makefile中相关命令:
include $(srctree)/arch/$(ARCH)/Makefile
架构目录下Makefile相关命令:
zImage Image xipImage bootpImage uImage: vmlinux

  这就是刚刚所说的顶层Makefile调用架构目录下Makefile,架构目录下Makefile生成uImage,而且依赖于vmlinux文件。下面我们就开始讲解如何生成vmlinux文件。在顶层Makefile中,我们找到了有关生成vmlinux的大部分命令。

  

顶层目录Makefile:
init-y := init/
init-y := $(patsubst %/, %/built-in.o, $(init-y))
core-y := usr/
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
core-y := $(patsubst %/, %/built-in.o, $(core-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) drivers-y := drivers/ sound/
drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y)) net-y := net/
net-y := $(patsubst %/, %/built-in.o, $(net-y)) = net/built-in.o vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE vmlinux-init := $(head-y) $(init-y)
vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
vmlinux-all := $(vmlinux-init) $(vmlinux-main)
vmlinux-lds := arch/$(ARCH)/kernel/vmlinux.lds
export KBUILD_VMLINUX_OBJS := $(vmlinux-all) 架构目录Makefile:
zImage Image xipImage bootpImage uImage: vmlinux head-y        := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o

  我已经把顶层目录和架构目录下生成vmlinux的命令摘选出来。首先,我们看要想生成vmlinux,需要vmlinux-lds文件、vmlinux-init文件、vmlinux-main文件。其中,vmlinux-lds是链接脚本文件,定义了代码段,数据段的存放位置。这里我们接着往下看,vmlinux-init需要head-y和init-y,通过查看两个Makefile,我们可以得到经过转换后的结果:

  

head-y        :=
arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o init-y := $(patsubst %/, %/built-in.o, $(init-y)) = init/built-in.o core-y := $(patsubst %/, %/built-in.o, $(core-y))
= usr/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 libs-y := $(libs-y1) $(libs-y2) =lib/lib.a lib/built-in.o drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y)) = drivers/built-in.o sound/built-in.o net-y := $(patsubst %/, %/built-in.o, $(net-y)) = net/built-in.o

  现在已经分析了内核编译的全部过程。那怎样知道我们分析的到底对不对,通过实际执行make uImage我们就可以看到执行过程。这是执行make uImage过程中的部分相关命令:

arm-linux-ld -EL  -p --no-undefined -X -o vmlinux
-T arch/arm/kernel/vmlinux.lds
arch/arm/kernel/head.o
arch/arm/kernel/init_task.o init/built-in.o --start-group usr/built-in.o arch/arm/kernel/built-in.o arch/arm/mm/built-in.o

  可以看到,首先目标要生成vmlinux,然后是链接脚本为vmlinux.lds。开始生成第一个文件:head.o,第二个文件:init_task.o。这和我们分析的完全一致。接下来以此类推,和我们分析的相同,也就是说我们分析的是正确的。

SECTIONS
{ . = (0xc0000000) + 0x00008000; .text.head : {
_stext = .;
_sinittext = .;
*(.text.head)
} .init : { /* Init code and data */
*(.init.text)
_einittext = .;
__proc_info_begin = .;
*(.proc.info.init)
__proc_info_end = .;
__arch_info_begin = .;
*(.arch.info.init)
__arch_info_end = .;
__tagtable_begin = .;
*(.taglist.init)
__tagtable_end = .;
. = ALIGN();
__setup_start = .;
*(.init.setup)
__setup_end = .;
__early_begin = .;
*(.early_param.init)
__early_end = .;
__initcall_start = .;

  这是链接脚本vmlinux.lds中的部分内容。首先定义了虚拟地址:(0xc0000000) + 0x00008000。 然后是首先执行头部文件,这与我们分析的完全一致。代码段,初始化代码段等等。

  这就是Linux内核的从配置到编译的全部分析了^_^

CCJ

2016-12-01 11:32:45

Linux内核配置、编译及Makefile简述的更多相关文章

  1. Linux内核配置编译及基本调试方法

    一.Linux内核配置编译 1. 交叉编译设置:make ARCH=arm CROSS_COMPILE=arm-linux- 注:也可以直接修改顶层Makefile ARCH ?= arm CROSS ...

  2. Linux内核@系统组成与内核配置编译

    Linux系统由什么组成? 由用户空间(应用程序+GNU C标准库)和内核空间(系统调用接口+内核+内核架构代码)组成. Linux内核到底是什么?以及组成. ARM的七种操作级别? 内核网络协议栈( ...

  3. Linux内核配置机制(make menuconfig 、Kconfig、Makefile)讲解【转】

    本文转载自:http://www.codexiu.cn/linux/blog/34801/ 前面我们介绍模块编程的时候介绍了驱动进入内核有两种方式:模块和直接编译进内核,并介绍了模块的一种编译方式—— ...

  4. Linux 内核配置机制(make menuconfig、Kconfig、makefile)讲解

    前面我们介绍模块编程的时候介绍了驱动进入内核有两种方式:模块和直接编译进内核,并介绍了模块的一种编译方式--在一个独立的文件夹通过makefile配合内核源码路径完成 那么如何将驱动直接编译进内核呢? ...

  5. Linux 内核配置和编译

    Linux 内核配置和编译 一.配置内核 (1). 为什么要配置内核 1. 硬件需求 2. 软件需求 选出需要的,去掉不要的 (2). 如何配置内核 1. make  config 基于文本模式的交互 ...

  6. Linux内核分析(一)---linux体系简介|内核源码简介|内核配置编译安装

    原文:Linux内核分析(一)---linux体系简介|内核源码简介|内核配置编译安装 Linux内核分析(一) 从本篇博文开始我将对linux内核进行学习和分析,整个过程必将十分艰辛,但我会坚持到底 ...

  7. 【Linux内核】编译与配置内核(x86)

    [Linux内核]编译与配置内核(x86)  https://www.cnblogs.com/jamesharden/p/6414736.html

  8. Linux内核配置浅析

    1.Linux Kernel Kconfig系统的基本结构 Linux内核的配置系统由三个部分组成,分别是: 1>.Makefile:分布在 Linux 内核源代码根目录及各层目录中,定义 Li ...

  9. Tiny4412 Linux 内核配置流程

    1.配置交叉编译器 默认情况下,内核构建的是与宿主机相同的体系架构镜像.如果要交叉编译,需要设置两个变量ARCH和CORSS_COMPILE. ①ARCH:指明目标体系架构,如x86.arm.mips ...

  10. linux内核配置 kbuild

    Linux 内核配置机制 http://blog.csdn.net/dianhuiren/article/details/6917132 linux kbuild文档 http://blog.chin ...

随机推荐

  1. 开始学nodejs——net模块

    net模块的组成部分 详见 http://nodejs.cn/api/net.html 下面整理出了整个net模块的知识结构,和各个事件.方法.属性的用法 net.Server类 net.Socket ...

  2. .NET CoreCLR开发人员指南(上)

    1.为什么每一个CLR开发人员都需要读这篇文章 和所有的其他的大型代码库相比,CLR代码库有很多而且比较成熟的代码调试工具去检测BUG.对于程序员来说,理解这些规则和习惯写法非常的重要. 这篇文章让所 ...

  3. Android中点击事件的实现方式

    在之前博文中多次使用了点击事件的处理实现,有朋友就问了,发现了很多按钮的点击实现,但有很多博文中使用的实现方式有都不一样,到底是怎么回事.今天我们就汇总一下点击事件的实现方式. 点击事件的实现大致分为 ...

  4. Android中Fragment与Activity之间的交互(两种实现方式)

    (未给Fragment的布局设置BackGound) 之前关于Android中Fragment的概念以及创建方式,我专门写了一篇博文<Android中Fragment的两种创建方式>,就如 ...

  5. 如何区别exists与not exists?

    1.exists:sql返回结果集为真:not exists:sql不返回结果集为真.详解过程如图: exists not exists

  6. 为什么你SQL Server的数据库文件的Date modified没有变化呢?

    在SQL Server数据库中,数据文件与事务日志文件的修改日期(Date Modified)是会变化的,但是有时候你会发现你的数据文件或日志文件的修改日期(Date Modified)几个月甚至是半 ...

  7. 烂泥:wiki系统confluence5.6.6安装、中文、破解及迁移

    本文由ilanniweb提供友情赞助,首发于烂泥行天下 想要获得更多的文章,可以关注我的微信ilanniweb confluence是一个专业的企业知识管理与协同软件,可以用于构建企业wiki.通过它 ...

  8. Visual Studio 实用扩展推荐

    Visual Studio 拥有非常不错的可扩展性,在之前的文章中,我也给大家示范了如何进行编辑器的扩展(详见文末参考资源).在本篇文章中,我将介绍几款非常实用的扩展,从而帮助我们提高开发效率. C# ...

  9. 自定义ActionBar标题与菜单中的文字样式

    自定义标题文字样式 标题样式是ActionBar样式的一部分,所以要先定义ActionBar的样式 <style name="AppTheme" parent="A ...

  10. 在IDEA上跑eclipse开发的J2EE项目

    Context MacOS 10.12.1 IDEA ULTIMATE 2016.2 项目使用eclipse开发 项目使用SVN进修版本管理 核心步骤 检出项目,完成基本配置 从svn检出 当项目下载 ...