树莓派内核源代码保存在GitHub上github.com/raspberrypi/linux,可以看做是Linux主线内核代码的一个分支。树莓派内核源代码是从Linux主线的长期维护的稳定版本加上树莓派特有的改动形成的。树莓派的内核更新可以通过apt命令自动更新到最新的稳定版本。但是如果你需要使用到最新的非稳定版本或者指定版本或者要对内核进行裁剪或者修改内核代码。那么你就会需要对内核进行编译。
通过访问github找到树莓派内核源代码项目(方法见下载linux内核代码),通过https或者git下载你想要的版本的源代码到本地主机。
编译过成可以分成在本机上本地编译和交叉编译,本地编译指的是在目标主机上直接编译,编译完成后就在目标主机上直接运行,交叉编译是指在其它主机上编译,编译完成后再把编译出来的程序安装到目标主机上执行。在树莓派这里,我们可以采用本地编译与可以采用交叉编译,因为树莓派运行速度较慢,所以交叉编译在这里可以显著的提高编译速度。
启动树莓派后,输入如下命令安装编译环境
sudo apt install git bc bison flex libssl-dev make
然后通过https下载Linux内核代码后解决压或者通过git下载代码到/usr/src目录下,如下所示:
xxx@raspberrypi:/usr/src $ ls -l
total 16
drwxr-xr-x 27 root root 4096 Jun 5 13:56 linux-rpi-6.1.y
xxx@raspberrypi:/usr/src $ cd ./linux-rpi-6.1.y/
xxx@raspberrypi:/usr/src/linux-rpi-6.1.y $ ls -l
total 1012
drwxr-xr-x 24 root root 4096 Jun 4 19:39 arch
drwxr-xr-x 3 root root 12288 Jun 5 14:01 block
drwxr-xr-x 2 root root 4096 Jun 5 10:28 certs
-rw-r--r-- 1 root root 496 Jun 4 19:39 COPYING
-rw-r--r-- 1 root root 101639 Jun 4 19:39 CREDITS
drwxr-xr-x 4 root root 20480 Jun 5 13:25 crypto
drwxr-xr-x 86 root root 4096 Jun 4 19:39 Documentation
开始编译之前我们需要先对内核进行配置,让编译工程知道我们要编译的内核的目标主机架构等信息,编译工程才知道自己应该怎么编译。
xxx@raspberrypi:/usr/src $ cd ./linux-rpi-6.1.y/
xxx@raspberrypi:/usr/src $ KERNEL=kernel
xxx@raspberrypi:/usr/src $ sudo make bcmrpi_defconfig
xxx@raspberrypi:/usr/src $ cd ./linux-rpi-6.1.y/
xxx@raspberrypi:/usr/src $ KERNEL=kernel7
xxx@raspberrypi:/usr/src $ sudo make bcm2709_defconfig
xxx@raspberrypi:/usr/src $ cd ./linux-rpi-6.1.y/
xxx@raspberrypi:/usr/src $ KERNEL=kernel7l
xxx@raspberrypi:/usr/src $ sudo make bcm2711_defconfig
xxx@raspberrypi:/usr/src $ cd ./linux-rpi-6.1.y/
xxx@raspberrypi:/usr/src $ KERNEL=kernel8
xxx@raspberrypi:/usr/src $ sudo make bcm2711_defconfig
本文使用的是树莓派zero w,只支持32位内核,所以使用的是第一种配置。
自定义内核配置
待更新
加入内核补丁
待更新
修改当前目录下的.config文件里的
CONFIG_LOCALVERSION=“my_first_kernel”
xxx@raspberrypi:/usr/src/linux-rpi-6.1.y $ ls -a | grep config
.cocciconfig
.config----------------------------修改这个文件里的LOCAL配置项成你想要的任何字符串
Kconfig
这个可以在你后续运行中通过uname命令查询到你自己编译的Linux内核的版本号,也会让新的内核在/lib/modules目录下产生新的目录文件去放置新内核的模块,而不是直接覆盖。
这一步,我们将编译,安装内核,模块和设备树,因为树莓派性能比较差,所以这一步会花费非常长的时间,尤其是如果你使用的是树莓派的早期硬件版本的话,就更慢了。
32bit内核
make -j4 zImage modules dtbs
sudo make modules_install
sudo cp arch/arm/boot/dts/*.dtb /boot/
sudo cp arch/arm/boot/dts/overlays/*.dtb* /boot/overlays/
sudo cp arch/arm/boot/dts/overlays/README /boot/overlays/
sudo cp arch/arm/boot/zImage /boot/$KERNEL.img
64bit内核
make -j4 Image.gz modules dtbs
sudo make modules_install
sudo cp arch/arm64/boot/dts/broadcom/*.dtb /boot/
sudo cp arch/arm64/boot/dts/overlays/*.dtb* /boot/overlays/
sudo cp arch/arm64/boot/dts/overlays/README /boot/overlays/
sudo cp arch/arm64/boot/Image.gz /boot/$KERNEL.img
编译安装完成后,重启则已经用新编译的内核了。
这里以ubuntu为例,介绍如何对树莓派内核进行交叉编译
启动树莓派后,输入如下命令安装编译环境
sudo apt install git bc bison flex libssl-dev make libc6-dev libncurses5-dev
根据你编译的目标是32bit内核还是64bit内核选择安装不同的toolchain
sudo apt install crossbuild-essential-armhf
sudo apt install crossbuild-essential-arm64
然后通过https下载Linux内核代码后解决压或者通过git下载代码到/usr/src目录下,如下所示:
xxx@ubuntu:/usr/src $ ls -l
total 16
drwxr-xr-x 27 root root 4096 Jun 5 13:56 linux-rpi-6.1.y
xxx@ubuntu:/usr/src $ cd ./linux-rpi-6.1.y/
xxx@ubuntu:/usr/src/linux-rpi-6.1.y $ ls -l
total 1012
drwxr-xr-x 24 root root 4096 Jun 4 19:39 arch
drwxr-xr-x 3 root root 12288 Jun 5 14:01 block
drwxr-xr-x 2 root root 4096 Jun 5 10:28 certs
-rw-r--r-- 1 root root 496 Jun 4 19:39 COPYING
-rw-r--r-- 1 root root 101639 Jun 4 19:39 CREDITS
drwxr-xr-x 4 root root 20480 Jun 5 13:25 crypto
drwxr-xr-x 86 root root 4096 Jun 4 19:39 Documentation
开始编译之前我们需要先对内核进行配置,让编译工程知道我们要编译的内核的目标主机架构等信息,编译工程才知道自己应该怎么编译。
如果你的设备是Raspberry Pi 1, Zero 或者 Zero W 或者 Raspberry Pi Compute Module 1:
cd linux-rpi-6.1.y
KERNEL=kernel
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcmrpi_defconfig
如果你的设备是Raspberry Pi 2, 3, 3+ 或者 Zero 2 W 或者 Raspberry Pi Compute Modules 3, 3+:
cd linux-rpi-6.1.y
KERNEL=kernel7
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2709_defconfig
如果你的设备是Raspberry Pi 4 或者 400, 或者 Raspberry Pi Compute Module 4 :
cd linux-rpi-6.1.y
KERNEL=kernel7l
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2711_defconfig
如果你的设备是Raspberry Pi 3, 3+, 4, 400 或者 Zero 2 W, 或者 Raspberry Pi Compute Modules 3, 3+ 或者 4:
cd linux-rpi-6.1.y
KERNEL=kernel8
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2711_defconfig
本文使用的是树莓派zero w,只支持32位内核,所以使用的是第一种配置。
修改当前目录下的.config文件里的
CONFIG_LOCALVERSION=“-v7-MY_FIRST_KERNEL”
xxx@raspberrypi:/usr/src/linux-rpi-6.1.y $ ls -a | grep config
.cocciconfig
.config----------------------------修改这个文件里的LOCAL配置项成你想要的任何字符串
Kconfig
这个可以在你后续运行中通过uname命令查询到你自己编译的Linux内核的版本号,也会让新的内核在/lib/modules目录下产生新的目录文件去放置新内核的模块,而不是直接覆盖。
这一步,我们将编译,安装内核,模块和设备树,因为是交叉编译,交叉编译用的主要性能相对于树莓派而言都是非常非常高的了,所以这一步会花费的时间会比较短,8核 i7用-j12选项一般来说25分钟就可以编完了。
32bit内核
make -j4 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs
64bit内核
make -j4 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- Image modules dtbs
完成交叉编译后,需要将编译出来的内核拷贝到树梅莓里并安装内核模块。通过将SD读卡器插入编译主机的方式进行的操作会比较简单。下面就以这个为例进行说明。
将带有SD卡的SD卡读卡器插入主机,输入以下命令(注意,如果你的主机本来就有多个硬盘那么插入的SD卡可能显示的是sdc之类的,注意鉴别一下):
xxx@xx-PC:~$ lsblk -f | grep sdb
sdb
├─sdb1 vfat FAT32 bootfs CEE7-0DF0
└─sdb2 ext4 1.0 rootfs ebadab55-bd70-46a9-8f18-995c136fb5b2
sudo mkdir mnt
sudo mkdir mnt/fat32
sudo mkdir mnt/ext4
sudo mount /dev/sdb1 mnt/fat32
sudo mount /dev/sdb2 mnt/ext4
sudo env PATH=$PATH make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=mnt/ext4 modules_install
sudo env PATH=$PATH make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- INSTALL_MOD_PATH=mnt/ext4 modules_install
sudo cp mnt/fat32/$KERNEL.img mnt/fat32/$KERNEL-backup.img
sudo cp arch/arm/boot/zImage mnt/fat32/$KERNEL.img
sudo cp arch/arm/boot/dts/*.dtb mnt/fat32/
sudo cp arch/arm/boot/dts/overlays/*.dtb* mnt/fat32/overlays/
sudo cp arch/arm/boot/dts/overlays/README mnt/fat32/overlays/
sudo umount mnt/fat32
sudo umount mnt/ext4
sudo cp mnt/fat32/$KERNEL.img mnt/fat32/$KERNEL-backup.img
sudo cp arch/arm64/boot/Image mnt/fat32/$KERNEL.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/
sudo umount mnt/fat32
sudo umount mnt/ext4
退出SD卡,将SD卡插回树莓派,重启则可。
我们可以看到内核版本已经变成6.1.31my_first_kernel,也已经 更新了内核编译的时间。
xxx@raspberrypi:~ $ uname -a
Linux raspberrypi 6.1.31my_first_kernel #1 Mon Jun 5 20:48:53 CST 2023 armv6l GNU/Linux