linux 内核裁剪与编译

一、Linux 内核源码

到 www.kernel.org 下载官方内内核。

1.linux内核目录

$ tree kernel/ -L 1
kernel/
├── android
├── arch
├── backported-features
├── block
├── boot.img
├── build.config.cuttlefish.aarch64
├── build.config.cuttlefish.x86_64
├── certs
├── config.old
├── COPYING
├── CREDITS
├── crypto
├── Documentation
├── drivers
├── firmware
├── fs
├── include
├── init
├── ipc
├── Kbuild
├── Kconfig
├── kernel
├── kernel.img
├── lib
├── logo.bmp
├── MAINTAINERS
├── Makefile
├── mm
├── modules.builtin
├── modules.order
├── Module.symvers
├── net
├── README
├── REPORTING-BUGS
├── resource.img
├── samples
├── scripts
├── security
├── sound
├── System.map
├── tools
├── usr
├── verity_dev_keys.x509
├── virt
├── vmlinux
├── vmlinux.o
└── zboot.img

23 directories, 24 file

目录说明

  • arch:包含和硬件体系结构相关的代码,每种平台占一个相应的目录,如 i386、arm、arm64、powerpc、mips 等。Linux 内核目前已经支持30种左右的体系结构。
    • 在 arch 目录下,存放的是各个平台以及各个平台的芯片对 Linux 内核进程调度、内存管理、中断等的支持,以及每个具体的 SoC 和电路板的板级支持代码。
  • block:块设备驱动程序 I/O 调度。
  • crypto:常用加密和散列算法(如AES、SHA等),还有一些压缩和 CRC 校验算法。
  • documentation:内核各部分的通用解释和注释。
  • drivers:设备驱动程序。每个不同的驱动占用一个子目录,如 char、block、net、mtd、 i2c 等。
  • fs:所支持的各种文件系统,如EXT、FAT、NTFS、JFFS2等。
  • include:内核 API 级別头文件,与系统相关的头文件放置在 include/linux 子目录下。
  • init:内核初始化代码。著名的 stait_kemel() 就位于 init/main.c 文件中。
  • ipc:进程间通信的代码。
  • kernel:内核最核心的部分,包括进程调度、定时器等,而和平台相关的一部分代码放在 arch/*/kemel 目录下。
  • lib:库文件代码。
  • mm:内存管理代码,和平台相关的一部分代码放在arch/*/mm目录下。
  • net:网络相关代码,实现各种常见的网络协议。
  • scripts:用于配置内核的脚本文件。
  • security:主要是一个 SELinux 的模块。
  • sound:ALSA、OSS 音频设备的驱动核心代码和常用设备驱动。
  • usr:实现用于打包和压缩的 cpio 等。

2.快速确定主板关联代码

板级基础代码

Linux 移植通常分为体系结构级别移植、处理器级别移植和板级移植 。

  • 确定体系架构相关的文件

    $ tree arch/arm64/ -L 1
    arch/arm64/
    ├── boot
    ├── configs
    ├── crypto
    ├── include
    ├── Kconfig
    ├── Kconfig.debug
    ├── Kconfig.platforms
    ├── kernel
    ├── kvm
    ├── lib
    ├── Makefile
    ├── mm
    ├── net
    └── xen
    
    • 确定内核配置文件,决定编译的内核模块和驱动。

      • 如:默认内核配置文件为

        # 部分内容
        CONFIG_DEFAULT_HOSTNAME="localhost"
        CONFIG_SYSVIPC=y
        CONFIG_POSIX_MQUEUE=y
        CONFIG_FHANDLE=y
        CONFIG_NO_HZ=y
        CONFIG_HIGH_RES_TIMERS=y
        CONFIG_LOG_BUF_SHIFT=18
        CONFIG_CGROUPS=y
        CONFIG_CGROUP_FREEZER=y
        CONFIG_CGROUP_PIDS=y
        CONFIG_CGROUP_DEVICE=y
        CONFIG_CPUSETS=y
        CONFIG_CGROUP_CPUACCT=y
        CONFIG_MEMCG=y
        CONFIG_MEMCG_SWAP=y
        CONFIG_CGROUP_PERF=y
        CONFIG_CGROUP_SCHED=y
        CONFIG_CFS_BANDWIDTH=y
        CONFIG_RT_GROUP_SCHED=y
        CONFIG_BLK_CGROUP=y
        CONFIG_NAMESPACES=y
        CONFIG_USER_NS=y
        ...
        
    • 确定设备树文件,决定板级外设配置

      • 如:
  • 确定对应的主板文件(32位板子)。

    • 如:

驱动代码

​ 驱动代码在drivers 目录

其它代码

​ 文件系统的实现代码、网络子系统的实现代码等。

2.Linux 内核中的 Makefile 文件

1)顶层 Makefile

源码目录树顶层 Makefile 是整个内核源码管理的入口,对整个内核的源码编译起着决定性作用。编译内核时,顶层 Makefile 会按规则递归历遍内核源码的所有子目录下的Makefile 文件,完成各子目录下内核模块的编译。

内核版本号

顶层 Makefile,开头的几行记录了内核源码的版本号 。

VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 35
EXTRAVERSION =3
#说明代码版本为 2.6.35.3

内核在目标板运行后,输入 uname -a 命令可以得到印证 。

编译控制
  • 体系结构

    • Linux 是一个支持众多体系结构的操作系统,在编译过程中需指定体系结构,以与实际平台对应。在顶层 Makefile 中,通过变量 ARCH 来指定 。

    • ARCH ?= $(SUBARCH)
      #如果进行 ARM 嵌入式 Linux 开发,则必须指定 ARCH 为 arm(注意大小写,须与 arch/目录下的 arm 一致)
      #如:$make ARCH=arm
      
  • 编译器

    • 进行 ARM 嵌入式 Linux 开发,必须指定交叉编译器,可以在内核配置通过 CONFIG_CROSS_COMPILE 指定交叉编译器,也可以通过 CROSS_COMPILE 指定。

    $ make ARCH=arm CROSS_COMPILE= arm-linux-gnueabihf-

    
    ```makefile
    CROSS_COMPILE = arm-linux-gnueabihf-
    #注意: CROSS_COMPILE 指定的交叉编译器必须事先安装并正确设置系统环境变量; 如果没有设置环境变量, 则需使用绝对地址
    

2)子目录的 Makefile

几乎每个子目录都有相应的 Makefile 文件,管理着对应目录下的代码。

Makefile 中有两种表示方式:

  • 一种是默认选择编译,用 obj-y 表示

    • obj-y += usb-host.o # 默认编译 usb-host.c 文件
      obj-y += gpio/ # 默认编译 gpio 目录
      
  • 另一种表示则与内核配置选项相关联,编译与否以及编译方式取决于内核配置 。

    • obj-$(CONFIG_WDT) += wdt.o # wdt.c 编译控制
      obj-$(CONFIG_PCI) += pci/ # pci 目录编译控制
      

      是否编译 wdt.c 文件,或者以何种方式编译,取决于内核配置后的变量 CONFIG_WDT值:如果在配置中设置为[*],则静态编译到内核,如果配置为[M],则编译为 wdt.ko 模块,否则不编译。

3.Linux 内核中的 Kconfig 文件

​ 内核源码树每个目录下都还包含一个 Kconfig 文件,用于描述所在目录源代码相关的内核配置菜单,各个目录的 Kconfig 文件构成了一个分布式的内核配置数据库。

​ 通过 make menuconfig(make xconfig 或者 make gconfig)命令配置内核的时候,从 Kconfig 文件读取单,配置完毕保存到文件名为.config 的内核配置文件中,供 Makefile 文件在编译内核时使用。

1)Kconfig的格式

​ Kconfig按照一定的格式来书写,menuconfig程序可以识别这种格式,然后从中提取出有效信息组成menuconfig中的菜单项。

​ 截取/drivers/net下的Kconfig文件中的部分内容:

# Network device configuration
menuconfig NETDEVICES
        default y if UML
        depends on NET
        bool "Network device support"
        ---help---
          You can say N here if you don't intend to connect your Linux box to any other computer at all.
……
config DM9000
        tristate "DM9000 support"
        depends on ARM || BLACKFIN || MIPS
        select CRC32
        select MII
        ---help---
          Support for DM9000 chipset.

          To compile this driver as a module, choose M here.  The module will be called dm9000.
……
source "drivers/net/arcnet/Kconfig"
source "drivers/net/phy/Kconfig"
  • menuconfig:表示菜单(本身属于一个菜单中的项目,但是又有子菜单项目)、config表示菜单中的一个配置项(本身并没有子菜单下的项目)。一个menuconfig后面跟着的所有config项就是这个menuconfig的子菜单。这就是Kconfig中表示的目录关系。
  • NETDEVICES:配置项名字,用大写字母表示。这个字符串前面添加CONFIG_后就构成了“.config”文件中的配置项名字。
  • source:内核源码目录树中每一个Kconfig都会用source引入其所有子目录下的Kconfig,从而保证了所有的Kconfig项目都被包含进menuconfig中。
    • 如果在linux内核中添加了一个文件夹,一定要在这个文件夹下创建一个Kconfig文件,然后在这个文件夹的上一层目录的Kconfig中source引入这个文件夹下的Kconfig文件。
  • tristate:意思是三态(3种状态,对应Y、N、M三种选择方式),意思就是这个配置项可以被三种选择。
  • bool:是要么真要么假(对应Y和N)。意思是这个配置项只能被2种选择。
  • depends:意思是本配置项依赖于另一个配置项。如果那个依赖的配置项为Y或者M,则本配置项才有意义;如果依赖的哪个配置项本身被设置为N,则本配置项根本没有意义。
  • select:表示depends on的值有效时,下面的select也会成立,将相应的内容选上。
  • default:表示depends on的值有效时,下面的default也会成立,将相应的选项选上,有三种选项,分别对应y,n,m。
  • help:帮助信息,解释这个配置项的含义,以及如何去配置他。

2)Kconfig和.config文件和Makefile三者的关联

  • 配置项被配置成Y、N、M会影响“.config”文件中的CONFIG_XXX变量的配置值。
  • .config”中的配置值(=y、=m、没有)会影响最终的Makefile编译链接过程,如makefile中:obj-$(CONFIG_DM9000) += dm9000.o
    • 如果=y则会被编入(built-in);
    • 如果=m会被单独连接成一个”.ko”内核模块(需要insmod动态加载到内核中);
    • 如果没有则对应的代码不会被编译。

4.Linux 内核源码配置执行过程

关键文件

  • Kconfig ---> (每个源码目录下)提供选项
  • .config ---> (源码顶层目录下)保存选择结果
  • Makefile---> (每个源码目录下)根据.config中的内容来告知编译系统如何编译

1)执行步骤

  • 系统读取arch/$ARCH/目录下的Kconfig文件生成整个配置界面选项(Kconfig是整个linux配置机制的核心)。

    • 那么ARCH环境变量的值由linux内核根目录下的makefile文件决定的,在makefile有此环境变量的定义。
    • 或者通过 make ARCH=arm menuconfig命令来生成配置界面。
  • 修改内核配置后,当保存make menuconfig选项时,系统会将配置保存在内核根目录下.config文件。还会将所有的选项以宏的形式保存在Linux内核根目录下的 include/generated/autoconf.h文件下。

    • 内核有默认配置选项提供,存放在arch/$ARCH/configs下,可以将所需的配置复制到内核根目录下.config文件。
    $ cp arch/arm64/configs/rockchip_linux_defconfig .config
    
  • 执行make编译,会根据.config文件所配置的选项(=y、=m、没有)逐个进行编译。

    • 或者可以指定编译配置文件

      # Kernel defconfig
      export RK_KERNEL_DEFCONFIG=rockchip_linux_defconfig
      # Kernel dts
      export RK_KERNEL_DTS=rk3399-firefly-aioc
      
      $ make ARCH=arm64 $RK_KERNEL_DEFCONFIG
      $ make ARCH=arm64 $RK_KERNEL_DTS.img
      

二、配置和编译 Linux 内核

1.快速配置内核

进入 Linux 内核源码数顶层目录,输入 make menuconfig 命令 。

注意: 主机须安装 ncurses 相关库才能正确运行该命令并出现配置界面 。

如果没有在 Makefile 中指定 ARCH,则须在命令行中指定

$ make ARCH=arm menuconfig

2.内核配置详情

菜单项 说明
General setup ---> 内核通用配置选项,包括交叉编译器前缀、本地版本、内核压缩模式、 config.gz 支持、内核 log 缓冲区大小、 initramfs以及更多的内核运行特性支持等
[ ] Enable loadable module support ---> 内核模块加载支持,通常都需要
[ ] Enable the block layer ---> 使能块设备。如果未选中使能,块设备将不能使用, SCSI类字符设备和 USB 大容量类设备也将不能使用。
System Type ---> 系统类型,设置 ARM 处理器型号、处理器的特性以及默认的评估板主板
Bus support ---> PCMCIA/CardBUS 总线支持,目前已经很少使用
Kernel Features ---> 内核特性,包括内核空间分配、实时性配置等特性配置
Boot options ---> 内核启动选项,如果采用内置启动参数,则在这里设置
CPU Power Management ---> CPU 电源管理,包括处理器频率降频、休眠模式支持等
Floating point emulation ---> 浮点模拟
Userspace binary formats ---> 用户空间二进制支持
Power management options ---> 电源管理选项
[ ] Networking support ---> 网络协议支持,包括网络选项、 CAN-Bus、红外、无线、 NFC等。其中的网络选项还有更多配置项,如 IPv4、 IPv6 等
Device Drivers ---> 设备驱动,包含多级下级菜单,包括驱动通用选项、 MTD设备、字符设备、网络设备、输入设备、 I2C 总线、 SPI 总线、 USB 总线、 GPIO、声卡、显卡等各种外设配置菜单
File systems ---> 文件系统, 包含 Ext2、 Ext3、 Ext4、 JFFS、 NFS、 DOS 等各种文件系统, 以及本地语言支持等
Kernel hacking ---> 内核 Hacking,在内核调试阶段可酌情使能其中的选项,以获得需要的调试信息
Security options ---> 安全选项
< > Cryptographic API ---> 加密接口,内核提供的一些加密算法如 CRC32、MD5、SHA1、SHA224 等
OCF Configuration ---> 开放的加密框架
Library routines ---> 库例程
Load an Alternate Configuration File 装载一个配置文件
ave an Alternate Configuration File 保存为一个配置文件

1)通用设置 General setup

选项 说明
( ) Cross-compiler tool prefix 交叉编译器前缀,将会设置 CONFIG_CROSS_COMPILE 变量, 等同于 make CROSS_COMPILE=prefix-
( ) Local version - append to kernel release 填写本地版本
[ ] Automatically append version informationto the version string 自动增加版本信息。如果用了 Git 管理内核源码,每次 Git提交都会造成内核版本号增加。谨慎使用该选项
< > Kernel .config support 选中该选项会将当前内核配置信息保存到内核中
[ ] Enable access to .config through/proc/config.gz 通过/proc/config.gz 获得当前运行内核的配置信息。建议选中
[ ] Initial RAM filesystem and RAM disk(initramfs/initrd) support Initramfs 支持,使能该特性可以将一个文件系统打包到内核文件中,内核启动不需要额外的文件系统
( ) Initramfs source file(s) Initramfs 文件系统的路径,通常放在源码树 usr 目录下

2)内核特性 Kernel Features

选项 说明
[ ] Tickless System (Dynamic Ticks) 无时钟系统支持,根据系统运行状况来启用或者禁用时钟,能让内核运行更有效且更省电。 A8 这样的处理器建议选中
[ ] High Resolution Timer Support 高精度定时器。处理器支持则可选中
Memory split (3G/1G user/kernel split)---> 4G 内存分割比例,内核和用户空间: 3G/1G、 2G/2G、 1G/2G。早期内核是 3G/1G 固定分割,目前可配置
Preemption Model (No Forced Preemption(Server)) ---> 内核抢占模式,可选值:No Forced Preemption (Server)Voluntary Kernel Preemption (Desktop)Preemptible Kernel (Low-Latency Desktop)需要实时性则须设置为 Preemptible Kernel
[ ] Compile the kernel in Thumb-2 mode(EXPERIMENTAL) 以 Thumb-2 指令集编译内核。不推荐
[ ] High Memory Support 高端内存,嵌入式系统通常不用选

3)启动选项

默认启动参数通过“Default kernel command string”设置

(root=/dev/mmcblk0p2 rootwait console=ttyO0,115200) Default kernel command string

内核参数类型通过 Kernel command line type 来设置

  • ( ) Use bootloader kernel arguments if available
    • 可接受bootloader传递的参数启动
  • ( ) Extend bootloader kernel arguments
  • ( ) Always use the default kernel command string
    • 只能使用默认内核启动参数

4)网络支持

网络支持部分,包括了以太网、 CAN、红外、蓝牙、无线等各种网络的支持配置选项。

从 Networking support -> Networking options, 可进入网络选项配置界面 。

选项 说明
< > Packet socket 选中支持应用直接与网卡通信而不需要在内核中实现网络协议,建议选中
< > Unix domain sockets UNIX domain Socket 支持,建议选中。如果采用 udev/mdev动态管理设备,则必须选中
< > PF_KEY sockets PF_KEY 协议族,内核安全相关,建议选中
[ ] TCP/IP networking TCP/IP 支持,使用网络通常需选中,还有更多的下级菜单,如 IPv4、 IPv6 等设置
[ ] Network packet filtering framework(Netfilter) ---> 对网络数据包进行过滤,如果需要防火墙功能,则必须选中。有下级菜单,根据实际需要配置
< > 802.1d Ethernet Bridging 802.1d 以太网桥
< > 802.1Q VLAN Support 802.1Q 虚拟局域网
[ ] QoS and/or fair queueing ---> Qos 支持,该选项可支持多种不同的包调度算法,否则仅能使用简单的 FIFO 算法

使用 Linux 的系统都会用到网络,而使用网络又往往离不开 TCP/TP,故建议在配置中选中 TCP/IP 选项,并选中下级全部选项 。

5)设备驱动

选项 说明
Generic Driver Options ---> 通用设备驱动选项
CBUS support ---> CBUS 支持,不清楚则不要选
< > Connector - unified userspace <-> kernelspacelinker ---> 统一的用户空间<-->内核空间连接器,工作在 Netlinksocket 协议顶层,不确定则不选
< > Memory Technology Device (MTD) support---> 内存技术设备,如 FLASH、 RAM 等支持。通常需要选中
Device Tree and Open Firmware support ---> /proc 设备树支持,可选中
< > Parallel port support ---> 并口支持,嵌入式系统通常不选
[ ] Block devices ---> 块设备,选中,否则不能操作任何块设备
[ ] Misc devices ---> 杂项设备。通常选中,如需用 eeprom 设备,则必选
SCSI device support ---> SCSI 设备支持。如要用 U 盘,则必选
< > Serial ATA and Parallel ATA drivers ---> SATA 和 PATA 设备支持。除非硬件支持,否则不选
[ ] Multiple devices driver support (RAID and LVM)---> 多设备支持(RAID&LVM),嵌入式通常不选
< > Generic Target Core Mod (TCM) and ConfigFSInfrastructure ---> TCM 存储引擎和 ConfigFS 控制
[ ] Network device support ---> 网络设备支持,包括网卡、 PHY 驱动、 ppp 协议等选择
[ ] ISDN support ---> ISDN 支持
< > Telephony support ---> 电话支持。在 Linux 下使用 Modem 拨号,无需使能该选项
Input device support ---> 输入设备支持,包括键盘、鼠标、触摸屏、游戏杆等
Character devices ---> 字符设备,包括 tty 等设备。特别注意,串口驱动配置也在这里面
< > I2C support ---> I2C 支持。 I2C 协议和控制器配置
[ ] SPI support ---> SPI 支持。 SPI 协议和 SPI 控制器
PPS support ---> PPS 支持
PTP clock support ---> PTP 时钟支持
[ ] GPIO Support ---> GPIO 支持
< > PWM Support ---> PWM 支持
< > Dallas's 1-wire support ---> Dallas 单总线支持
< > Power supply class support ---> 电源管理类支持
< > Hardware Monitoring support ---> 硬件监测支持,各种传感器
< > Generic Thermal sysfs driver ---> Thermal sysfs 接口支持
[ ] Watchdog Timer Support ---> 看门狗支持,包括硬件看门狗和软件看门狗
Sonics Silicon Backplane ---> SSB 总线支持
Broadcom specific AMBA ---> 博通 AMBA 总线支持
Multifunction device drivers ---> 多功能设备驱动支持
[ ] Voltage and Current Regulator Support ---> 电压和电流调节支持。如果有电源管理芯片,通常需要选中
< > Multimedia support ---> 多媒体支持。 V4L2 在这里面配置
Graphics support ---> 图形支持。 Framebuffer、背光、 LCD、开机 LOGO 等配置
< > Sound card support ---> 声卡支持
[ ] HID Devices ---> HID 设备,使用 USB 鼠标键盘等 HID 设备必须选中该选项
[ ] USB support ---> USB 支持
< > MMC/SD/SDIO card support ---> SD/MMC 设备支持
< > Sony MemoryStick card support(EXPERIMENTAL) ---> Sony 记忆棒支持
[ ] LED Support ---> LED 子系统和驱动
[ ] Accessibility support ---> 易用性支持,嵌入式通常不选
[*] Real Time Clock ---> 实时时钟,包括处理器内部时钟和外扩时钟选择
[ ] DMA Engine support ---> 引擎支持
[ ] Auxiliary Display support ---> 辅助显示支持
< > Userspace I/O drivers ---> 用户空间 I/O 驱动(uio 支持)
Virtio drivers ---> Virtio 驱动
[*] Staging drivers ---> 分阶段驱动
Hardware Spinlock drivers ---> 硬件 Spinlock 驱动
[ ] IOMMU Hardware Support ---> IOMMU 硬件支持,根据具体硬件选择
[ ] Virtualization drivers ---> 虚拟化驱动
[ ] Generic Dynamic Voltage and Frequency Scaling(DVFS) support ---> 通用的动态电压和频率调节

6)文件系统 File systems

选项 说明
< > Second extended fs support Ext2 文件系统支持,建议选中或模块编译
< > Ext3 journalling file system support Ext3 文件系统支持,建议选中或模块编译
< > The Extended 4 (ext4) filesystem Ext4 文件系统支持,建议选中或模块编译
< > Reiserfs support Reiserfs 是一种先进的文件系统,不过嵌入式中不常用
< > JFS filesystem support IBM 开发的日志文件系统,嵌入式中不常用
< > XFS filesystem support XFS 文件系统支持
< > GFS2 file system support GFS2 文件系统支持
< > Btrfs filesystem (EXPERIMENTAL)Unstable disk format BtrFS 文件系统支持。 BtrFS 是一种新型文件系统,被称为下一代 Linux 文件系统
< > NILFS2 file system support(EXPERIMENTAL) NiLFS2 文件系统支持
[ ] Dnotify support 文件系统通知系统,建议选中
[ ] Inotify support for userspace 用户空间 Inotify 支持,建议选中
[ ] Filesystem wide access notification Fanotify 支持,能比 Inotify 传递更多信息
[ ] Quota support 磁盘配额支持。选中后可限制某个用户或者某组用户的磁盘占用空间。嵌入式中不常用
< > Kernel automounter version 4support (also supports v3) 第 4 版内核自动加载远程文件系统支持(同时支持第 3 版)
< > FUSE (Filesystem in Userspace) support 选中后则允许在用户空间实现一个文件系统
Caches ---> 文件系统 Cache 支持
CD-ROM/DVD Filesystems ---> CD-ROM 和 DVD 支持,有 ISO 9660 和 UDF 两个选项。如果需要支持 CD/DVD,则可选
DOS/FAT/NT Filesystems ---> DOS/FAT/NTFS 文件系统支持。如果需要支持 U 盘,必须选中 MDOS 和 VFAT 支持
Pseudo filesystems ---> 伪文件系统,基于内存的文件系统,如 tmpfs
[ ] Miscellaneous filesystems ---> 其它杂项文件系统,很多文件系统都归类在这里,嵌入式中常用的 cramfs、 ubifs 等都在这里配置
[ ] Network File Systems ---> 网络文件系统。建议选中,通过 NFS 能方便调试,对于嵌入 式系统, NFS Server 通常不选
Partition Types ---> 分区支持
< > Native language support ---> 本地语言支持,通常选中 iso-8859-1、 CP437、 CP437 和 utf-8等

3.编译内核

1)从内核码源编译成zImage

内核配置完成,输入 make 命令即可开始编译内核。如果没有修改 Makefile 文件并指定
ARCH 和 CROSS_COMPILE 参数,则须在命令行中指定 。

$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-

目前大多数主机都是多核处理器,为了加快编译进度,可以开启多线程编译,在 make
的时候加上“-jN”即可, N 的值为处理器核心数目的 2 倍。

$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- -j8

如果编译不出错,编译完成,会生成 vmlinux、 Image、 zImage 等文件

文件 说明 备注
vmlinux 未经压缩、带调试信息和符号表的内核文件, elf 格式 顶层目录下
arch/arm/boot/compressed/vmlinux 经过压缩的 Image,并加入了解压头的 elf 格式文件
arch/arm/boot/Image 将 vmlinux 去除调试信息、注释和符号表等,只包含内核代码和数据后得到的非 elf 格式文件
arch/arm/boot/zImage 经过 objcopy 处理,能直接下载到内存中执行的内核映像文件
  • zImage

zImage 是通常情况下默认的压缩内核,可以直接加载到内存地址并开始执行。

  • uImage

对于 ARM Linux 系统,大多数采用 U-Boot 引导,很少直接使用 zImage 映像,实际上
更多的是 uImage。

uImage 是 U-Boot 默认采用的内核映像文件,它是在 zImage 内核映像之
前加上了一个长度为 64 字节信息头的映像。这 64 字节信息头包括映像文件的类型、加载位置、生成时间、大小等信息 。

在 U-Boot 下,通过 bootm 命令可以引导 uImage 映像文件启动。

$ tftp C0008000 uImage
$ bootm C0008000

2)把zImage转为uImage

  • mkimage 工具

从 zImage 生成 uImage 需要用到 mkimage 工具。该工具可在编译 U-Boot 源码后从 tools目录下获得,复制到系统/usr/bin 目录即可 。

对于 Ubuntu 系统,还可用 sudo apt-get installu-boot-tools 命令安装得到。

进入 mkimage 文件所在目录执行该文件,或者在安装 mkimage工具后,使用 mkimage 工具根据 zImage 制作 uImage 映像文件的命令如下:

$ mkimage [-x] -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image
#命令参数中需要指定体系结构、操作系统类型、压缩方式和入口地址等信息
参数 说明
-A arch 指定处理器的体系结构为 arch,可能值有: alpha、 arm、 x86、 ia64、 mips、 mips64、 ppc、s390、 sh、 sparc、 sparc64、 m68k 等
-O os 指定操作系统类型为 os,可用值有: openbsd、 netbsd、 freebsd、 4_4bsd、 linux、 svr4、 esix、solaris、 irix、 sco、 dell、 ncr、 lynxos、 vxworks、 psos、 qnx、 u-boot、 rtems、 artos 等
-T type 指定映象类型为 type,可能值有: standalone、 kernel、 ramdisk、 multi、 firmware、 script、filesystem 等
-C comp 指定映象压缩方式为 comp,可能值有:none 不压缩(推荐, zImage 已经过 bzip2 压缩,通常无需再压缩)gzip 用 gzip 的压缩方式bzip2 用 bzip2 的压缩方式
-a addr 指定映象在内存中的加载地址为 addr(16 进制)。制作好的映象下载到内存时, 须按照该参数所指定的地址值来下载。 U-Boot 的 bootm xxx 命令会判断 xxx 是否与 addr 相同:(1)如果不同,则从 xxx 这个地址开始提取出这个 64 字节的头部,对其进行分析,然后把去掉头部的内核复制到 addr 地址中去运行。(2)如果相同,则不作处理, 仅将-e 指定的入口地址推后 64 字节, 即跳过这 64 字节的头部信息。
-e ep 指定映象运行的入口地址为 ep(16 进制)。 ep 的值为 addr+0x40,也可设置为和 addr 相同
-n name 指定映象文件名为 name
-d data_file 指定制作映象的源文件,通常是 zImage
image 输出的 uImage 映像文件名称,通常设置为 uImage

对于 EPC-28x 处理器,内存起始地址为 0x40000000,从 zImage 生成 uImage 映像文件
的命令实际操作范例:

$ mkimage -A arm -O linux -T kernel -C none -a 0x40008000 -e 0x40008000 -n 'Linux-2.6.35' -d arch/arm/boot/zImage arch/arm/boot/uImage

内存地址与处理器相关,在不同处理器上可能有差异 .

查看一个 uImage 映像文件的文件头信息

$ mkimage -l uImage
Image Name: Linux-2.6.35.3-571-gcca29a0-g191
Created: Tue Nov 17 11:57:47 2015
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2572336 Bytes = 2512.05 kB = 2.45 MB
Load Address: 40008000
Entry Point: 40008000

3)从内核源码直接生成 uImage

文件中给出了 uImage 的生成规则:

quiet_cmd_uimage = UIMAGE $@
    cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \
                -C none -a $(LOADADDR) -e $(STARTADDR) \
                -n 'Linux-$(KERNELRELEASE)' -d $< $@

生成 uImage 的编译命令为 make uImage

$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- -j8 uImage

4)编译内核模块

如果内核中有配置为的模块或者驱动,需要在编译内核后再通过 make modules 命
令编译这些模块或者驱动

$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- modules

编译得到的内核模块文件以“.ko”结尾,这些可以通过 insmod 命令插入到运行的内核中。

$ insmod kernel/drivers/net/bonding/bonding.ko

有的模块则可能编译后得到多个“.ko”文件,或者依赖于其它模块文件,且各文件插入还有顺序要求, 需要通过 make modules_install 命令安装模块 ,可将编译得到的全部模块安装到某一目录下,并且还会生成模块的依赖关系文件。

$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- INSTALL_MOD_PATH=/home/chenxibing/work/rootfs modules_install

安装后将在安装目录下生成“lib/modules/内核版本/”目录,将“lib/modules/内核版本/”复制到目标系统后根目录后,就可以用 modprobe 命令进行模块安装

#模块依赖关系
kernel/drivers/net/bonding/bonding.ko: 
kernel/drivers/usb/serial/usbserial.ko: 
kernel/drivers/usb/serial/ftdi_sio.ko:kernel/drivers/usb/serial/usbserial.ko 
# modprobe ftdi_sio

4.运行内核

得到 uImage 映像文件后,将 uImage 加载到内存地址 ep-0x40 处(0x40007fc0),通过 bootm 命令即可运行内核:

# tftp 40007fc0 uImage
# bootm 40007fc0

你可能感兴趣的