linux任务响应模型&linux实时化&RTAI 3.2分析&Adeos分析
- UID
- 1029342
- 性别
- 男
|
linux任务响应模型&linux实时化&RTAI 3.2分析&Adeos分析
下面是以前做过的关于linux(基于2.4的)实时化方面的一些学习心得,希望对大家有所帮助,同时也强烈的希望大家共同补充、修正。
从Linux本身所固有的实时性方面的缺陷可以看出,Linux实时化的最终目标是要满足实时任务快速的响应时间的要求。一个实时任务的一次运行(实时任务一般都是周期性的)是由外部中断触发的,当中断产生的时候,CPU接收到中断信号,如果CPU当前允许中断(如果不允许,则直到允许中断后才处理中断),保存当前运行的任务跳转到中断服务程序,执行中断服务程序(在中断服务程序中唤醒实时任务),然后执行中断返回,如果当前系统允许进行进程调度,则调度实时任务开始运行(假定这个实时任务的优先级最高)。为了更好的理解Linux实时化的基本原理,我们有必要对Linux的任务响应模型作详细的分析,如附件中图像所示,给出了一个简化的Linux任务响应模型。
如图所示任务响应模型中,任务2(可以看成Linux内的软实时任务)的优先级高于任务1。t0时刻任务1在运行,而任务2处于睡眠状态,等待中断唤醒;t1时刻任务1请求系统服务完成某些操作(例如通过read()文件接口读取磁盘上的文件等),此时开始,系统在内核态运行;在t2时刻,产生一个中断(在这个中断的中断服务程序中唤醒任务2),但可能由于系统在内核态进行某些操作不希望被中断,CPU的处理中断被禁止,那么这个中断信号没有立刻得到响应,而是继续在内核态执行系统服务;在t3时刻,内核态代码使能中断响应(Linux内核退出临界区),这个时候CPU开始响应在t2时刻产生的中断,并从t4时刻开始执行中断服务程序;当中断服务程序执行完之后(在这个中断服务程序中唤醒了任务2),返回被中断的代码,由于此时系统运行在内核态(执行任务1的系统服务请求),任务2无法抢占任务1的控制权,所以执行任务1的系统服务请求;在t7时刻,由于任务1的系统调用完成返回或者在执行系统服务的过程中主动请求任务调度,系统开始进行任务调度,并在时刻t8运行任务2(假定此时任务2是系统内最高优先级的任务)。
其中,从时刻t2至时刻t8这个时间段,就是我们所说的任务响应延迟时间(Task Response Time);从图可以看出,任务的响应延迟时间可以分为以下几个部分:
1)中断潜伏期(InterruptLatency)或者说中断延迟,这个指从中断产生到CPU开始响应中断的时间段,也就是图中从t2至t3的时间段。中断潜伏期是由于内核在进入临界区前关闭CPU的中断响应所引起的,在这个时间段内,虽然外部设备使CPU的中断请求线有效,但CPU并不立刻响应中断,而是继续执行临界区的内核代码,直至退出临界区、使能中断请求,才开始进行中断的响应。当然,还需要注意的一点是,中断潜伏期实际上包含了硬件所产生的中断延迟时间,我们一般所研究的是如何最大限度的减少软件所造成的延迟时间,所以,如果没有特别说明,我们是不考虑硬件所产生的延迟(但实际上,在工程应用中,当经过软件的优化还不能满足系统实时性的要求时,唯一的办法就只有提高硬件的处理速度了)。
2)中断分发阶段(中断准备阶段),这个指从CPU开始响应中断请求到开始执行中断服务程序之间的时间段,也就是图中从t3至t4的时间段。这个期间系统要做的主要操作包括查找中断号、保存寄存器、定位中断服务程序等。这个时间段的长度对于具体的平台来说,一般是确定性的,也就是说时间长度是固定的。另外,从中断产生到开始执行中断服务程序之间的时间段被称为中断响应延迟时间(Interrupt ResponseTime),对应于图中t2至t4的时间段。
3)中断服务阶段,这个指从系统开始执行中断服务程序到中断服务程序执行完的时间段,也就是图中t4至t5的时间段。这个时间段的长度与具体的中断或者说具体的应用有关,也就是说,这个时间段的长度是可以控制的。
4)中断返回阶段,这个指从中断服务程序执行完到恢复被中断代码开始运行的时间段,也就是图中t5至t6的时间段。这个期间系统要做的主要操作是恢复寄存器的值,这个时间段长度一般也是固定的。
5)调度潜伏期(ScheduleLatency)或者说调度延迟,这个指从系统需要进行进程调度(当前进程的进程结构中need_resched的值为1)到实际开始进行调度的时间段,也就是图中t6至t7的时间段。由于Linux2.4内核的不可抢占性,当系统运行在内核空间中时,即使有更高优先级的进程需要运行,除非主动请求进行调度,否则高优先级的进程是无法抢占当前进程运行的;所以,只有等到低优先级进程的系统调用完成或主动请求调度的时候,才能进行进程的调度。
6)进程调度时间,这个指从系统开始进行调度到最高优先级的进程开始被调度运行的时间段,也就是图中t7至t8的时间段。在这个期间,系统主要是根据系统资源的利用情况、进程的优先级、进程的运行情况,选择合适的进程进行调度。
linux实时化技术
1 软件中断模拟
由于Linux存在许多关中断的区域,这就会导致中断潜伏期过长,当中断频繁时,会有丢失外部中断的可能性,这是实时系统所不能容忍的。解决这个问题最直接的办法,就是不关中断;这里所谓的不关中断,是对整个系统来说不关中断,但对于Linux本身来说,或者说从Linux的角度来看的话,Linux本身的行为和实际关中断的时候时一样的。这种方法可以用软件中断模式技术来实现。
软件中断模式技术中所指的软件中断,是对于Linux来说的,也就是说,Linux并不直接控制硬件中断,当Linux需要关中断时,它实际上的操作只是将一个软件标识置位,表示从此时开始Linux的执行不想受到中断的干扰,当Linux开中断的时候,实际上的操作是将这个软件标识清除。而实际硬件中断由处于硬件和Linux之间的一个软件层来管理,这个软件层的主要任务就是接收硬件中断,并根据需要调度Linux的中断服务程序;当Linux关中断时(并没有实际禁止硬件中断),软件中断模拟层继续接收硬件中断,并将中断信息记录在日志中,当Linux开中断时,模拟层就根据中断日志调用Linux的中断服务程序;
通过软件中断模拟技术,可以有效的防止外部中断的丢失,但是,我们应该看到,在Linux关中断期间,外部中断还是得不到响应(也就是Linux本身的相应中断服务程序没有执行),所以,这种技术并没有缩短系统的中断潜伏期,也就没有提高系统的中断响应时间,还是无法满足实时任务对快速的中断响应时间的要求。
2 增加内核抢占点
从对Linux的任务响应模型的分析可以看出,调度潜伏期对任务响应时间的影响非常大,在任务响应时间中占了很大一部分(很多文献关于这方面的测试结果都可以证明这一点);所以,Linux实时性优化的一个重要目标就是缩短调度潜伏期的时间。那么,影响Linux调度潜伏期的因素有哪些呢?调度潜伏期的长短与Linux在内核态的一次运行时间长短有关(从进入内核态执行系统服务到退出内核态的时间段),为了减少调度潜伏期的时间,就必须减少Linux连续运行在内核态的时间;最直观的方法就是在执行时间长的内核代码中增加抢占点(也就是增加部分代码主动请求进行调度),将执行时间长的内核代码划分成若干段执行时间段的代码,在各个代码段之间可以进行进程调度,从而达到缩短调度潜伏期的目的。
已经有资料显示,增加内核抢占点是最有效的缩短调度潜伏期的方法;但是,尽管这种方法的原理很简单,实现起来却是相当的繁琐和费时。一方面,要找出内核中哪些部分的执行时间较长本身就不是一件容易的事,而且同样的代码在不同的系统状态下执行时间的长短也不一样,这就需要进行动态的分析找出内核中耗时的代码段;另一方面,随着内核的不断发展,这种方法在不同版本内核之间的移植性也比较差,而且还要对新增加的内核代码进行分析。
3 利用SMP技术实现可抢占内核
由于Linux内核原来的设计是不可抢占的,也就是说,内核代码大部分没有考虑函数的重入(一个系统服务并发的被两个进程执行)和数据的互斥访问的问题,在这种情况下要实现内核的可抢占相当困难。但是,随着后来Linux对SMP(对称多处理器)支持的成熟,出现了利用SMP技术实现可抢占内核的方法。实现可抢占内核,它的目标和增加内核抢占点类似,实际上也是为了缩短调度潜伏期。
要实现可抢占内核,最主要的工作就是要找出哪些代码可能被进程并发调用,并对相关的临界区进行保护,保持数据的一致性。而对SMP的支持,考虑的也是类似的问题,因为在多处理器系统中可以有多个进程同时运行并访问同样的临界资源。所以,可以利用Linux内核对SMP的支持,实现内核的可抢占。在可抢占内核中,当有高优先级的进程可以运行时,系统会立刻进行进程调度;当然,在某些情况下内核抢占也是不允许的,这主要包括以下几种情形: |
|
|
|
|
|