Linux RT 内核 (5) - 移植 PREEMPT_RT 内核补丁
1. 前言
限于作者能力水平,本文可能存在谬误,因此而给读者带来的损失,作者不做任何承诺。
2. 移植 PREEMPT_RT 内核补丁
2.1 下载源码
本文以 Linux 4.14.336 为例说明 PREEMPT_RT 补丁的移植过程。首先到地址 linux-4.14.336.tar.xz 下载 linux-4.14.336 内核源码,然后到地址 patch-4.14.336-rt159.patch.xz PREEMPT_RT 内核补丁源码。
2.2 应用 PREEMPT_RT 内核补丁
分别解压 linux-4.14.336.tar.xz 和 patch-4.14.336-rt159.patch.xz,假定 linux-4.14.336.tar.xz 解压到目录 linux-4.14.336 下,patch-4.14.336-rt159.patch.xz 解压后到目录 patches。通过如下脚本 apply-patches.sh 将 patch-4.14.336-rt159.patch.xz 补丁应用到内核 linux-4.14.336.tar.xz:
#!/bin/bash
# 脚本用法说明
usage() {
echo "用法: $0 <补丁目录> <内核源码目录>"
echo " 补丁目录: 包含 .patch 文件的目录"
echo " 内核源码目录: 要应用补丁的 Linux 内核源码目录"
exit 1
}
# 检查参数数量
if [ $# -ne 2 ]; then
usage
fi
PATCH_DIR="$1"
KERNEL_DIR="$2"
# 检查目录是否存在
if [ ! -d "$PATCH_DIR" ]; then
echo "错误: 补丁目录 '$PATCH_DIR' 不存在"
exit 1
fi
if [ ! -d "$KERNEL_DIR" ]; then
echo "错误: 内核源码目录 '$KERNEL_DIR' 不存在"
exit 1
fi
# 将相对路径转换为绝对路径
get_abs_path() {
local dir="$1"
if [[ "$dir" != /* ]]; then
echo "$(cd "$dir" && pwd)"
else
echo "$dir"
fi
}
ABS_PATCH_DIR=$(get_abs_path "$PATCH_DIR")
ABS_KERNEL_DIR=$(get_abs_path "$KERNEL_DIR")
# 保存当前目录,以便脚本结束时返回
ORIGINAL_DIR="$(pwd)"
# 定义清理函数,确保退出时回到原目录
cleanup() {
cd "$ORIGINAL_DIR" || exit
}
# 设置陷阱,确保脚本退出时执行清理
trap cleanup EXIT
# 切换到内核源码目录
cd "$ABS_KERNEL_DIR" || {
echo "错误: 无法切换到内核源码目录 '$ABS_KERNEL_DIR'"
exit 1
}
# 查找并排序 .patch 文件
PATCH_FILES=$(find "$ABS_PATCH_DIR" -name "*.patch" -type f | sort)
# 检查是否找到 .patch 文件
if [ -z "$PATCH_FILES" ]; then
echo "警告: 在 '$ABS_PATCH_DIR' 中未找到 .patch 文件"
exit 0
fi
echo "找到 $(echo "$PATCH_FILES" | wc -l) 个补丁文件"
# 应用补丁
for patch_file in $PATCH_FILES; do
echo "正在应用补丁: $(basename "$patch_file")"
# 使用 git apply 应用补丁
if ! git apply --whitespace=nowarn "$patch_file"; then
echo "错误: 应用补丁 '$(basename "$patch_file")' 失败"
echo "已停止应用后续补丁"
exit 1
fi
done
echo "所有补丁已成功应用"
# 先建立 git 仓库才能应用补丁
$ cd linux-4.14.336
$ git init
$ git add -A
$ git commit -m "Initial commit."
$ cd ..
$ ./apply-patches.sh patches linux-4.14.336
也可以跳过补丁打入步骤,直接下载官方合并好的实时内核版本:
- 开发中的版本:https://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git
- 稳定版本:https://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-stable-rt.git
另外,现在的高版本内核更是在 upstream 内核直接集成了 RT 补丁,而不是独立维护了。
2.3 编译运行
笔者通过 QEMU 模拟 ARM 开发板,并辅以 ubuntu 的 rootfs 测试运行。先生成默认配置:
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- O=output vexpress_defconfig
然后通过命令
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- O=output menuconfig
选择内核抢占配置如下:

也即选择 CONFIG_PREEMPT_RT_FULL=y,然后编译:
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- O=output -j$(nproc)
最后用 QEMU 运行:
#!/bin/bash
sudo qemu-system-arm \
-M vexpress-a9 -smp 4 -m 512M \
-kernel linux-4.14.336/output/arch/arm/boot/zImage \
-dtb linux-4.14.336/output/arch/arm/boot/dts/vexpress-v2p-ca9.dtb \
-append "root=/dev/mmcblk0 rw rootfstype=ext4 console=ttyAMA0 page_owner=on" \
-sd rootfs/image/arm-ubuntu-16.04.img \
-serial stdio \
-net nic -net tap,ifname=tap0,script=no,downscript=no
# -nographic \
# -S -s
运行起来后像这样:
Ubuntu 16.04 LTS qemu-ubuntu ttyAMA0
qemu-ubuntu login: root
Password:
Welcome to Ubuntu 16.04 LTS (GNU/Linux 4.14.336-rt159+ armv7l)
* Documentation: https://help.ubuntu.com/
root@qemu-ubuntu:~# cat /proc/version
Linux version 4.14.336-rt159+ (lxj@lxj-virtual-machine) (gcc version 5.4.0 20160609 (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.9)) #1 SMP PREEMPT RT Mon Mar 9 15:55:15 CST 2026
root@qemu-ubuntu:~#
从 cat /proc/version 可以看到 PREEMPT RT 输出,说明这是 RT 内核版本。
3. 番外
这两天又在开源硬件 NanoPi-NEO-Core 上移植了一把 PREEMPT_RT 补丁,主要分为两步:
- 将内核从 4.14.111 升级到 4.14.336
- 在内核 4.14.336 适配 PREEMPT_RT 补丁 patches-4.14.336-rt159.tar.gz
系统起来后,uname -a 的输出如下:
root@NanoPi-NEO-Core:~# uname -a
Linux NanoPi-NEO-Core 4.14.336-rt159 #3 SMP PREEMPT RT Tue Mar 17 13:25:16 CST 2026 armv7l armv7l armv7l GNU/Linux

浙公网安备 33010602011771号