Linux内核编译并移植至ARM平台
- Linux系统相关概念
- 操作系统的启动过程
- 获取树莓派源码
- Linux内核源代码目录树结构
- 树莓派Linux源码配置
- 树莓派Linux内核编译
- 移植内核至树莓派
Linux系统相关概念
操作系统的启动过程
-
x86,Intel的启动过程: 电源上电 -> BIOS -> Windows内核 -> C盘,D盘 -> 应用程序启动(QQ等)
-
嵌入式产品(Linux系统)启动过程: 电源上电 -> BootLoader -> Linux内核 ->文件系统 -> 应用程序
-
安卓的启动过程: 电源上电 -> fastBoot/Bootloader -> linux内核 -> 文件系统 -> 虚拟机 -> HOME应用程序 -> 通过图标打开某APP
获取树莓派源码
1. 通过指令查看树莓派的内核版本号:
uname -r
内核版本号:
2. 下载树莓派对应内核源码
通过 树莓派官网 下载源码,并将其拷贝到Ubuntu并解压
解压命令:
unzip linux-rpi-4.14.y
Linux内核源代码目录树结构
-
arch: 包含和硬件体系结构相关的代码,每种平台占一个相应的目录。和32位PC相关的代码存放在i386目录下,其中比较重要的包括kernel(内核核心部分)、mm(内存管理)、math-emu(浮点单元仿真)、lib(硬件相关工具函数)、boot(引导程序)、pci(PCI总线)和power(CPU相关状态)。
-
block: 部分块设备驱动程序。
-
crypto: 常用加密和散列算法(如AES、SHA等),还有一些压缩和CRC校验算法。
-
Documentation: 关于内核各部分的通用解释和注释。
-
drivers: 设备驱动程序,每个不同的驱动占用一个子目录。
-
fs: 各种支持的文件系统,如ext、fat、ntfs等。
-
include: 头文件,其中,和系统相关的头文件被放置在linux子目录下。
-
init: 内核初始化代码(注意不是系统引导代码)。
-
ipc: 进程间通信的代码。
-
kernel: 内核的最核心部分,包括进程调度、定时器等,和平台相关的一部分代码放在arch/*/kernel目录下。
-
lib: 库文件代码。
-
mm: 内存管理代码,和平台相关的一部分代码放在arch/*/mm目录下。
-
net: 网络相关代码,实现了各种常见的网络协议。
-
scripts: 用于配置内核文件的脚本文件。
-
security: 主要是一个SELinux的模块。
-
sound: 常用音频设备的驱动程序等。
-
usr: 实现了一个cpio。
树莓派Linux源码配置
-
当我们工作中要进行驱动代码的编写,编写完以后要进行编译,要进行驱动代码的编译就必须要一个提前编译好的内核,编译内核就必须要先配置。
-
配置的最终目标会生成 .config文件,该文件指导Makefile去把有用东西组织成内核。 厂家配linux内核源码,比如说买了树莓派,树莓派linux内核源码:使用源码里自带的config。
其中Linux源码配置有三种方式:
- 方式一:厂家会配linux内核源码,厂家会提供对于芯片的内核源码,拷贝厂家的.cinfig文件进行配置
- 方式二:make menuconfig 一项项配置 ,通常是基于厂家的config来配置
- 方式三:完全自己来
其中编译Linux源码需要先安装好arm-linux交叉编译工具链。
其中交叉编译工具链的安装参考以下博文:交叉编译工具链的安装及带wiringPi库的交叉编译实现
方式一:拷贝厂家提供的config文件
执行命令,查看厂家给的配置文件
cd linux-rpi-4.14.y/
find . -name *_defconfig
find . -name *_defconfig|grep bcm2709
内核配置:
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make bcm2709_defconfig
- 指定ARM架构 : ARCH=arm
- 指定编译器 : CROSS_COMPILE=arm-linux-gnueabihf-
- 树莓派 : KERNEL=kernel7
- 主要核心指令 : make bcm2709_defconfig
方式二:make menuconfig
一项项配置,常是基于厂家的config来配置,首先要安装必要的库:
sudo apt-get install bc
sudo apt-get install libncurses5-dev libncursesw5-dev
sudo apt-get install zlib1g:i386
sudo apt-get install libc6-i386 lib32stdc++6 lib32gcc1 lib32ncurses5
安装完后执行以下配置指令:
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make menuconfig
然后根据自己的需要来剪裁内核,按需配置
驱动两种加载方式:
-
[*] 编译进内核 zImage包含了驱动
-
[M] 模块方式生成驱动文件xxx.ko 系统启动后,通过命令inmosd xxx.ko 加载
[ * ] 和< M >是驱动加载的两种方式,可以按空格键进行加载方式的切换。
[ ] :表示略过的,不参与编译,也就是需要裁剪的东西
方式三:完全自己来: 配置完内核后就可以进行内核的编译了。
树莓派Linux内核编译
编译指令:
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make -j4 zImage modules dtbs
此过程较慢,大约要20多分钟左右
- -j4: 指定用多少电脑资源进行编译
- zImage: 生成内核镜像
- modules: 要生成驱动模块
- dtbs: 生成配置文件
编译成功后,看到源码树目录多了vmlinux,失败则无此文件。成功后,目标zImage镜像arch/arm/boot底下
移植内核至树莓派
STEP 1:打包zImage文件
- 用mkknlimg 工具打包zImage 文件,将生成的zImage打包成树莓派可用的 xxx.img 比如 kernel_new.img
./scripts/mkknlimg arch/arm/boot/zImage ./kernel_new.img
STEP 2:挂载U盘
-
插入带有树莓派系统的内存卡的读卡器并挂载到虚拟机,并输入
dmesg
命令后出现sda1和sda2表示连接成功 -
在根目录新建两个文件夹data1、data2并将U盘里的内容挂载到这两个文件夹中
mkdir data1 data2 sudo mount /dev/sdb1 data1 sudo mount /dev/sdb2 data2
-
sdb1、sdb2 分别是树莓派SD卡的两个分区
- sdb1即data1是fat分区,是boot相关的内容,kernel的img文件在此分区
- sdb2即data2是ext4分区,也就是系统的根目录分区。(cd /进入的就是系统的根目录
-
通过挂载U盘,data1 和 data2 文件夹内就有了U盘内部的数据
STEP 3 :安装modules:
- 用于安装设备驱动文件,像无线网卡,IIC等驱动设备,进入树莓派源码树目录键入
注意:这里要将【ext4】改为自己具体的绝对路径sudo ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make INSTALL_MOD_PATH=[ext4] modules_install
sudo ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make INSTALL_MOD_PATH=/home/yuanjl/data2 modules_install
STEP 4:更新 kernel.img 文件
- 因为之前用 mkknlimg 工具打包了kernel_new.img文件,只要把它复制到fat分区(data1)并配置使用即可,防止刷机失败,首先备份之前的kernel.img 文件 ,进入挂载fat分区(data1)文件键入下列命令:
cp kernel7.img kernel7OLD.img
- 将之前在源码树目录生成的kernel_new.img拷贝到fat分区(data1)并替代之前的kernel7.img
cp kernel_new.img /home/yuanjl/data1/kernel7.img
- 拷贝完成后需要校验md5值,如果两文件的md5值不一样则需要重新拷贝。
md5sum /home/zh/SYSTEM/linux-rpi-4.14.y/kernel_new.img md5sum kernel7.img
STEP 5:在源码树中复制其它配置文件到fat分区(data1)
cp arch/arm/boot/dts/.*dtb* /home/yuanjl/data1
cp arch/arm/boot/dts/overlays/.*dtb* /home/yuanjl/data1/overlays/
cp arch/arm/boot/dts/overlays/README /home/yuanjl/data1/overlays/
STEP 6: 将配置玩的内存卡放入树莓派中键入uname -r查看更换后的内核版
参考博文:
1. 树莓派Linux内核配置
2. 树莓派-内核开发-说明 下载代码 编译 替换内核
3. Linux内核源代码目录树结构
4. 配置、编译Linux内核适合树莓派相关操作
5. 树莓派——配置Linux内核适合树莓派