微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 应用中的嵌入式Linux实时优化技巧

应用中的嵌入式Linux实时优化技巧

时间:05-16 来源:EDN 点击:
中断延时、中断服务程序

  中断延时指的是从外设发出中断信号开始到ISR的第1条指令开始执行的时间间隔。由外部中断引起的实时任务需求是实时系统处理量的主要组成部分,足够快地中断响应和迅速地中断服务程序处理是衡量实时系统的重要性能指标。不同的ISR执行时间是不一样的,即使是相同的ISR也可能因为有多个出口而有不同的执行时间。而ISR执行时外部中断是被禁用的,造成这样一种情况,即使Linux的中断延时非常小,如果在一个ISR执行时某个外设也产生了一个中断信号,因为正在执行的ISR运行时间的不确定性和不可抢占性,也会产生Linux的中断延时的不可预测性。

  3 系统实时性能的提高

  3.1 任务切换机倒的建立

  在2.1节中提到进程在临界区中执行的时候不能被抢占的问题,为了不影响系统稳定性、减少调试和测试的时间,我们不打算对此进行修改,而引入一个机制保证实时任务能够得到优先执行。即在实时系统中,只有当进程的临界区能在下一个实时任务开始之前结束才被允许进入。

  如何判断下一个实时任务中断信号的产生时间,一般来说中断信号是为了那些开始时间不可预测的任务而设定的,它的产生是完全随机的。为了使中断信号的时间能够被预测,将中断信号的产生与时钟中断挂钩:中断信号只能与时钟中断同时产生。时钟中断由系统计时硬件以周期性间隔产生。这个间隔由内核根据Hz值设定。Hz是一个与体系结构有关的常数,在文件中定义。当前的Linux为大多数平台定义的Hz值是100,亦即时钟中断周期是10ms。显然这是达不到实时系统定时精度要求的。提高Hz值能够带来系统性能提升,但却是以增加系统开销为代价。这就必须仔细权衡实时性要求和系统开销的平衡。一种方法是通过大量的测试确定的实时任务中断请求发生的时间间隔和进程在临界区中的执行时间,取一个稍大于大多数实时任务中断间隔和临界区执行时间的数值。

  Linux提供了一些机制让我们得以计算函数的执行时间,gettimefoday()函数是其中之一。函数的原型及需要使用的一个数据结构如下:



  其中,gettimeofday()将当前时间保存在tv结构中,tz一般不需要用到,可用NULL代替。使用示例如下:



  如此即可得出进程在临界区function_in_critical_section()所耗费的时间,以供参考。将Hz值设定在2000,此时系统时钟中断周期为0.5ms,精度提高了20倍。

  如图1、图2所示,当进程进入临界区之前,它比较自身的平均执行时间T(NP)和T(REMAIN)的值,当T(NP)≤T(REMAIN)的时候,进程才被允许进入临界区,否则进程进入工作队列等待下一次判断。



  本文尝试用数学方法来分析采用这种机制对实时性能的提高。首先给出一个定义:当预定在时刻t时执行的实时任务推迟到时刻t'时才执行,则t'-t称作系统延迟,用Lat(OS)表示。在普通Linux中,Lat(OS)如下:

Lat(OS)=T(NP)+ T(SHED)

  设任意时刻 ,T(NP)≤T(REMAIN)的机率为ρ,则普通Linux中的平均Lat(OS)为

AvLat(OS)=ρ[T(NP)+ T(SHED)] +(1-ρ)[T(NP)+ 2T(SHED)]

  引入前述机制后,由于总是优先保证实时任务的执行,Lat(RT-OS)固定式为:

Lat(RT-OS)=T(SHED)

  采用该机制前后系统廷迟的变化为

δ=AvLat(NOR-OS)-Lat(RT-OS)=T(NP)+(2-ρ)T(SHED)

  在一个特定系统里,ρ是固定的,而在Linux 2.6中,采用O(1)算法后T(SHED)也是固定的,由前式可得出结论:在临界区的进程执行时间长的系统中,引入该机制前后平均系统廷迟下降的越大,系统实时性能的改善越明显。

  3.2 优先级量顶

  试描述一个如下场景:低优先级的任务L和高优先级H任务需要占用同一共享资源,低优先级任务开始后不久,高优先级任务也准备就绪,发现所需共享资源被占用后,任务H被挂起,等待任务L结束释放该资源。此时一个不需要该资源的中优先级任务M 出现,调度器依据优先原则转而执行任务M。这就进一步廷长了任务H的等待时间,如图3所示。更加恶劣的情况是,如果出现了更多的类似任务M0,M1,M2,...,将有可能使任务H错过临界期限(Critical Deadline),而导致系统崩溃。

  在一个不太复杂的实时系统中,可采用优先级置顶的方法解决这一问题。该方案对每一个可能被共享的资源分配一个优先级,该优先级为有可能使用这个资源的最高优先级的进程的优先级(如下伪代码中的RESOURCE_X_PRIO)。由调度器将优先级传给使用该资源的进程,进程结束后其自身的优先级(如下伪代码中的TASK_A_PRIO)才恢复正常。这样就避免了上面场景中任务L被任务M抢占,而导致任务H始终处于挂起状态。优先级置顶的示例代码如下:



Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top