现在的位置: 首页 > 综合 > 正文

(三)自旋锁_zzhere2007

2018年02月07日 ⁄ 综合 ⁄ 共 1875字 ⁄ 字号 评论关闭

1  自旋锁简介   
     自旋锁它是为为实现保护共享资源而提出一种锁机制。其实,自旋锁与互斥锁比较类似,它们都是为了解决对某项资源的互斥使用。无论是互斥锁,还是自旋锁,在任何时刻,最多只能有一个保持者,也就说,在任何时刻最多只能有一个执行单元获得锁。但是两者在调度机制上略有不同。对于互斥锁,如果资源已经被占用,资源申请者只能进入睡眠状态。但是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,"自旋"一词就是因此而得名。

2  自旋锁适用情况

    自旋锁比较适用于锁使用者保持锁时间比较短的情况。正是由于自旋锁使用者一般保持锁时间非常短,因此选择自旋而不是睡眠是非常必要的,自旋锁的效率远高于互斥锁。信号量和读写信号量适合于保持时间较长的情况,它们会导致调用者睡眠,因此只能在进程上下文使用,而自旋锁适合于保持时间非常短的情况,它可以在任何上下文使用。如果被保护的共享资源只在进程上下文访问,使用信号量保护该共享资源非常合适,如果对共享资源的访问时间非常短,自旋锁也可以。但是如果被保护的共享资源需要在中断上下文访问(包括底半部即中断处理句柄和顶半部即软中断),就必须使用自旋锁。自旋锁保持期间是抢占失效的,而信号量和读写信号量保持期间是可以被抢占的。自旋锁只有在内核可抢占或SMP(多处理器)的情况下才真正需要,在单CPU且不可抢占的内核下,自旋锁的所有操作都是空操作。另外格外注意一点:自旋锁不能递归使用。

 3 自旋锁 使用

自旋锁定义:  linux/Spinlock.h

在Linux中,每个自旋锁都用spinlock_t结构表示:
typedef struct { 
               raw_spinlock_t raw_lock; 
           #if defined(CONFIG_PREEMPT) && defined(CONFIG_SMP) 
               unsigned int break_lock; 
           #endif 
           #ifdef CONFIG_DEBUG_SPINLOCK 
               unsigned int magic, 
               owner_cpu; 
               void *owner; 
           #endif 
           #ifdef CONFIG_DEBUG_LOCK_ALLOC 
               struct lockdep_map dep_map; 
           #endif
} spinlock_t;
typedef  struct{
                 volatile unsigned int slock;
} raw_spinlock_t;
定义和初始化
spinlock_t my_lock = SPIN_LOCK_UNLOCKED; 
void spin_lock_init(spinlock_t *lock); 
自旋锁操作:
//加锁一个自旋锁函数
void spin_lock(spinlock_t *lock);                              //获取指定的自旋锁
void spin_lock_irq(spinlock_t *lock);                          //禁止本地中断获取指定的锁
void spin_lock_irqsave(spinlock_t *lock, unsigned long flags); //保存本地中断的状态,禁止本地中断,并获取指定的锁
void spin_lock_bh(spinlock_t *lock)                            //安全地避免死锁, 而仍然允许硬件中断被服务


//释放一个自旋锁函数
void spin_unlock(spinlock_t *lock);                                 //释放指定的锁
void spin_unlock_irq(spinlock_t *lock);                             //释放指定的锁,并激活本地中断
void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags); //释放指定的锁,并让本地中断恢复到以前的状态
void spin_unlock_bh(spinlock_t *lock);                              //对应于spin_lock_bh

//非阻塞锁
int spin_trylock(spinlock_t *lock);                  //试图获得某个特定的自旋锁,如果该锁已经被争用,该方法会立刻返回一个非0值,
                                                     //而不会自旋等待锁被释放,如果成果获得了这个锁,那么就返回0.
                                                     //而不会自旋等待锁被释放,如果成果获得了这个锁,那么就返回0.
int spin_trylock_bh(spinlock_t *lock);                           
//这些函数成功时返回非零( 获得了锁 ), 否则 0. 没有"try"版本来禁止中断.

//其他
int spin_is_locked(spinlock_t *lock);      //和try_lock()差不多,如果自旋锁被置为1(未锁),返回0;否则,返回1
zz总结

抱歉!评论已关闭.