惬谈自旋锁

  之前一想到自旋锁我的眉头就紧皱,可能之前看书都是囫囵吞枣,半懂半不懂的,现在想明白了,才知道自旋锁原来是这么惬意的。

  现在从简单的开始谈起,如果你想用自旋锁来保护你的临界区,你可以用下面的函数对

  spin_lock(&my_lock);

      ...............................

  spin_unlock(&my_lock);

  其实自旋锁的具体实现是依据不同的系统而定的,在多处理器和可抢占式系统中,spin_lock的实现分两步,第一步是关闭可抢占,第二步是如果没有获得锁时将执行一段自旋的代码直到活动锁.

     而在单处理器可抢占式系统中,spin_lock的实现就只有一步,就是关闭可抢占,因为在单处理器中关闭了可抢占已经足够保证了你的代码的安全(还有一种情况没有考虑到,下面再另外讨论)。所以自旋锁在单处理器中并不需要自旋,自旋是针对多处理器而设置的,因为在多处理器中,即使关闭了可抢占,由于不同的处理器可以运行不同的进程,所以还需要自旋部分的代码来保证整个系统只有且唯一一个进程在执行临界区的代码。

  现在我们再考虑另一种情况,假如你用spin_lock来保护你对某一全局资源的访问,然后在执行临界区代码时,发生了外部中断,而在外部中断程序中也需要获得该全局资源的访问而调用spin_lock,那么由于中断程序是不能休眠和进行进程切换的,而且锁始终无法获得,那么便在该中断程序中产生了死锁,系统崩溃。

  所以为了避免上面的情况的出现,假如你要访问的资源有可能被外部中断所访问,那么便要使用下面的锁函数对

  void spin_lock_irq(spinlock_t *lock);

  void spin_unlock_irq(spinlock_t *lock);

该锁函数的实现只增加了一个步骤,便是禁止了外部中断,所以可以避免出现上述的死锁状况

还有一个函数对在此介绍下:

   void spin_lock_irqsave(spinlock_t *lock ,unsigned flags);

 void spin_lock_irqrestore(spinlock_t *lock,unsigned flags);

该函数对和上面唯一的区别就是在禁止了中断之后还保存了系统标志寄存器。

最后我们要记住的便是,使用自旋锁进入的临界区代码要尽可能的短,而且绝对不能休眠和调用可能会导致休眠的函数

 

  

posted @ 2013-03-19 18:45  一维  阅读(312)  评论(0编辑  收藏  举报