Linux 内核

内核

The Raspberry Pi 内核存储在 GitHub 中,可以在 github.com/raspberrypi/linux 查看;它遵循主分支 Linux内核。主分支 Linux 内核在不断更新;我们获取首页提到的内核的长期版本,并将更改集成到 Raspberry Pi 内核中。然后我们创建一个“next”分支,其中包含内核的不稳定端口;经过广泛的测试和讨论,我们将其推送到主分支。

更新您的内核

如果您使用标准的the Raspberry Pi操作系统 更新和升级过程,这将自动更新内核到最新的稳定版本。这是推荐的过程。但是,在某些情况下,您可能希望更新到最新的“前沿”或测试内核。只有当Raspberry Pi工程师建议您这样做时,或者只有在这个最新的软件中才有特定的功能时,您才应该这样做。

将代码合并到内核

可能有很多原因致使您想放一些东西到内核里面:

  • 你已经编写了一些特定于 Raspberry Pi 的代码,希望每个人都能从中受益

  • 您已经为设备编写了通用 Linux 内核驱动程序,并希望每个人都使用它

  • 您已经修复了一个通用内核错误

  • 您已经修复了特定于the Raspberry Pi的内核错误

最初,您应该派生 Linux存储库,并在您的构建系统上克隆它;这可以在Raspberry Pi上,也可以在用于交叉编译的Linux机器上。然后,您可以做出更改,测试它们,并将它们提交到您的分支中。 接下来,确定代码是否是特定于the Raspberry Pi:

  • 对于特定于 Raspberry Pi 的更改或错误修复,请向内核提交拉取请求。

  • 对于一般的 Linux 内核更改(即新驱动程序),需要先在上游提交这些更改。在上游提交并接受后,提交拉取请求,我们将收到它。

构建内核

操作系统附带的默认编译器和链接器被配置为构建在该操作系统上运行的可执行文件——它们是本地工具——但事实并非如此。交叉编译器被配置为为运行构建过程的目标之外的目标构建代码,使用它被称为交叉编译。

the Raspberry Pi内核的交叉编译很有用,原因有两个:

  • 它允许使用 64 位操作系统构建 32 位内核,反之亦然,并且

  • 即使是一台普通的笔记本电脑也可以比the Raspberry Pi本身更快地交叉编译the Raspberry Pi内核.

以下说明分为本机构建和交叉编译;选择适合您情况的部分 - 尽管两者之间有许多常见的步骤,但也存在一些重要差异。

在本地构建内核

在Raspberry Pi上,首先安装最新版本的 Raspberry Pi OS。然后启动您的the Raspberry Pi,登录并确保您已连接到互联网以允许您访问源代码。

首先安装 Git 和构建依赖项

sudo apt install git bc bison flex libssl-dev make

接下来获取源,这将需要一些时间:

git clone --depth=1 https://github.com/raspberrypi/linux

选择来源

上面的git clone命令将下载当前活动分支(我们正在构建 Raspberry Pi OS 映像的分支),没有任何历史记录。省略 --depth=1 将下载整个存储库,包括所有分支的完整历史记录,但这需要更长的时间并占用更多的存储空间。

要下载其他分支(同样没有历史记录),请使用以下 --branch 选项:

git clone --depth=1 --branch <branch> https://github.com/raspberrypi/linux

其中 <branch> 是您要下载的分支的名称。

有关可用分支的信息,请参阅原始 GitHub 存储库

内核配置

配置内核;除了默认配置外,您可能还希望 更详细地配置内核应用来自其他来源的补丁,以添加或删除所需的功能。

应用默认配置

首先,通过运行以下命令来准备默认配置,具体取决于您的the Raspberry Pi型号:

对于the Raspberry Pi 1、零和零W 以及the Raspberry Pi计算模块 1 默认(仅限 32 位)构建配置

cd linux
KERNEL=kernel
make bcmrpi_defconfig

适用于the Raspberry Pi 2、3、3+ 和零2W,以及the Raspberry Pi计算模块 3 和 3+ 默认 32 位构建配置

cd linux
KERNEL=kernel7
make bcm2709_defconfig

对于the Raspberry Pi 4 和 400,以及the Raspberry Pi计算模块 4 默认的 32 位构建配置

cd linux
KERNEL=kernel7l
make bcm2711_defconfig

适用于the Raspberry Pi 3、3+、4、400 和零2W 以及the Raspberry Pi计算模块 3、3+ 和 4 默认 64 位构建配置

cd linux
KERNEL=kernel8
make bcm2711_defconfig
自定义内核版本 LOCALVERSION

除了内核配置更改之外,您可能还希望调整 LOCALVERSION 以确保新内核不会收到与上游内核相同的版本字符串。这既澄清了您在 uname 的输出中运行自己的内核,又确保 /lib/modules 中的现有模块不会被覆盖。

为此,请更改 .config 中的以下行:

CONFIG_LOCALVERSION="-v7l-MY_CUSTOM_KERNEL"

您还可以以图形方式更改该设置,如 内核配置说明中所示。它位于 "常规设置"=>"本地版本 - 附加到内核版本"中。

构建内核

构建并安装内核、模块和DTB文件;此步骤可能需要 很长 时间,具体取决于所使用的the Raspberry Pi模型。 对于 32 位内核:

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

对于 64 位内核:

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
Note
在Raspberry Pi 2/3/4上,该 -j4 标志将工作分配给所有四个内核,大大加快了编译速度。

如果你现在重启,你的Raspberry Pi应该运行你新编译的内核!

交叉编译内核

首先,您需要一个合适的Linux交叉编译主机。我们倾向于使用Ubuntu由于Raspberry Pi OS也是Debian发行版,这意味着许多方面都是相似的,比如命令行。

您可以在Windows上使用VirtualBox(或VMWare)来完成此操作,也可以将其直接安装到您的计算机上。作为参考,你可以遵循 Wikihow 上的在线说明。

安装所需的依赖项和工具链

要构建用于交叉编译的源代码,请执行以下命令,确保您的计算机上有所需的依赖项:

sudo apt install git bc bison flex libssl-dev make libc6-dev libncurses5-dev

如果您发现您需要其他东西,请提交一个拉请求来更改文档。

为32位内核安装32位工具链
sudo apt install crossbuild-essential-armhf
为64位内核安装64位工具链
sudo apt install crossbuild-essential-arm64

获取内核源代码

要下载当前分支的最小源代码树,请运行:

git clone --depth=1 https://github.com/raspberrypi/linux

有关如何选择不同分支的说明,请参见上面的 选择源

编译源代码

输入以下命令来构建源和设备树文件:

[[32-bit-configs]] ===== 32-位 配置

对于Raspberry Pi 1、零和零W以及Raspberry Pi计算模块1:

cd linux
KERNEL=kernel
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcmrpi_defconfig

对于Raspberry Pi 2、3、3+和Zero 2 W,以及Raspberry Pi计算模块3和3+:

cd linux
KERNEL=kernel7
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2709_defconfig

对于Raspberry Pi 4和400以及Raspberry Pi计算模块4:

cd linux
KERNEL=kernel7l
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2711_defconfig

[[64-bit-configs]] ===== 64-位 配置

对于Raspberry Pi 3、3+、4、400和Zero 2 W,以及Raspberry Pi计算模块3、3+和4:

cd linux
KERNEL=kernel8
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2711_defconfig
配置构建
Note
为了在多处理器系统上加速编译,并在单处理器系统上获得一些改进,可以使用 -j n ,其中n是处理器的数量* 1.5。您可以使用 nproc 命令来查看您有多少个处理器。或者,请随意试验,看看什么有效!
对于所有32位版本
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs
对于所有64位版本
Note
请注意32位和64位图像目标之间的差异。
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- Image modules dtbs

直接安装到SD卡上

构建好内核后,您需要将它复制到您的Raspberry Pi上并安装模块;最好直接使用SD读卡器。

首先,在插入SD卡前后使用 lsblk 进行识别。您应该会得到类似这样的结果:

sdb
   sdb1
   sdb2

其中 sdb1FAT 文件系统(引导)分区, sdb2ext4 文件系统(根)分区。

首先安装它们,根据需要调整分区号:

mkdir mnt
mkdir mnt/fat32
mkdir mnt/ext4
sudo mount /dev/sdb1 mnt/fat32
sudo mount /dev/sdb2 mnt/ext4
Note
您应该根据您的设置适当调整驱动器号,例如,如果您的SD卡显示为 /dev/sdc ,而不是 /dev/sdb

接下来,将内核模块安装到 SD 卡上:

对于 32-位
sudo env PATH=$PATH make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=mnt/ext4 modules_install
对于 64-位
sudo env PATH=$PATH make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- INSTALL_MOD_PATH=mnt/ext4 modules_install

最后,将内核和设备树 blob 复制到 SD 卡上,确保备份旧内核:

对于 32-位
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
对于 64-位
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

另一种选择是将内核复制到同一位置,但使用不同的文件名 - 例如 kernel-myconfig.img - 而不是覆盖 kernel.img 文件。然后,您可以编辑该 config.txt 文件以选择the Raspberry Pi将启动的内核:

kernel=kernel-myconfig.img

这样做的好处是,将自定义内核与系统管理的库存内核映像和任何自动更新工具分开,并允许您在内核无法引导时轻松恢复到库存内核。.

最后,将卡插入the Raspberry Pi并启动它!

配置内核

Linux 内核是高度可配置的;高级用户可能希望修改默认配置以根据需要对其进行自定义,例如启用新的或实验性的网络协议,或启用对新硬件的支持。

配置通常通过 make menuconfig 界面完成。或者,您可以手动修改. .config 文件,但对于新用户来说,这可能会更加困难。

准备配置

menuconfig 工具需要 ncurses 开发头文件才能正确编译。这些可以用以下命令安装:

 sudo apt install libncurses5-dev

您还需要下载并准备内核源代码,如 构建指南中所述。特别是,请确保您已安装 默认配置

使用 menuconfig

设置好一切并准备就绪后,您可以按如下方式编译并运行该 menuconfig 实用程序:

 make menuconfig

如果要交叉编译 32 位内核:

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

或者,如果要交叉编译 64 位内核:

make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig

menuconfig 实用程序具有简单的键盘导航。经过简短的编译后,您将看到一个子菜单列表,其中包含您可以配置的所有选项;有很多,所以花点时间通读它们并熟悉它们。

使用箭头键进行导航,使用 Enter 键进入子菜单(由 ---> 指示),使用两次 Esc 键向上关卡或退出,使用空格键循环显示选项的状态。某些选项有多个选项,在这种情况下,它们将显示为子菜单,而 Enter 键将选择一个选项。您可以按 h 大多数条目以获取有关该特定选项或菜单的帮助。

抵制诱惑,第一次尝试就启用或禁用很多东西;破坏配置相对容易,所以从小处着手,熟悉配置和构建过程

保存更改

完成所需的更改后,按 Esc 键,直到系统提示您保存新配置。默认情况下,这将保存到 .config 文件中。您可以通过复制此文件来保存和加载配置。

修补内核

构建自定义内核时,您可能希望将补丁或补丁集合("补丁集")应用于 Linux 内核。

补丁集通常作为临时措施提供较新的硬件,在补丁应用于上游 Linux 内核("主线")之前,然后向下传播到 Raspberry Pi 内核源。但是,存在用于其他目的的补丁集,例如启用完全抢占式内核以供实时使用。

版本标识

在下载和应用补丁时检查您拥有的内核版本非常重要。在内核源目录中,运行 head Makefile -n 3 将显示源与以下版本相关的版本:

VERSION = 3
PATCHLEVEL = 10
SUBLEVEL = 25

在本例中,源码适用于 3.10.25 内核。您可以使用该 uname -r 命令查看您在系统上运行的版本。In this instance, the sources are for a 3.10.25 kernel. You can see what version you’re running on your system with the uname -r command.

应用补丁

应用修补程序的方式取决于修补程序可用的格式。大多数修补程序都是单个文件,并与 patch 实用程序一起应用。例如,让我们下载并使用实时内核补丁来修补我们的示例内核版本:

 wget https://www.kernel.org/pub/linux/kernel/projects/rt/3.10/older/patch-3.10.25-rt23.patch.gz
 gunzip patch-3.10.25-rt23.patch.gz
 cat patch-3.10.25-rt23.patch | patch -p1

在我们的例子中,我们简单地下载文件,解压缩它,然后使用 cat 工具和Unix管道将它传递给 patch

某些修补程序集以邮箱格式修补程序集的形式提供,排列为修补程序文件的文件夹。我们可以使用 Git 将这些补丁应用于我们的内核,但首先我们必须配置 Git 以在进行这些更改时让它知道我们是谁:

 git config --global user.name "Your name"
 git config --global user.email "your email in here"

完成此操作后,我们可以应用补丁:

 git am -3 /path/to/patches/*

如有疑问,请咨询补丁的分销商,他们应该告诉您如何应用它们。某些补丁集需要特定的提交才能进行修补;按照修补程序分发服务器提供的详细信息进行操作。

内核头文件

如果你正在编译内核模块或类似模块,你将需要 Linux 内核头文件。它们提供了编译与内核接口的代码时所需的各种函数和结构定义。

如果您已经从github克隆了整个内核,那么头文件已经包含在源代码树中了。如果你不需要所有额外的文件,可以从Raspberry Pi OS repo只安装内核头文件。

 sudo apt install raspberrypi-kernel-headers
Note
此命令可能需要相当长的时间才能完成,因为它会安装许多小文件。没有进度指示器。

发布新的内核版本时,您将需要与该内核版本匹配的标头。更新存储库以反映最新的内核版本可能需要几周时间。如果发生这种情况,最好的方法是按照 构建部分 中所述克隆内核。