標準的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
下載匹配的3.12.6的rt補丁包(https://www.kernel.org/pub/linux/kernel/projects/rt/3.12/ 注意,一定要和內核版本匹配)。
wget https://www.kernel.org/pub/linux/kernel/projects/rt/3.12/patches-3.12.6-rt9.tar.bz2
假設下載的兩個包都處於同一目錄,解壓kernel包
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,這次很順利。