APP下载

基于ARM的Linux实时抢占补丁的研究与实现

2015-12-30王帅华,杨东升,王允森

组合机床与自动化加工技术 2015年9期

基于ARM的Linux实时抢占补丁的研究与实现*

王帅华1,2,杨东升2,王允森1,2,袁晓慧1,2

(1.中国科学院大学,北京100049;2.中国科学院 沈阳计算技术研究所,沈阳110168)

摘要:随着ARM处理器计算能力的提高,该类型的处理器在嵌入式领域的应用越来越广泛的同时,也得到了数控系统的青睐。结合数控系统的实时加工技术的要求,通过分析和研究Linux实时抢占补丁(RT-Preempt patch)技术,提出了一种基于ARM微处理器TI AM3358的嵌入式实时系统解决方案。在以TI AM3358为硬件平台的Linux嵌入式系统中实现了RT-Preempt的应用,并对任务调度延迟、中断响应延迟和优先级反转问题进行了测试。经试验证明,提出的实时系统解决方案可以满足中档数控系统实时加工的需求。

关键词:可抢占实时补丁;嵌入式实时系统;嵌入式数控系统

文章编号:1001-2265(2015)09-0001-04

收稿日期:2014-11-25

基金项目:*"核高基"专项(2012ZX01029-001-002)

作者简介:王帅华(1988—),男,山东日照人,中国科学院大学硕士研究生,研究方向为实时系统,(E-mail)wangshuaihua@sict.ac.cn;杨东升(1965—),男,沈阳人,中国科学院研究员,博士生导师,研究方向为自动控制、数控技术等。

中图分类号:TH164;TG65

Research and Implementation on RT-Preempt Patch of Linux Based on ARM

WANG Shuai-hua1,2, YANG Dong-sheng2, WANG Yun-sen1,2, YUAN Xiao-hui1,2

(1. University of Chinese Academy of Sciences, Beijing 100049, China; 2. Shenyang Institute of Computing Technology, Chinese Academy of Science, Shenyang 110168, China)

Abstract:With the increase in computing power of ARM processor, this type of processors are used more and more widely in embedded field, at the same time, they are favored by the CNC system. Through analysis and study of the Linux real-time preemption patch (RT-Preempt) presented a new embedded real-time system solution based on ARM microprocessor TI AM3358 and RT-Preempt. Finally, this paper completed the measurement of task schedule latency, interrupt response delay and priority inversion problem which affect the performance of real-time system. The results of the experiment support that the performance of that solution can meet the demand of real-time processing from CNC.

Key words: real-time preemption patch; embedded real-time system; embedded CNC

0引言

嵌入式系统平台包括硬件平台和软件平台。硬件系统平台主要包括x86平台和以ARM为代表的RISC平台。软件平台主要有Linux、WinCE、Vxworks、QNX和pSOS等系统平台[1]。基于x86的处理器功耗大、成本高、体积大并且外围电路复杂,而基于ARM的处理器功耗低、成本低、体积小并且外围电路简单。ARM处理器的计算能力不断提高,最新的ARM处理器的已经可以满足中档数控系统计算能力的要求[2]。Linux系统作为嵌入式软件系统有它独特的优势,其开源的特性使我们可以对其进行深度定制和实时性改造。

1Linux实时化技术

Linux作为一个通用的操作系统,为了适应服务器和用户桌面的应用,增加系统的吞吐量和用户体验,被设计成分时操作系统。而嵌入式实时控制领域对系统的实时性要求比较高,所以需要对Linux系统进行实时化改造。

对Linux的实时化改造有两种方法:

(1)对Linux内核进行修改,优化Linux的实时性能;

(2)采用双内核方案,增加一个实时内核,有实时要求的任务都在这个实时内核上运行,标准Linux内核作为这个实时内核优先级最低的一个进程[3-4]。

对Linux内核改造的主要产物有:RED-Linux、Hard-hat Linux、Kurt-Linux和RT-Preempt等[5]。对标准Linux实施双内核改造的产物有:RTLinux、RTAI(Real-Time Application Interface)和Xenomai等。

与使用双内核的方法相比,对标准Linux内核直接改造的方法更适合在新硬件平台上进行嵌入式实时系统的研发。TI AM3358是TI公司新推出的硬件平台,具有720MHz的主频和较强的运算能力,适合在数控系统中应用,但是目前官方还没有双内核方案对该平台的完整支持。因此,我们选择RT-Preempt对现有的Linux内核进行实时性改造。

2TI AM 3358微处理器

基于ARM Cortex-A8的AM3358微处理器在图像、图形处理、外设和诸如EtherCAT和PROFIBUS的工业接口选项方面进行了增强。处理器主频最高可以达到720MHz,具有单错检测(奇偶校验)的32KB L1指令/数据高速缓存,含纠错码(ECC)的256KB L2高速缓存,支持移动双倍速率同步动态随机存储器(mDDR)(低功耗DDR(LPDDR))/DDR2/DDR3,支持通用存储器(NAND,NOR,SRAM,等),支持高达16位ECC,支持最多2个具有集成物理层的USB 2.0高速OTG端口,支持最多2个端口的10/100/1000以太网交换机,串口包括:2个控制器局域网端口(CAN),6个UART,2个McASPI,2个McSPI和3个I2C端口,支持硬件加密加速(AES,SHA,PKA,RNG)。在这款符合工控要求的嵌入式处理器硬件平台之上,整个嵌入式实时系统的实时性能主要由操作系统决定。

3Linux实时抢占补丁实现原理

Linux实时补丁现主要由Ingo Molnar和Thomas Gleixner维护,并且由开源自动化开发实验室(OSADL)对其稳定性测试。最新版的实时补丁随Linux内核一同发布,并且越来越多的实时抢占补丁的内容被官方Linux项目接收[6],融入到发行版的Linux内核中。Linux实时补丁相比于双内核机制方案最大的优势在于它遵循POSIX标准,使用该补丁的实时系统应用程序和驱动程序与非实时系统的应用和驱动程序差异很小,因此,在使用该补丁的平台上做相应的开发比双内核机制的方案更容易。另外,该补丁与硬件平台相关性小,可移植性高。

3.1实时补丁的工作原理

通常情况下Linux内核仅仅在以下三种情况下允许进程间的抢占:

(1)当CPU运行在用户态时;

(2)当内核代码从系统调用或者中断返回到用户空间时;

(3)当内核代码块阻塞在互斥量或者明确地将控制权交给另外一个进程时。

如果内核代码正在执行时有高优先级事件产生,该高优先级线程不能抢占正在执行中的内核代码,该线程只能等到内核代码明确地交出控制权才能得到执行。在更糟糕的情况下这个延迟会达到上百毫秒或者更大。这在实时系统中是不能接受的。

Linux实时补丁通过以下方法将纯净的Linux内核转变成一个完全可抢占的内核:

(1)通过使用rtmutex重新实现自旋锁来实现内核锁原语的可抢占操作;

(2)为了解决优先级反转问题,为内核中的自旋锁和信号量实现优先级继承策略;

(3)将中断处理程序转换成可抢占的内核线程;

(4)提高了用户空间POSIX定时器的精度。

3.2实时补丁的具体实现

(1)可抢占自旋锁的实现。以spin_lock_irqsave宏函数为例:

#define spin_lock_irqsave(lock, flags)do{typecheck(unsigned long, flags);flags=0;spin_lock(lock);}while(0)

在对spin_lock()函数的调用上没有任何区别,主要区别在spin_lock函数的实现:

首先,普通的自旋锁的实现如下:

#define spin_lock (lock) _spin_lock(lock)

void__lockfunc_spin_lock(spinlock_t*lock)

{

preempt_disable();

_raw_spin_lock(lock);

}

在自旋锁普通的实现中,最先通过调用preempt_disable()是禁止进程抢占,再调用获取自旋锁的_raw_spin_lock()函数。而可抢占实时补丁中自旋锁的实现如下代码所示:

#define spin_lock(lock)do {migrate_disable();rt_spin_lock(lock);}

可抢占内核用rt_spin_lock()重新改写了自旋锁的实现。在rt_spin_lock()函数的实现中调用了rt_spin_lock_fastlock()函数,而rt_spin_lock_fastlock()函数是自旋锁可抢占实现的关键代码,因为在该函数中调用了might_sleep()函数,might_sleep()这个函数的作用是指示当前进程可以睡眠,可以睡眠意味这可以交出CPU的控制权,即,该进程可以被抢占。该函数的实现代码如下所示:

static inline void rt_spin_lock_fastlock ()

{

might_sleep();

……

}

might_sleep()的函数的实现如下代码所示:

#define might_sleep() do{ might_resched(); } while (0)

通过对可抢占实时补丁的源代码的分析可以看出在该补丁中对自旋锁的实现完全抛开了非抢占内核中对自旋锁实现的方式,并且保留了非抢占自旋锁的实现。所以可以继续使用_raw_spin_lock()函数创建不可抢占的内核区域。

(2)优先级反转问题的解决。在uc/OS-II中不支持优先级继承,使用的是优先级天花板方式解决的优先级反转问题。这种方法存在的问题是,只要有进程访问可能引起优先级发转的资源时,不论是否发生优先级反转,都会对该进程的优先级进行调整,浪费了许多CPU资源,也影响了系统的实时性[7]。而Linux在中采用优先级继承的解决方法时,只有在低优先级进程占用资源并阻塞高优先级进程时才会对占有该资源低优先级进程的优先级的调整,这样可以减少不必要的CPU资源消耗。可抢占实时补丁实现的优先级继承策略已经被内核项目接收,成为内核源码的一部分,其实现在/kernel/rtmutex.c文件中。

(3)中断线程化。中断线程化包括两部分:硬中断线程化和软中断线程化。

软中断的线程化在spawn_ksoftirqd()中完成,该函数在内核初始化的时候执行,他通过kthread_create()调用run_ksoftirqd()创建相应的软中断线程,设置中断线程的优先级,软中断线程采用SCHED_FIFO实时调度策略。软中断线程化后,所有的软中断都转到线程中去处理。其执行时机是当硬中断处理完后,在irq_exit()中调用do_softirqd()通过wakeup_softirq()唤醒相应的中断处理程序。

硬中断的线程化在__setup_irq()中完成,通过kthread_create()调用irq_thread()创建相应的处理线程,硬中断线程也是采用SCHED_FIFO的调度策略。其线程的优先级比软中断线程的优先级要高,为用户线程优先级的一半。__setup_irq()被setup_irq()、request_irq()或request_threaded_irq()调用。中断发生时,硬中断的处理在do_IRQ()中完成,最后通过handle_IRQ_event()唤醒相应的中断线程来处理。

需要注意的是:并不是所有的中断都可线程化,例如时钟中断具有最高优先级,用于驱动整个系统,就不能被线程化。对于不能被线程化的中断需要在中断的irqaction结构体中对flags成员加上IRQF_NODELAY标记。对于时钟中断,因为IRQF_TIMER标记包含了IRQF_NODELAY标记,只需要加上IRQF_TIMER标记即可。

4基于实时抢占补丁的系统平台的构建

RT-Preempt在TI AM 3358平台的移植过程中的关键技术为高精度时钟的实现,因为有关任务调度和中断线程的调度都与时钟有关。在内核文件kernel/sched_clock.c中,有一个平台无关的sched_clock()函数的实现,该函数的关键代码为:

(jiffies-INITIAL_JIFFIES)*(NSEC_PER_SEC/HZ);

从该语句中可以看出,该实现基于系统的jiffies,而jiffies与Hz有关,即jiffies=1/Hz秒。若使用高精度的时钟定时器,必须实现TI AM3358平台的sched_clock()函数。

TI AM 3358处理器的主频为720MHz,可以提供高达1/(720×106)=1.4ns的计时分辨率。

sched_clock()函数实现伪代码:

unsigned long long notrace sched_clock (void)

{

u32 cyc = 0;

_ raw_spin_lock(&lock);

cyc = 读取定时器时间戳;

_ raw_spin_unlock(&lock);

return cyc_2_ns(cyc, (u32)~0);

}

实现该分辨率时钟,首先读取定时器的时间戳,然后将时间戳转换成ns并返回,cyc_2_ns()函数的实现可以参考公式(1)。

ns=(cycles·mult)>>shift

(1)

在该公式中shift的取值为(u32)~0,mult被限制为32位的整数。

为了使Linux实时可抢占补丁生效,需要对内核做相应的配置:

(1)使能CONFIG_PREEMPT选项。在3.x版本的内核需要开启以下三个选项,它们是:

CONFIG_PREEMPT=y

CONFIG_PREEMPT_RT_BASE=y

CONFIG_PREEMPT_RT_FULL=y

(2)激活高精度时钟选项。

CONFIG_HIGH_RES_TIMERS=y

(3)禁用所有的电源管理选项。例如,ACPI和APM等。

5实时性能测试及分析

一般来讲对实时系统的“实时性”的衡量指标主要有两个:一是任务调度延迟,二是中断处理延迟[8]。此外优先级反转也是影响实时系统性能重要因素之一。

任务调度延迟是指任务从需要被调度到任务实际被调度的时间段。图1和图2是分别对Linux重CPU负载的情况下使用clock_nanosleep(TIME_ABSTIME)和POSIX interval timer定时器对任务调度延迟进行的测试。从测试结果中可以看出在使用clock_nanosleep定时器测试时,实时可抢占内核的Linux系统的最小、平均和最大任务调度延迟都小于普通Linux内核的最小、平均和最大延迟,尤其是最大任务调度延迟实时可抢占内核的延迟比普通内核的最大调度延迟小两个数量级。在使用POSIX interval timer定时器的测试中,虽然实时可抢占的Linux内核的最小和平均延迟比标准Linux内核略大,但是还是在同一个数量级内(100μs以内),而在最大延迟方面可抢占实时Linux内核比普通Linux内核同样是小了两个数量级——实时可抢占Linux内核的最大延迟为105μs,而普通Linux内核的最大延迟为2353μs,这远远超过了该实时系统的要求(系统的任务调度周期是1ms)。

图1 clock_nanosleep在两种系统上的对比

图2 POSIX timer在两种系统上的对比

中断处理延迟是指从中断产生到该中断得到响应的时间间隔。Linux中断分为上半部和下半部,上半部对中断信号进行响应,但是具体的中断处理工作将会有下半部执行,中断处理程序不会立刻被执行,而是被放在等待队列中,等CPU空闲时才会得到执行[9]。

对用于工业控制系统来说对中断响应的延迟要求比较高,如果中断得不到及时的响应很可能会造成灾难性的后果。所以中断响应也是对实时系统测试的一个重要标准。原基于X86的RTAI/Linux实时数控系统对中断响应周期为2ms,而标准的Linux内核对2ms周期的中断响应时存在中断丢失的情况。该系统平台使用FPGA编程负责产生2ms/次的中断,该硬件每2ms向CPU其中的一个寄存器中写入连续的数字,并且每40ns向CPU的另外一个寄存器也写入一个连续的数字,由内核中的中断处理程序对寄存其中的数据进行读取并计算数字的连续性和两次中断响应的时间间隔。根据下面的公式计算两次响应的时间间隔和中断响应的抖动时间。

ΔT=Tnew-Told

(2)

ΔTjitter=ΔT×40-2000000

(3)

通过公式(2)计算出两次响应的寄存器中的时间间隔,该寄存器由FPGA负责修改,每40ns修改一次。公式(3)用于计算这两次响应的真实的时间间隔与中断周期2ms之间的差值,该值即为中断响应的时间抖动值,如图3所示。该图为2ms中断响应周期条件下对2ms/次的中断响应时间的抖动值,从图中可以看出最大的抖动值在300μs左右,在以2ms为中断周期的条件下,该中断响应延迟在CNC系统中是可以接受。为了取得更好的测试效果,本次实验中尝试了使用1ms中断响应周期对2ms/次的中断进行响应,其测试结果如图4所示。从实验结果中可以看出在1ms中断响应周期下对中断的响应延迟在1.5μs以内,可以满足中档数控系统实时加工的需求。

图3 2ms中断响应周期抖动图

图4 1ms中断响应周期抖动图

优先级反转对于实时系统来说同样是致命的。对实时可抢占Linux系统的优先级反转的测试如图5所示。在该优先级反转的测试中,每组有三个线层:低优先级线程、中优先级线程和高优先级线程。中优先级线程执行时由低优先级进程持有mutex,这时高优先级线程申请mutex时会被阻塞,同时低优先级线程会继承高优先级线程的优先级,直到低优先级线程执行完毕并释放mutex时,高优先级线程才能得到执行,避免死锁。从执行结果中可以看出,在2min的时间内总共进行了773018组测试,并没有发生死锁问题。可以知道实时可抢占Linux内核已经解决了系统中优先级反转问题。

图5 RT-Preempt Linux系统优先级反转测试

6结论

本文首先分析了嵌入式Linux实时系统的实现方法,着重分析了RT-Preempt实时补丁的实现原理,在基于ARM cortex-A8内核的TI AM3358处理器平台采用Linux实时可抢占补丁的方法构建了嵌入式实时系统平台,并对该系统平台设计和进行了实时性测试。实验结果表明基于ARM处理器TI AM3358的嵌入式RT-Preempt+Linux实时系统可以满足工业级实时性的要求,实现数控系统的实时加工。本课题对数控系统向小型化和经济化的发展有着重要的参考价值。

[参考文献]

[1] 苏宇. 基于Xenomai的实时Linux系统的研究[J].计算机技术与发展,2013,23(10):1-5.

[2] 陆小虎,刘玉香,于东,等.基于CORTEX-A8处理器的嵌入式数控系统试试平台的设计与实现[J].小型微型计算机系统,2013,34(7): 1689-1692.

[3] 刘涛. 一种嵌入式实时Linux的设计与实现[D]. 成都:电子科技大学,2007.

[4] 陈曾汉. 基于Xenomai的实时测控系统的研究与实现[J]. 计算机应用与软件. 2009,26(5):162-165.

[5] 黄芳. 基于S3C2440和RTAI的实时平台的设计与实现[J].组合机床与自动化加工技术,2014(2):83-89.

[6] 吴章金. Linux实时抢占补丁的研究与实践[D].兰州: 兰州大学,2010.

[7] 秦邵华. 关于uc/os-II中优先级反转问题[J]. 单片机与嵌入式系统应用,2005(2):71-71.

[8] 余兵. Linux操作系统实时性分析[J]. 计算机技术与发展, 2007,17(9):41-47.

[9] 李江. Linux系统实时性测试及分析[J]. 计算机应用, 2005,25(7):1679-1681.

(编辑李秀敏)