10.Linux内核的编译
这儿的Linux内核指的是Kernel,或则称内核也是指的Kernel
10.1.为何要自己编译Kernel
其实我们提供的内核早已支持绝大多数功能了虚拟主机 linux,并且对于一些须要订制功能的顾客来说不一定有她们须要的功能配置,所以本章将讲解怎样配置与编译内核
这儿提供一个简单的测量工具查询该内核配置的情况:
1 2 3
sudo wget https://raw.githubusercontent.com/moby/moby/master/contrib/check-config.sh
sudo chmod 755 ./check-config.sh
./check-config.sh
可以看见配置了的内容
没有启动的到kernel里进行配置启动即可
10.2.下载安装编译镜像系统
使用平台:Ubuntu18.04.5LTS版本
可以使用我们提供的虚拟机镜像
也可以自己下载ubuntu18.04.5LTS官方镜像搭建
10.3.安装编译工具和依赖
编译内核之前须要安装必要的环境工具。
1
sudo apt install make gcc-arm-linux-gnueabihf gcc bison flex libssl-dev dpkg-dev lzop vim
10.4.获取kernel
10.4.1.下载源代码
有三个方式获取Kernel源码,一个是Kernel官方内核源码,一个是NXP官方的kernel源码,一个是经过我们更改适配我们板子的kernel源码,我们这儿使用我们提供的源码为例,对官方源码感兴趣的男子伴也可以下载来学习配置。我们的kernel是按照NXP官方提供的kernel订制的,NXP的kernel是按照kernel官方某一版本进行芯片适配的。我们作为嵌入式开发者,通常只须要使用芯片厂商适配好的kernel进行开发即可,对于从kernel官方下载新版原本配置这是芯片厂商做的事情,感兴趣的伙伴也可以按照NXP官方提供的芯片指南进行适配新版本的kernel。因为imx6ull这款芯片较为常用所以NXP官方将适配补丁递交给了kernel官方,这样kernel官方基本每一个版本都适配了这款芯片新版本的kernel官方的kernel也是可以直接编译来使用的。
Kernel官方内核源码:
NXP内核源码:
EBF内核源码:
使用我们提供的
1
git clone https://github.com/Embedfire/ebf_linux_kernel.git
一般一个内核库房常常维护着不同分支的内核源码,步入库房目录下可通过命令查看及切换内核分支
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
#查看uboot分支 git branch -a #打印消息如下,默认为master主分支。 * ebf_4.1.19_imx remotes/origin/HEAD -> origin/ebf_4.1.19_imx remotes/origin/ebf_4.1.15_imx remotes/origin/ebf_4.19.35_imx6ul remotes/origin/ebf_4.19_imx remotes/origin/ebf_4.19_imx_timeout_15S_PMIC remotes/origin/ebf_4.19_star remotes/origin/ebf_5.10.25_rk3328 remotes/origin/ebf_5.4.47_imx8mmini remotes/origin/master remotes/origin/test #切换ebf_4.19.35_imx6ul分支 git checkout ebf_4.19.35_imx6ul #打印消息如下 Checking out files: 100% (63998/63998), done. Branch 'ebf_4.19.35_imx6ul' set up to track remote branch 'ebf_4.19.35_imx6ul' from 'origin'. Switched to a new branch 'ebf_4.19.35_imx6ul' #重新查看当前分支 qinghui@ebf-dev:~/embedfire/ebf_linux_uboot$ git branch ebf_4.1.15_imx * ebf_4.19.35_imx6ul
也可以在下载时指定分支,如下所示
1
git clone -b ebf_4.19.35_imx6ul https://github.com/Embedfire/ebf_linux_kernel.git
10.5.kernel工程结构剖析
学习一个软件,尤其是开源软件,首先应当从剖析软件的工程结构开始。一个好的软件有良好的工程结构,对于读者学习和理解软件的构架以及工作流程都有挺好的帮助。
ebf_6ull_linux内核源码目录如下
arch COPYING drivers init kernel make_deb.sh README sound block CREDITS firmware ipc lib Makefile samples tools build_image crypto fs Kbuild LICENSES mm scripts usr certs Documentation include Kconfig MAINTAINERS net security virt
我们可以看见Linux内核源码目录下是有特别多的目录,且目录下也有特别多的文件,下边我们简单剖析一下这种目录的主要作用。
arch:主要包含和硬件体系结构相关的代码,如arm、x86、MIPSlinux内核源代码,PPC,每种CPU平台占一个相应的目录,比如我们使用的imx系列CPU就在arch/arm/mach-imx目录下,Linux内核目前早已支持30种左右的CPU体系结构。arch中的目录下储存的是各个平台以及各个平台的芯片对Linux内核进程调度、内存管理、中断等的支持,以及每位具体的SoC和电路板的板级支持代码。
block:在Linux中block表示块设备(以块(多个字节组成的整体,类似于磁道)为单位来整体访问),例如说SD卡、Nand、硬盘等都是块设备,block目录下放的是一些Linux储存体系中关于块设备管理的代码。
crypto:这个目录下储存的是常用加密和散列算法(如md5、AES、SHA等),还有一些压缩和CRC校验算法。
Documentation:内核各部份的文档描述。
drivers:设备驱动程序,上面列举了linux内核支持的所有硬件设备的驱动源代码,每位不同的驱动占用一个子目录,如char、block、net、mtd、i2c等。
fs:fs就是filesystem,上面包含Linux所支持的各类文件系统,如EXT、FAT、NTFS、JFFS2等。
include:目录包括编译核心所须要的大部份头文件,比如与平台无关的头文件在include/linux子目录下,与cpu构架相关的头文件在include目录下对应的子目录中。
init:内核初始化代码,这个目录下的代码就是linux内核启动时初始化内核的代码。
ipc:ipc就是interprocesscommuication,进程间通讯,该目录下都是linux进程间通讯的代码。
kernel:kernel就是Linux内核,是Linux中最核心的部份,包括进程调度、定时器等,而和平台相关的一部份代码放到arch//kernel目录下。
lib:lib是库的意思linux内核源代码,lib目录下储存的都是一些公用的有用的库函数,注意这儿的库函数和C语言的库函数不一样的,由于在内核编程中是不能用C语言标准库函数的,所以须要使用lib中的库函数,除此之外与处理器结构相关的库函数代码被置于arch/*/lib/目录下。
mm:目录包含了所有独立于cpu体系结构的显存管理代码,如页式储存管理显存的分配和释放等,而与具体硬件体系结构相关的显存管理代码坐落arch/*/mm目录下,比如arch/arm/mm/fault.c。
net:网路合同栈相关代码,net目录下实现各类常见的网路合同。
scripts:这个目录下全部是脚本文件,这种脚本文件不是linux内核工作时使用的,而是用了配置编译linux内核的。
security:内核安全模型相关的代码,譬如最有名的SELINUX。
sound:ALSA、OSS音频设备的驱动核心代码和常用设备驱动。
usr:实现用于打包和压缩的cpio等。
此处仅列举一些常见的目录。
10.6.内核配置选项
Linux内核的配置系统由三个部份组成,分别是:
读者假如想看我们提供的配置文件npi_v7_defconfig中更改了哪些地方,可以通过makemenuconfigKCONFIG_CONFIG=arch/arm/configs/npi_v7_defconfigARCH=armCROSS_COMPILE=arm-linux-gnueabihf-命令来查看我们的配置,makemenuconfig是一个基于文本选择的配置界面,推荐在字符终端下使用,而这个配置文件为npi_v7_defconfig此时就可以看见在npi_v7_defconfig的配置选择,可以通过鼠标的”上”、”下”、”左”、”右”、”回车”、”空格”、”?”、”ESC”等按钮进行选择配置,具体见:
1 2 3 4 5
#使用图形界面配置需要额外安装 libncurses-dev sudo apt install libncurses-dev #执行命令 make menuconfig KCONFIG_CONFIG=arch/arm/configs/npi_v7_defconfig ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
例如我们选择配置我们开发板的ds1818bb2020驱动:ds1818bb2020,假如读者找不到这个配置选项在那里,可以使用makemenuconfig中的搜索功能,在中文输入法状态下按下”/”则可以进行搜索,输入”ds1818bb2020”找到改配置选项的位置,当输入错误时,可使用Ctrl+退格键删掉输入。具体见:
从图中可以很显著看出ds1818bb2020配置选项坐落->DeviceDrivers选项下的->EmbedfireModules下的->EmbedfireModules(EBF_MODULE[=y])的选项中,虽然也可以按下"1"直接可以定位到对应的选项,之后选中以下内容即可,具体见图:
可使用y、n、m键修改ds1818bb2020驱动的配置时,其中y表示编译进内核中,m表示编译成模块,n表示不编译。也可使用空格选择ds1818bb2020驱动的配置选项。
想要配置其他的驱动也是这么。
10.7.kernel编译
编译Kernel有两种方式,一种是编译较为通用的zImage,常用于建立成镜像固件。另一种则是编译成deb安装包,将其下载到板子上安装即可更新Kernel。
10.7.1.编译内核zImage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
#清除之前编译环境 make mrproper #编译内核 make ARCH=arm npi_v7_defconfig make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j8 #编译成功后将打印以下信息。 ....... LD [M] sound/soc/fsl/snd-soc-fsl-esai.ko LD [M] sound/soc/fsl/snd-soc-fsl-micfil.ko LD [M] sound/soc/fsl/snd-soc-fsl-rpmsg-i2s.ko LD [M] sound/soc/fsl/snd-soc-fsl-sai.ko LD [M] sound/soc/fsl/snd-soc-fsl-ssi.ko LD [M] sound/soc/fsl/snd-soc-imx-audmux.ko LD [M] sound/soc/fsl/snd-soc-imx-wm8960.ko LD [M] sound/soc/fsl/snd-soc-fsl-utils.ko LD [M] sound/soc/generic/snd-soc-simple-card-utils.ko LD [M] sound/soc/generic/snd-soc-simple-card.ko LD [M] sound/soc/generic/snd-soc-simple-scu-card.ko LD [M] sound/soc/snd-soc-core.ko LD [M] sound/usb/snd-usbmidi-lib.ko LD [M] sound/usb/snd-usb-audio.ko AS arch/arm/boot/compressed/bswapsdi2.o AS arch/arm/boot/compressed/piggy.o LD arch/arm/boot/compressed/vmlinux OBJCOPY arch/arm/boot/zImage Kernel: arch/arm/boot/zImage is ready
编译得到的zImage内核在arch/arm/boot目录下,设备树在arch/arm/boot/dts目录下设备树分为emmc版本imx6ull-mmc-npi.dtb以及nand版本imx6ull-nand-npi.dtb。
zImage生成阐述
通过arm-linux-gnueabihf-ld命令将vmlinux.ldshead.opiggy.omisc.odecompress.ostring.ohyp-stub.olib1funcs.oashldi3.obswapsdi2.o链接成vmlinux
再通过arm-linux-gnueabihf-objcopy命令将vmlinux以bin格式输出到zImage,期间删掉了comment等信息
10.7.2.编译内核deb安装包
想要编译内核的deb安装包,以sudo权限运行野火提供的make_deb.sh脚本即可,我们也推荐使用这样的编译形式编译内核,建立下来的deb安装包可直接使用sudodpkg-ixxx.deb命令安装在鲁班猫系统上,之后重启使用cat/proc/version查看内核是否更新。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
sudo ./make_deb.sh #编译成功打印消息如下 INSTALL debian/headertmp/usr/include/linux/sunrpc/ (1 file) INSTALL debian/headertmp/usr/include/linux/tc_act/ (15 files) INSTALL debian/headertmp/usr/include/linux/tc_ematch/ (5 files) INSTALL debian/headertmp/usr/include/linux/usb/ (13 files) INSTALL debian/headertmp/usr/include/linux/wimax/ (1 file) INSTALL debian/headertmp/usr/include/asm/ (38 files) dpkg-deb: 正在 '../linux-headers-4.19.35-carp-imx6_1stable_armhf.deb' 中构建软件包 'linux-headers-4.19.35-carp-imx6'。 dpkg-deb: 正在 '../linux-libc-dev_1stable_armhf.deb' 中构建软件包 'linux-libc-dev'。 dpkg-deb: 正在 '../linux-image-4.19.35-carp-imx6_1stable_armhf.deb' 中构建软件包 'linux-image-4.19.35-carp-imx6'。 dpkg-genbuildinfo --build=binary dpkg-genchanges --build=binary >../linux-upstream_1stable_armhf.changes dpkg-genchanges: 警告: 控制文件声明了包 linux-image-4.19.35-carp-imx6-dbg 但它却不在文件列表中 dpkg-genchanges: info: binary-only upload (no source code included) dpkg-source --after-build build dpkg-buildpackage: info: binary-only upload (no source included) make[1]: 离开目录“/home/qinghui/embedfire/ebf-image-builder/ebf_linux_kernel/build_image/build”
构成生成的deb包在内核源码/build_image目录下。
10.8.镜像组成
NXP官方镜像(后简称官方镜像)与鲁班猫镜像(后简称lubancat),我们将kernel学linux有前途吗,dtb,dtbo打包进了rootfs内,这样更为通用且更换其中怎么一部份只需将文件替换即可。官方镜像则是烧录指定地址对于不同芯片储存的地址是不同的不利于移植于其他芯片。
10.9.内核的烧录
详尽可参考Linux内核的烧写