文章目录
ps:本篇涉及的Linux内核源码是针对于树莓派的
源码获取
-
Raspberry Pi · GitHub
-
使用命令:uname -r查看自己树莓派的是什么版本,选择合适的版本
-
- v8+:64位
- v8l+:32位
-
- 解压:unzip linux-rpi-6.1.yzip
源码目录树分析
-
使用tree命令分析源码文件可以知道整个源码有5116个目录,78967个文件
- Linux系统是一个开源的支持多平台多架构(如:ARM、X86、PowerPc……)的系统,可以移植性非常高。
- Linux内核编译出来的大小一般就几M的占用内存,整个源码很大是因为涵盖了多平台代码的结果。
- 正因为支持多平台多架构,其实很多代码并需要不参与编译,所以编译之前要配置,配置成适合的目标平台来用
-
内核源码结构
源码配置
配置源码的目的
- 驱动代码的编写的前提(驱动代码的编译)需要一个提前编译好的内核(编译内核前必须配置)
- 配置的最终目的会生成.config文件,该文指导makefile去把有用的东西组织成内核
配置方式
-
厂家配Linux内核源码,比如说买了树莓派,提供了树莓派Linux内核源码(源码里有厂家的config)
- cp 厂家.config拷贝成.config来使用
-
make menuconfig一项项配置,通常是基于厂家的config来配置
- make menuconfig一项项配置,通常是基于厂家的config来配置
- 自己来完成(一般厂家来做的事)
分别介绍32位arm和64位arm的配置步骤
linux源码中有很多工程
- 树莓派1的工程是bcmrpi_defconfig;
- 树莓派2、3的工程是bcm2709_defconfig。
- 树莓派4的工程是bcm2711_defconfig。
- 32位:arm-linux-gnueabihf-
- 64位:aarch64-linux-gnu-
32位(源码目录下进行)
-
配置config
-
运行:ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7l make bcm2711_defconfig
- arm:指定arm架构
- CROSS_COMPILE=arm-linux-gnueabihf-:指定编译器
- KERNEL=kernel7l:树莓派厂家要求的(树莓派1-3都是kernel7,树莓派4是kernel7l)
-
make bcm2711_defconfig:主要核心指令
- 此命令功能是获取bcm2711_defconfig的配置到 .config里。
-
运行:ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7l make bcm2711_defconfig
-
自定义配置(如果不需要则不用进行这一步)
- 运行:ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7l make menuconfig
-
这一步如果没有成功可能是没有安装ncurses库
- sudo apt-get install libncurses5-dev libncursesw5-dev
-
执行命令后出现界面(方向键切换,回车键选择或是进入子菜单)
-
-
-
驱动加载的两种方式
-
*(Y)编译进内核 zImage包含了驱动
-
M模块方式生成驱动文件,系统启动后,通过命令inmosd xxx.ko加载
-
补充
-
后面有箭头说明有子菜单 -
[ ]里面空的说明不编译进内核(选择性,不编译那么多进内核内核镜像就小,M模式也是让内核变小的一种方式)
-
-
-
-
编译
-
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7l make -j4 zImage modules dtbs
- arm:指定ARM架构
- CROSS_COMPILE=arm-linux-gnueabihf-:指定编译器
- KERNEL=kernel7l:树莓派1-3都是kernel7,树莓派4-32位kernel7l
- -j4指定4核编译(指定用多少电脑资源进行编译)
- zImage:生成内核镜像
- modules:驱动模块
- detbs:生成配置文件
-
成功后
-
内核源码目录下生成
- 真正的目标文件是zImage:在/arch/arm/boot路径下,需要将其打包成.img结尾的镜像文件
-
内核源码目录下生成
-
打包zImage文件
-
./scripts/mkknlimg arch/arm/boot/zImage ./kernel_new.img(在源码目录下进行)
- 成功后会在本目录生成一个kernel_new.img文件,这个文件就是要放到树莓派boot目录下的文件。
-
出现错误
-
原因:打包工具mkknlimg被淘汰了
-
解决1(已经验证)
- 重新下载源码Linux-rpi-4.14.y.zip(低版本的), 在文件夹scripts里找到打包工具mkknlimg拷贝到5.15版本的的scripts文件夹下
-
解决2(未验证,会报错没有python2)
-
tool_master工具包找到imagetool-uncompressed.py
- sudo ./(imagetool-uncompressed.py的绝对路径) /zImage(绝对路径)
-
-
-
-
拷贝相关文件
-
装有树莓派系统的sd卡有两个分区
-
一个是fat分区,是boot相关的内容,kernel的img文件就放在这个分区里(可以不用root权限操作)
-
一个是ext4分区,也就是系统的根目录分区(需要root权限操作)
-
-
将树莓派的SD卡拔出用读卡器连接ubuntu,并挂载
-
使用命令dmesg打印内核信息查看ubuntu将读卡器识别成sdb或是sdc亦或其他
-
sudo mount /dev/需要挂载的分区 挂载到的文件夹
sudo mount /dev/sdb1(这个不一定是sdb1,也有可能是sdc1,不能有/) data1 (这个是fat分区
sudo mount /dev/sdb2(这个不一定是sdb2,也有可能是sdc2,不能有/) data2 (这个是ext4分区
-
-
安装modules(涉及设备驱动文件:HDMI,USB,WIFI等等)
-
这一步很重要,如果内核更换了,设备文件没有更换,那么所有的设备驱动都是不能用的(设备驱动文件是有版本的,要和内核版本一致才能用)
- sudo ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7l make INSTALL_MOD_PATH=**/home/theone/Desktop/USB/**data2(绝对路径) modules_install
-
-
更新kernel.img文件
-
法一:前面已经用 mkknlimg 工具打包kernel_new.img文件了,把它复制到boot分区并配置使用即可(推荐使用这种)
- cp kernel_new.img /home/theone/Desktop/USB/data1/
- 编辑data1/config.txt文件。在最后一行加入kernel=kernel_new.img
-
法二:直接将kernel_new.img文件以
kernel7.img名字
复制到data1分区进行覆盖(这种方法最好要备份配置之前的树莓派kernel7.img文件)(不推荐使用这种)- cp kernel_new.img /home/theone/Desktop/USB/data1/kernel7.img
-
复制完之后进行校验
- md5sum kernel_new.img
- md5sum /home/theone/Desktop/USB/data1/kernel7.img
- 一致的话说明复制成功
-
法一:前面已经用 mkknlimg 工具打包kernel_new.img文件了,把它复制到boot分区并配置使用即可(推荐使用这种)
-
复制其他文件
- cp arch/arm/boot/dts/.*dtb /home/theone/Desktop/USB/data1
-
cp arch/arm/boot/dts/overlays/.
dtb
/home/theone/Desktop/USB/data1/overlays/ - cp arch/arm/boot/dts/overlays/README /home/theone/Desktop/USB/data1/overlays/
-
sudo umount mnt/data1
sudo umount mnt/data2
-
64位(源码目录下进行)
-
输入以下命令以构建源和设备树文件
-
cd 源文件名(来到获取的源文件目录)
KERNEL=kernel8
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2711_defconfig
-
cd 源文件名(来到获取的源文件目录)
-
使用配置构建
- make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- Image modules dtbs -j4
-
将树莓派的SD卡拔出用读卡器连接ubuntu,并挂载
-
使用命令sudo dmesg打印内核信息查看ubuntu将读卡器识别成sdb或是sdc亦或其他
-
-
在内核源码目录下
- mkdir mnt
- mkdir mnt/fat32
- mkdir mnt/ext4
- sudo mount /dev/sdb1 mnt/fat32
- sudo mount /dev/sdb2 mnt/ext4
-
-
-
将内核模块安装到 SD 卡上(挂载成功后执行)
- sudo env PATH=$PATH make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- INSTALL_MOD_PATH=mnt/ext4 modules_install
-
将内核和设备树 blob 复制到 SD 卡上,确保备份旧内核(我选择使用这一方法:将内核复制到同一位置,但使用不同的文件名而不是覆盖文件。然后,编辑文件config.txt以选择树莓派将启动的内核)
-
将编译生成的内核镜像拷贝到树莓派的fat32分区做为的内核命名为:kernel8_new.img
- sudo cp arch/arm64/boot/Image mnt/fat32/kernel8_new.img
-
拷贝其他文件
-
sudo cp arch/arm64/boot/dts/broadcom/*.dtb mnt/fat32/
-
sudo cp arch/arm64/boot/dts/overlays/
.dtb
mnt/fat32/overlays/ -
sudo cp arch/arm64/boot/dts/overlays/README mnt/fat32/overlays/
-
-
编辑文件mnt/fat32/config.txt,指定内核为新内核
-
-
补充:kernel=kernel8_new.img(
不能有多余的符号,空格也不能有,如上图所示是错误的没有指定内核成功的,如果还不行那就放在最后一行
)
-
补充:kernel=kernel8_new.img(
-
-
卸载
-
sudo umount mnt/fat32
sudo umount mnt/ext4
-
sudo umount mnt/fat32
-
结果
-
可能遇到的问题
-
- sudo apt-get install flex
-
错误: /bin/sh: 1: bision: not foung
- sudo apt-get install bison
-
- sudo apt-get install libssl-dev
参考