李在林,韩宏克.嵌入式Linux实时性分析及改造.2010
Linux 的实时性测试——中断延迟测试
在Linux中,内核或驱动程序显式地关/开中断,一般是通过调用_cli()/_sti()来进行操作的。在调用_cli()时,记录系统的时间值,读出当_sti()被调用的系统时间,它们之间的时间差就是关中断时间。关中断时间测试程序重写了_cli()/_sti()宏,以允许记录调用它们的文件以及在何处调用,记录这些信息,以分析在Linux中哪些关中断时间比较长。
注:作者利用关中断时间代表中断延迟时间可能不太合适,以下是我在网上搜到的
(Interrupt Latency) 中断延迟,是指从硬件中断发生到开始执行中断处理程序第一条指令之间的这段时间。
也就是:计算机接收到中断信号到操作系统作出响应,并完成换到转入中断服务程序的时间。
不严格地,也可以表述为:(外部)硬件(设备)发生中断,到系统执行中断服务子程序(ISR)的第一条指令的时间。
另外,如果尽可能严格地考虑问题,那么还要考虑下列情况:
1.中断的详细情况就是:外界硬件发生了中断后,CPU到中断处理器读取中断向量,并且查找中断向量表,
找到对应的中断服务子程序(ISR)的首地址,然后跳转到对应的ISR去做相应处理。
此部分时间,我称其为:识别中断时间
2.在允许中断嵌套的实时操作系统中,中断也是基于优先级的,允许高优先级中断抢断正在处理的低优先级中断,如ucOS/II,所以,如果当前正在处理更高优先级的中断,即使此时有低优先级的中断,
系统也不会立刻响应,而是等到高优先级的中断处理完之后,才会响应。
而即使在不支持中断嵌套,即中断是没有优先级的,中断是不允许被中断的,所以,如果当前系统正在处理一个中断,而此时另一个中断到来了,系统也是不会立即响应的,而只是等处理完当前的中断之后,才会处理后来的中断。
此部分时间,我称其为:等待中断打开时间
3.在嵌入式系统中,如ucOS/II,(其他类似系统中也有此情况),
常用开关中断来实现共享区的互斥访问。
所以,会出现这种情况:当前中断来了,但由于之前某个程序访问共享区,
而关闭中断了,导致当前中断得不到处理。而只有等待其访问完成共享区之后,再开中断。
(不过,一般来说,关中断的时间都很短,否则也就不适合用开关中断的方法来实现共享区互斥访问,
而应该用信号量或者其他手段实现。因为关中断时间长短,是衡量一个实时系统性能好坏的一个重要指标)
此部分时间,我称其为:关闭中断时间
所以,总的中断延迟时间就可以表示为:
中断延迟 = 识别中断时间 + [等待中断打开时间] + [关闭中断时间]
Linux实时改造——双内核法
双内核法
这种方法是在同一硬件平台上采用了2个相互配合、共同工作的系统核心,一个具有精确的实时多任务管理功能,另一个具有复杂的非实时通用功能。实时核心层负责硬件管理并提供实时任务管理,Linux核心是实时核心中优先级最低的,只有当没有可运行的实时任务时,Linux核心才被调度使用[]
RTLinux的实现方法
RTLinux将Linux内核当做一个任务,在一个小的实时操作系统下运行,只有在没有实时任务需要运行的空闲状态时Linux(作为一个任务)才能投入运行。动态地看,Linux的运行不断地被实时任务打断。作为任务的Linux内核永远不能关闭中断,也就是不能避免自己被实时中断任务先占。实现的关键技术是用软件来模拟一个控制中断的硬件,将实时中断和非实时中断区别对待。Linux为了取得某些操作的同步,经常要关中断,这是造成其不可先占的根本原因。在RTLinux中,当Linux通知CPU关闭中断时,实时内核截获这个请求,并把它记录下来,然后,返回Linux继续运行(注意:并未真的将中断关闭,但CPU标志寄存器的中断标志位IF仍为"1"),所以,Linux并没有真正禁中断。无论Linux处在什么状态,它都不会对实时系统的中断响应增加任何延迟。当一个中断信号到来时,实时内核截获这个中断信号,并识别其类型(是实时中断还是Linux中断);如果是实时的,则唤醒其处理函数;如果不是实时的,或者虽是实时的但其处理函数表明要同Linux共同处理这个中断,则对之作“待处理”标记,并送入一个队列排队等候。
接下来,假如Linux已经开放中断,实时内核就用软中断指令唤醒Linux的中断处理函数,同时,使CPU重新开放中断,以允许实时中断进入。这样Linux的所有中断处理机制都能得到满足;当它关闭中断时,实时内核就不启动任何Linux中断处理函数,当然也就不会引起任何混乱。从以上机制可以看出,驱动Linux中断处理函数的,实际上是实时内核,硬件发出的中断信号完全由实时内核接管,实时内核是如何截获Linux的中断操作信号的呢?Linux是用"cli"和"sti"宏来操作关中断和开中断的。在标准的Linux中,这些宏只是简单地执行相应的X86指令。RTLinux对这些宏作了修改,当Linux用"cli"关闭中断时,它并不是真正屏蔽所有中断,而是转去执行一些RTLinux代码。
由此可知,硬件中断信号完全由实时内核接管,而与Linux完全无关。无论Linux正在做什么,不管它是在内核状态还是用户状态下运行,中断是开放的还是关闭的,也不管它是否正运行在回旋锁状态,实时系统总能够对中断做出及时响应。
下面,从CPU的中断机制角度说明RTLinux模拟中断分类硬件的方法。由前述可见,在RTLinux中,Linux内核永远不能关闭中断,实时内核为了不错过任何一个中断也不会轻易关中断,所以,每一个中断都会引发相应中断处理子程序的执行。在RTLinux中,在保留标准Linux的IDT(中断描述符表)的同时,实时内核另造了一个IDT,并使CPU的IDTR(中断描述符表寄存器)指向这个IDT,当一个中断信号到来时,CPU会自动用这个中断信号的中断类型码(由中断控制器8259A提供)由IDTR指向IDT中的相应位置,获取中断处理子程序的入口地址并转入执行。
在中断处理子程序中作如下处理:如果它是一个实时中断,则转去执行相应的实时处理函数;如果它是一个Linux中断并且Linux处于开中断状态,则使IDTR重新指向Linux的IDT并发出一个软中断,激活Linux的中断处理函数,如果Linux处于关中断状态,则使这个中断进入等候队列。
RTLinux的调度算法:
调度程序的工作,实际上就是采用某种调度算法从就绪队列中挑选出一个任务,使之投入运行,RTLinux实时内核的调度程序采用纯粹的优先级/时间驱动的调度策略,也就是说,在RTLinux中,永远是优先级最高的就绪任务投入运行,直到它将自己挂起或者有更高优先级任务就绪。如果数个任务具有相同的优先级,且它们都是就绪队列中优先级最高的任务,RTLinux调度器将按先入先出的策略进行调度。