面向多媒体应用的嵌入式Linux实时性研究
2008-06-10
作者:王建强1,陈建安1,刘钥婷2
摘 要: 首先对Linux系统的实时机制作了分析,然后根据多媒体应用" title="多媒体应用">多媒体应用的特点,通过改进Linux系统的实时性" title="实时性">实时性,构建了面向多媒体应用的嵌入式" title="的嵌入式">的嵌入式Linux系统。实验结果表明,该系统在实时性方面完全可以满足多媒体应用的需求。
关键词: 嵌入式系统 实时性 Linux 多媒体应用
当今信息社会,以多媒体为特征的信息技术和信息产业的发展及应用对人类社会产生的影响和作用愈来愈明显,愈来愈重要。多媒体技术的发展在很大程度上依赖于多媒体软件开发的水平。目前不管是支撑多媒体的系统软件,还是应用软件,都在能力和数量上难以满足多媒体飞速发展的需要。特别是多媒体系统软件的缺乏,一直是制约多媒体产业发展的瓶颈问题之一。
Linux从1991年诞生之日起至今不过十来年,却已发展成为一个功能强大、设计完善的操作系统。在嵌入式领域,Linux同样获得了飞速发展。Linux具有以下特点:
(1)Linux操作系统的开放源码易于定制剪裁,在价格上有竟争力;
(2)Linux操作系统的内核小、功能强大、运行稳定、系统强壮、效率高;
(3)Linux操作系统不仅支持X86 CPU,还可以支持其他数十种CPU芯片;
(4)Linux支持所有标准的因特网协议,几乎所有的协议和网络接口都定制在其中。
因此,Linux系统是多媒体终端操作系统的首选。
1 通用Linux实时性分析及其在实时性方面的不足
虽然目前Linux内核在实时性方面有所增强,但由于Linux系统本身是一个面向桌面的系统,所以将它应用于多媒体终端时,在实时性方面仍存在一些问题。
1.1 通用Linux系统的调度策略
通用Linux系统支持实时和非实时两种进程,实时进程相对于普通进程具有绝对的优先级。对应地,实时进程采用SCHED_FIFO或者SCHED_RR调度策略" title="调度策略">调度策略,普通的进程采用SCHED_OTHER调度策略。
SCHED_OTHER调度策略本质上是一种比例共享的调度策略,它的这种设计方法能够保证进程调度时的公平性:一个低优先级的进程在每一个epoch中也会得到自己应得的那些CPU执行时间,另外它也提供了不同进程的优先级区分,具有高priority值的进程能够获得更多的执行时间。
对于实时进程来说,它们使用基于实时优先级rt_priority的优先级调度策略,但根据不同的调度策略,同一实时优先级的进程之间的调度方法有所不同。
Linux调度时,要遍历运行队列,对队列中的每一个进程计算goodness值,goodness 最大的进程将被选中运行。根据调度策略的不同,进程的goodness值也要做不同的计算。普通进程的goodness值是在该进程计数值counter基础上略有浮动,其范围是0~999。实时进程的goodness值是将该进程实时优先级rt_priority 加上1000。所以实时进程的goodness 总是大于非实时进程,从而保证了实时进程的优先调度权。函数goodness( )如下:
static inline int goodness(struct task_struct*p,int
this_cpu,struct mm_struct*this _ mm)
{int weight;
weight=-1;
if(P->policy&SCHED_YIELD) goto out;/*非实时进程*/
if (p-> policy= =SCHED_OTHER)
{ weight=p一>counter;
if(! weight)goto out;
if(P一>mm= =this _ mm!!!p一>mm)
weight +=1;
weight +=20一P一>nice;
goto out;
}/*软实时进程*/
weight= 1000+P一>rt_priority;
goto out;
return weight;
}一
从上面的goodness()函数可以看出普通Linux内核的进程调度算法只是软实时的,并不是硬实时的。
1.2 通用Linux实时性方面的缺陷
(1)Linux系统中的调度单位为10ms,所以它不能够提供精确的定时;
(2)当一个进程调用系统调用进入内核态运行时,它是不可被抢占的;
(3)Linux内核实现使用了大量的封中断操作会造成中断的丢失;
(4)由于使用虚拟内存技术,当发生页出错时,需要从硬盘中读取交换数据,但硬盘读写由于存储位置的随机性会导致随机的读写时间,这在某些情况下会影响一些实时任务的截止期限;
(5)虽然Linux进程调度也支持实时优先级,但缺乏有效的实时任务调度" title="任务调度">任务调度机制和调度算法;其网络子系统的协议处理和其他设备的中断处理都没有与它对应的进程的调度关联起来,并且其自身也没有明确的调度机制。
2 面向多媒体应用的Linux实时性改进
提高Linux的实时性一般有两种方法:一种是对普通的Linux内核的数据结构、调度函数、中断方式等进行修改,使其能够处理实时进程。另一种是在Linux内核之外,进行实时性扩展。也就是在普通Linux的基础之上再设计一个用于专门处理实时进程的内核。为了提高Linux的实时性,并且使之能够更好地满足多媒体应用系统的需求,本文采用第一种方法来提高系统的实时性。
2.1 提高系统所支持的时钟精度
为了提高Linux系统的实时特性,必须提高系统所支持的时钟精度。但如果仅仅简单地提高时钟频率,会引起调度负载的增加,从而严重降低系统的性能。为了解决这个矛盾, 本文将时钟芯片设置为单次触发状态,即每次给时钟芯片设置一个超时时间,然后到该超时事件发生时在时钟中断处理程序中再次根据需要给时钟芯片设置一个超时时间。其基本思想是:一个精确的定时意味着时钟中断在一个比较精确的时间发生,但并非一定需要系统时钟频率达到此精度。它利用CPU的时钟计数器来提供精度可达CPU主频的时间精度。
2.2 可抢占式内核设计
(1)抢占式内核给task struct数据结构增加一个数据项:preempt_count。该数据项由宏preempt_disable()、preempt_enable()、以及preempt_enable_no_resched()所使用。preempt_disable对preempt_count计数进行递增,preempt_enable对preempt_count进行递减。preempt_enable宏查看当前进程的preempt_count和need_resched域的内容,如果 preempt_count为0并且need_resched为1,则调用preempt_schedule()函数。该函数将给当前进程的preempt_count项增加一个很大的值,然后调用进程调度函数schedule(),在schedule函数返回后从该进程preempt_count中再减去该值,从而实现内核可抢占。
(2)修改schedule函数,使它检测进程的preempt_co-unter是否很大(这是为了屏蔽一些普通调度流程中对于抢占式调度来说是冗余的那些操作),然后执行抢占式调度。同时修改spinlock的代码。在spin_lock()和spin_try_lock中增加了对于preempt_disable的调用,在spin_unlock()中增加了对于preempt_enable的调用。修改中断返回的代码,在其中增加了对于preempt_enable的调用。
由以上可看出内核的抢占式调度发生在如下情况:在释放spinlock时,或者当中断返回时,如果当前执行进程的need_resched被标记,则进行抢占式调度。
2.3 实时任务调度的实现
在任务切换方面限制Linux不能进入RTOS行列的主要原因是:内核无法及时进行进程调度,即任务调度器schedule()函数不能及时被执行;当中断返回到内核态时,Linux内核禁止进行进程调度,只有中断返回到用户态时,Linux内核才允许进行进程调度。针对这两点,对Linux内核的相关函数作如下修改:
(1)当系统从中断返回到内核态时,强制调用调度函数preemp_schedule(),为此,在arch/i386/kernel/Entry.S中修改如下代码:
……
#ifdef CONFIG PREEMPT
cli
decl preempt count(%ebx)/*恢复内核抢占标志*/
#endif
……
incl preempt count(%ebx)
sti
call SYMBOL_ NAME(preempt_schedule)
jmp ret_from_intr/*新进程返回ret_from_intr恢复抢占标志后再返回*/
……
(2)对于内核态抢占的任务不要从运行队列删除,为此需要对文件kernel/schedule.c作修改,关键代码如下:
……
#ifdef CONFIG PREEMPT
ctx_sw_off();/*加锁,禁止内核抢占*/
#endif
……
#ifdef CONFIG_PREEMPT
if(prev->state & TASK_PREEMPTED)
break;/*如果是内核抢占调度,则保留运行队列*/
#endif
……
#ifdef CONFIG PREEMPT
ctx_sw_on_no_preempt();/*解锁,允许内核抢占*/
#endif
……
这样可以解决当中断返回到内核态时,Linux内核禁止进行进程调度,只有中断返回到用户态时,Linux内核才允许进行进程调度的问题,从而增强了任务调度的实时性。
3 嵌入式Linux实时性能测试结果
测试工具:Linux Trace ToolKit-0.8
测试环境:Intel Celeron 1.2GHz CPU、256MB SDRAM,通用Linux为Red Hat9.0,RT-Linux为3.0版,Media-Linux即为本文实现的嵌入式Linux。
测试结果如表1所示。
可以看出,本文构建的Linux系统的任务响应时间处于十微秒级,完全可以满足多媒体应用终端的实时性需求。
根据多媒体应用的特点,在尽可能地保证系统性能的前提下,本文通过提高系统所支持的时钟精度、设计可抢占式内核、增强实时任务调度改进了通用Linux的实时性(关键部分给出了源代码及数据结构)。实验结果表明,该系统在实时性方面完全可以满足多媒体终端应用的需求,具有较好的应用前景。
参考文献
1 李善平,刘文峰,李程远.Linux内核2.4版源代码分析大全[M].北京:机械工业出版社,2001
2 邹思铁.嵌入式Linux设计与应用[M].北京:清华大学出版社,2002
3 Yaghmour K著,韩存兵,龚波译.构建嵌入式Linux系统[M].北京:中国电力出版社,2004
4 Jeffay K.Scheduling Sporadic Tasks with Shared Resources in Hard-Real-Time Systems[J].in Proc.Of the 13th Real-Time Systems Symposuim.Phoenix,Arizona,1992;(12)
5 Embedded Linux nears real time.http://www.edn.com/article/CA450620.html