标准的Linux 内核只能能够满足软中断的要求,为用户空间提供基本的Posix操作,但是不对固定的时间点做保证,PREEMPT_RT补丁解决了这一问题,它的实现技术包括:中断线程化(包括IRQ和softirq)、用Mutex取代spinlock、优先级继承和死锁检测、等待队列优先级化、大内核锁(BKL-Big Kernel Lock)可抢占等。通过这些达到提高实时性的目的。当然,代价是并发吞吐量的减少。
2. 打补丁
在linux-org上下载最新的stable kernel ,版本是3.12.6(https://www.kernel.org/) 。
wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.12.6.tar.xz
wget https://www.kernel.org/pub/linux/kernel/projects/rt/3.12/patches-3.12.6-rt9.tar.bz2
tar -xvf linux-3.12.6.tar.xz
对该内核源码打rt补丁
cd linux-3.12.6 && bzcat ../patch-2.6.33.7.2-rt30.bz2 | patch -p1
这里patch的参数取p1,原因很简单,解压patch-2.6.33.7.2-rt30.bz2后得到的补丁文件patch-3.12.6-rt9.patch中,有内容如下:
... - – - a/Documentation/sysrq.txt +++ b/Documentation/sysrq.txt …
p1的意思代表忽略第一层目录a和b,p0则不忽略目录,直接从当前目录开始,p2,3,4的以此类推。由于我们已进入linux-3.12.6内,所以使用p1。除了直接使用bz2包外,我们亦可先解压,在打补丁
patch -p1 < ../patch-3.12.6-rt9.patch
如果不想应用补丁,打算回退的,加-R参数:
patch -R -p1 < ../patch-3.12.6-rt9.patch
3. 一次失败的尝试
在linux-3.12.6目录下,执行make menuconfig
进入/Processor type and features/Preemption Model
选择Preemptible Kernel(Basic RT)
进入/Device Driver
去掉Staging drivers的勾选,保存这一配置。
在linux-3.12.6目录下执行 make -j2
在编译过程中有错误如下:
kernel/timer.c: In function ‘run_local_timers’:
kernel/timer.c:1463:2: error: implicit declaration of function ‘spin_do_trylock’ [-Werror=implicit-function-declaration]
kernel/timer.c:1474:2: error: implicit declaration of function ‘rt_spin_unlock_after_trylock_in_irq’ [-Werror=implicit-function-declaration]
修改linux-3.12.6/Makefile:372的KBUILD_CFLAGS配置项,去掉其中的-Werror-implicit-function-declaration选项,继续编译。
在最后链接vmlinux时又rt_spin_trylock和rt_spin_unlock_after_trylock_in_irq两函数的未定义引用错误,这两个函数的定义在linux-3.12.6/kernel/rtmutex.c中,make先将其编为rtmutex.o,再链入built-in.o。执行strings rtmutex.o | grep rt_spin_trylock
和strings rtmutex.o | grep rt_spin_unlock_after_trylock_in_irq都没有发现相关符号,果然,在rtmutex.c中发现,编译这两个函数需要打开CONFIG_PREEMPT_RT_FULL开关,在linux-3.12.6/Makefile:370的KBUILD_CPPFLAGS配置项中加入-D
CONFIG_PREEMPT_RT_FULL
,继续编译
本以为现在可以一帆风顺了,不了接下去又进入一个死圈,原来CONFIG_PREEMPT_RT_FULL
打开后,影响了struct mutex的定义,使得相当多的函数无法编译,虽然试过很多办法,但都无法彻底解决。
4. 通过
重新make menuconfig
,进入/Processor type and features/Preemption Model
受CONFIG_PREEMPT_RT_FULL
这个开关提示,将选项改为Fully Preemptible Kernel (RT) , 保存配置
重新make,这次很顺利。