如何给嵌入式Linux打实时补丁?

1. 实时系统分类

            

        实时系统可以分为硬实时(Safety-Critical,低延时,比如几十个us内)和软实时(几百个us~几个/几十个ms),硬实时通常跟高确定性、可靠性要求同时出现,如果达不到,可能会造成重大生命或者财产损失,比如说航天飞控、汽车制动系统、精密仪器等都有较高的硬实时要求。对于软实时,可靠性要求没那么高,即使出现了延迟,造成的损失可控,比如说音频失真,视频不顺畅。

 

2.已有方案

        

        Linux 本身已经有硬实时的方案,比如来自风河的 RT Linux,或者西班牙一家研究所的 XtratuM + PartiKle,还有其他的比如 Xenomai,RTAI 等。另外,内核官方还有完全抢占内核(Preempt-RT Linux)的支持,这个在某些情况下也达到了硬实时要求,改补丁现在有OSADL维护。        

        然后就是各种优化,包括驱动(irq, preempt disable), spin lock 等使用,中断函数线程化,mdelay 替换为 usleep_range() 等。优化时需要用到很多工具,比如 Ftrace, Perf, Cyclictest, Oscilloscope 等。

        硬件本身的低延迟设计、可靠性设计等也会严重影响系统的实时性,比如说 ARM Cortex A/R/M 三系中的 R 就是专为高端嵌入式实时系统设计的,在中断行为方面做了优化。

 

3.OSADL方案

1)下载内核源代码和实时抢占补丁包

以内核2.6.31.5为例: linux-2.6.31.5 and patch-2.6.31.5-rt17:

# cd /usr/src/kernels
# wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.31.5.tar.bz2
# wget http://www.kernel.org/pub/linux/kernel/projects/rt/patch-2.6.31.5-rt17.bz2

解压:

# tar -jxvf linux-2.6.31.5.tar.bz2

重命名目录:

# mv linux-2.6.31.5 linux-2.6.31.5-rt17

打补丁:

# bunzip2 patch-2.6.31.5-rt17.bz2
# cd linux-2.6.31.5-rt17
# patch -p1 <../patch-2.6.31.5-rt17

 

2)使用 ketchup脚本

# cd /usr/src/kernels
# mkdir tmp
# cd tmp
# ketchup -r -G 2.6.31.5-rt17

可以去下面的网址下载Matt Mackall's 和 Steven Rostedt 的 ketchup 脚本: http://people.redhat.com/srostedt/rt/tools/ketchup-0.9.8-rt3. 

记得修改权限:

# wget -O /usr/local/bin/ketchup http://people.redhat.com/srostedt/rt/tools/ketchup-0.9.8-rt3
# chmod +x /usr/local/bin/ketchup

 

3)配置和编译内核

打完补丁,并编译后,将/boot/config-`uname -r`文件拷过来,成为 .config:

# cp /boot/config-`uname -r` .config

开始配置内核:

# make menuconfig

找到以下属性:

Processor type and features  --->
     Preemption Mode (Complete Preemption (Real-Time))  --->

比如,在"kernel hacking"设置里有Debug, trace and diagnostic 等:

Kernel hacking  --->
  [*] Tracers  --->
     --- Tracers
     [*]   Kernel Function Tracer
     [*]   Interrupts-off Latency Tracer
     [*]     Interrupts-off Latency Histogram
     [*]   Preemption-off Latency Traver
     [*]     Preemption-off Latency Histogram
     [*]   Scheduling Latency Tracer
     [*]     Scheduling Latency Histogram
     [*]   Missed timer offsets histogram

这些设置,只适用于调试和评估。在系统投入生产前最好把它们都禁掉。 然而,调度延迟和丢失的定时器抵消了直方图,只是轻微地干扰了系统,因此可以用来在生产条件下连续记录唤醒延迟。无论如何,请将stack overflow检查禁掉,因为它可能会导致附加延迟。

Kernel hacking  --->
     [ ] Check for stack overflows

继续编译和安装模块:

# make
# make modules_install install

系统重启后,新的内核将会出现在启动菜单里。

如果你的机器是多核的,请确保在make时使用-j 开关,这里jobs等于CPU核的个数的两倍。这个开关将加快你的内核编译速度。

4)使用和测试实时补丁

首先确认内核版本中含有PREEMPT 和 RT标志:

uname -v
#42 SMP PREEMPT RT Fri Nov 6 18:55:29 CET 2009

为了使用内置诊断工具,必须mount debug文件系统。这可以通过下面的方式:

# mount -t sysfs nodev /sys
# mount -t debugfs nodev /sys/kernel/debug

或者在文件/etc/fstab中添加下面的命令行,使得系统在启动时能自动mount debug文件系统。

nodev /sys sysfs defaults 0 0
nodev /sys/kernel/debug debugfs defaults 0 0

注:在早期内核版本里,内置诊断工具一般都是在proc文件系统里。

每个CPU的唤醒延迟直方图可以用以下方式查看(注意必须是在打完实时补丁之后才能看到):

# ls /sys/kernel/debug/tracing/latency_hist/wakeup_latency/CPU?

从版本 2.6.2.31 开始, 文件位于下面的路径:

# ls /sys/kernel/debug/tracing/latency_hist/wakeup/CPU?

# grep -v " 0$" /sys/kernel/debug/tracing/latency_hist/wakeup*/CPU0
#Minimum latency: 0 microseconds.
#Average latency: 7 microseconds.
#Maximum latency: 39 microseconds.
#Total samples: 7069336
#There are 0 samples greater or equal than 10240 microseconds
#usecs           samples
   0             249884
   1             120023
   2             338781
   3             197834
   4             210872
   5             150366
   6              45870
   7            1053204
   8             564637
   9             273756
  10             190432
  11             483611
  12             328509
  13              44716
  14              72925
  15              59304
  16              28927
  17              10836
  18               2821
  19                543
  20                110
  21                 82
  22                 63
  23                 61
  24                 32
  25                 21
  26                  9
  27                  4
  28                  3
  29                  1
  30                  3
  31                  2
  32                  4
  33                  2
  39                  1

默认直方图和内核函数跟踪功能都是被禁止的,要打开它们,比如唤醒延迟直方图,输入以下命令:

echo 1 >/sys/kernel/debug/tracing/latency_hist/enable/wakeup

为了重置直方图,可以使用下面的脚本:

#!/bin/sh
TRACINGDIR=/sys/kernel/debug/tracing
HISTDIR=$TRACINGDIR/latency_hist

if test -d $HISTDIR
then
 cd $HISTDIR
 for i in `find . | grep /reset$`
 do
   echo 1 >$i
 done
fi

也可以到内核文档里找到一些资料: Documentation/trace/histograms.txt.

另外, Thomas Gleixner 还做了一个测试工具 cyclictest, 用来更好更具体的测量给定系统的实时性能。 你可以用下面的命令下载.。 git repository 有其他有用的实时系统工具。

下载并解压和编译工具:

# git clone git://git.kernel.org/pub/scm/linux/kernel/git/clrkwllms/rt-tests.git
# cd rt-tests
# make

如果想每一个CPU或者CPU核运行一个测试线程,请输入:  

# ./cyclictest -a -t -n -p99

在一个非实时系统中,你会看到像下面这样的:

T: 0 ( 3431) P:99 I:1000 C: 100000 Min:      5 Act:   10 Avg:   14 Max:   39242
T: 1 ( 3432) P:98 I:1500 C:  66934 Min:      4 Act:   10 Avg:   17 Max:   39661

右上角的列含有最重要的信息,比如最差延迟为39.242毫秒.在一个实时嵌入式系统里,结果应该会像下面这样:

T: 0 ( 3407) P:99 I:1000 C: 100000 Min:      7 Act:   10 Avg:   10 Max:      18
T: 1 ( 3408) P:98 I:1500 C:  67043 Min:      7 Act:    8 Avg:   10 Max:      22

这意味着短期最差延迟为18微秒。

那么,延迟多少才算正常呢?cyclictest 提供了 -b 选项,如果超过了某个预设的延迟阈值,比如:

# ./cyclictest -a -t -n -p99 -f -b100

如果延迟值超过100微秒,程序会退出。 可以到/sys/kernel/debug/tracing/trace查看trace输出。如下所示:

qemu-30047 2D.h3 742805us : __activate_task+0x42/0x68 (199 1)
qemu-30047 2D.h3 742806us : __trace_start_sched_wakeup+0x40/0x161 (0 -1)
qemu-30047 2DNh3 742806us!: try_to_wake_up+0x422/0x460 (199 -5)   
qemu-30047 2DN.1 742939us : __sched_text_start+0xf3/0xdcd (c064e442 0)

第一列表示触发延迟的进程。如果trace输出还不是很清楚,可以提交给 OSADL Latency Fight Support Service。除了使用 cat /sys/kernel/debug/tracing/trace, lspci命令的输出和用来编译内核的 .config文件也需要提交。 OSADL的服务原则是会员优先,但会尽可能帮助每个人都处理好延迟问题。

转载:https://mp.weixin.qq.com/s/sCYtbF3fvBGlK0wuZcpb_A

 

你可能感兴趣的:(【linux,kernel】)