4、spinlock转换成mutex
spinlock是一个高效的共享资源同步机制,在SMP(对称多处理器Symmetric Multiple Proocessors)的情况下,它用于保护共享资源,如全局的数据结构或一个只能独占的硬件资源。但是spinlock保持期间将使抢占失效,用spinlock保护的区域称为临界区(Critical Section),在内核中大量地使用了spinlock,有大量的临界区存在,因此它们将严重地影响着系统的实时性。为此使用mutex来替换spinlock,它的意图是让spinlock可抢占,但是可抢占后将产生很多后续影响。
Spinlock失效抢占的目的是避免死锁。Spinlock如果可抢占了,一个spinlock的竞争者将可能抢占该spinlock的保持者来运行,但是由于得不到spinlock将自旋在那里,如果竞争者的优先级高于保持者的优先级,将形成一种死锁的局面,因为保持者无法得到运行而永远不能释放spinlock,而竞争者由于不能得到一个不可能释放的spinlock而永远自旋在那里。
由于中断处理函数也可以使用spinlock,如果它使用的spinlock已经被一个进程保持,中断处理函数将无法继续进行,从而形成死锁,这样的spinlock在使用时应当中断失效来避免这种死锁的情况发生。标准linux内核就是这么做的,中断线程化之后,中断失效就没有必要,因为遇到这种状况后,中断线程将挂在等待队列上并放弃CPU让别的线程或进程来运行。
等待队列就是解决这种死锁僵局的方法,让每个spinlock都有一个等待队列,该等待队列是按进程或线程的优先级排队的。如果一个进程或线程竞争的spinlock已经被另一个线程保持,它将把自己挂在该spinlock的优先级化的等待队列上,然后发生调度把CPU让给别的进程或线程。
5、优先级继承和死锁检测
spinlock被mutex化后会产生优先级逆转(Priority Inversion)现象。所谓优先级逆转,就是优先级高的进程由于优先级低的进程保持了竞争资源被迫等待,而让中间优先级的进程运行,优先级逆转将导致高优先级进程的抢占延迟增大,中间优先级的进程的执行时间的不确定性导致了高优先级进程抢占延迟的不确定性,因此为了保证实时性,必须消除优先级逆转现象。
优先级继承协议(Priority Inheritance Protocol)和优先级顶棚协议(Priority Ceiling Protocol)就是专门针对优先级逆转问题提出的解决办法。
所谓优先级继承,就是spinlock的保持者将继承高优先级的竞争者进程的优先级,从而能先于中间优先级进程运行,尽可能快地释放锁,这样高优先级进程就能很快得到竞争的spinlock,使得抢占延迟更确定,更短。
所谓优先级顶棚,就是根据静态分析确定一个spinlock的可能拥有者的最高优先级,然后把spinlock的优先级顶棚设置为该确定的值,每次当进程获得该spinlock后,就将该进程的优先级设置为spinlock的优先级顶棚值。
Spinlock被mutex化后引入的另一个问题就是死锁,典型的死锁有两种:
一种为自锁,即一个spinlock保持者试图获得它已经保持的锁,很显然,这会导致该进程无法运行而死锁。另一种为非顺序锁而导致的,即进程P1已经保持了spinlock LOCKA但是要获得进程P2已经保持的spinlock LOCKB,而进程P2要获得进程P1已经保持的spinlock LOCKA,这样进程P1和P2都将因为需要得到对方拥有的但永远不可能释放的spinlock而死锁。对这两种情况都要进行检测,一旦发生这种死锁,内核将输出死锁执行路径并panic。
6、大内核锁可抢占
大内核锁(BKL---Big Kernel Lock)实质上也是spinlock,只是它一般用于保护整个内核,该锁的保持时间比较长,因此它对整个系统的实时性影响是非常大的,大内核锁使用了semaphore来实现,如果内核配置为前面三种抢占模式,struct semaphore是架构相关的,如对于x86,结构定义如下:
struct semaphore {
atomic_t count;
int sleepers;
wait_queue_head_t wait;
};
但对于第四种抢占模式,其结构为:
struct semaphore {
atomic_t count;
struct rt_mutex lock;
};
注意新的spinlock定义也包含字段struct rt_mutex lock,因此可抢占大内核锁和新的spinlock共用了低层的处理代码。使用semaphore之后,大内核锁就可抢占了。
7、结论
Linux实时性能的逐步完善,必将大大促进嵌入式Linux在工业控制、后PC时代信息电器等领域的广泛应用,应用的需要也会进一步促进大量新型实时算法的出现。通过对Linux的改动,就可以开发出一种可靠的且廉价的硬实时操作系统,具有很好的发展和应用前景。本文作者的创新点:通过改进延迟,优先级继承并增加抢占机制,改善了系统的实时性,为嵌入式系统开发打下了基础。