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. C# 破解 Reflector8.5

    一.分析 破解.net .dll,可以使用reflector,但官方提供的reflector是需要购买的,因此,破解reflector势在必行. 二.破解Reflector具体步骤 下面为详细的破解步 ...

  2. mybatis_个人总结

    在使用mybatis框架开发数据访问层的过程中,我在这段时间遇到很多细节问题困住我,在这里我来分享一下我遇到的坑,希望能帮到大家. 一.mybatis动态代理方式开发的规范: 1.注意在mybatis ...

  3. javascript之闭包理解以及应用场景

    半个月没写博文了,最近一直在弄小程序,感觉也没啥好写的. 之前读了js权威指南,也写了篇博文,但是实话实说当初看闭包确实还是一头雾水.现在时隔一个多月(当然这一段时间还是一直有在看闭包的相关知识)理解 ...

  4. 【云知道】LoadRunner 录制问题集锦

    关键词:各路录制小白汇集于此 虽然知道君对录制不感冒,但总是看到扎堆的人说这些问题,忍不住要站出来了. 百度虽好,帮助了很多小白,但关键是百度并没有排除错误内容,经过历史的几年传播,错的都快变对的了, ...

  5. 那些年【深入.NET平台和C#编程】

    一.深入.NET框架 1..NET框架具有两个组件:CLR(公共语言运行时)和FCL(框架类库),CLR是.NET框架的基础 2.框架核心类库: System.Collections.Generic: ...

  6. 【读书】PHP程序员要读的书目(不断完善中)

    本文地址 分享提纲: 1. PHP 2. Linux 3. Apache/Nginx 4. Mysql 5.设计模式/架构 6. 缓存并发 7. 其他语言 8. 代码基础 9. 大前端 10. 管理生 ...

  7. java web学习总结(五) -------------------servlet开发(一)

    一.Servlet简介 Servlet是sun公司提供的一门用于开发动态web资源的技术. Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源(即开发一个Java程序向 ...

  8. arcgis api for js入门开发系列七图层控制(含源代码)

    上一篇实现了demo的地图分屏对比模块,本篇新增图层控制模块,截图如下(源代码见文章底部): 图层控制模块实现的思路如下: 1.在地图配置文件map.config.js里面配置图层目录树节点信息,作为 ...

  9. BPM协同平台解决方案分享

    一.需求分析 企业信息化的过程都是从单纯解决一个业务功能问题,到解决企业内部业务流程问题,再扩展到解决不同业务流程的关联互动问题, 核心是业务的集成和业务的协同,需要有一个统一的业务协同平台. 国内的 ...

  10. iOS开源项目周报1222

    由OpenDigg 出品的iOS开源项目周报第二期来啦.我们的iOS开源周报集合了OpenDigg一周来新收录的优质的iOS开发方面的开源项目,方便iOS开发人员便捷的找到自己需要的项目工具等. io ...