CODE:spin_lock_bh(lock)
该宏在得到自旋锁的同时失效本地软中断。
CODE:spin_unlock(lock)
该宏释放自旋锁lock,它与spin_trylock或spin_lock配对使用。假如spin_trylock返回假,表明没有获得自旋锁,因此不必使用spin_unlock释放。
CODE:spin_unlock_irqrestore(lock, flags)
该宏释放自旋锁lock的同时,也恢复标志寄存器的值为变量flags保存的值。它与spin_lock_irqsave配对使用。
CODE:spin_unlock_irq(lock)
该宏释放自旋锁lock的同时,并激活本地中断。它与spin_lock_irq配对应用。
CODE:spin_unlock_bh(lock)
该宏释放自旋锁lock的同时,也使能本地的软中断。它与spin_lock_bh配对使用。
CODE:spin_trylock_irqsave(lock, flags)
该宏假如获得自旋锁lock,它也将保存标志寄存器的值到变量flags中,并且失效本地中断,假如没有获得锁,它什么也不做。
因此假如能够立即获得锁,它等同于spin_lock_irqsave,假如不能获得锁,它等同于spin_trylock。假如该宏获得自旋锁lock,那需要使用spin_unlock_irqrestore来释放。
CODE:spin_trylock_irq(lock)
该宏类似于spin_trylock_irqsave,只是该宏不保存标志寄存器。假如该宏获得自旋锁lock,需要使用spin_unlock_irq来释放。
CODE:spin_trylock_bh(lock)
该宏假如获得了自旋锁,它也将失效本地软中断。假如得不到锁,它什么也不做。因此,假如得到了锁,它等同于spin_lock_bh,假如得不到锁,它等同于spin_trylock。假如该宏得到了自旋锁,需要使用spin_unlock_bh来释放。
CODE:spin_can_lock(lock)
该宏用于判定自旋锁lock是否能够被锁,它实际是spin_is_locked取反。假如lock没有被锁,它返回真,否则,返回假。该宏在2.6.11中第一次被定义,在先前的内核中并没有该宏。
自旋锁的基本使用如下:
CODE:spinlock_t myr_lock = SPIN_LOCK_UNLOCKED;spin_lock(&myr_lock);/*临界区*/spin_unlock(&myr_lock);
因为自旋锁在同一时刻至多被一个执行线程持有,所以一个时刻只能有一个线程位于临界区,这就为多处理器提供了防止并发访问所需的保护机制,但是在单处理器上,编译的时候不会加入自旋锁。它仅仅被当作一个设置内核抢占机制是否被启用的开关。注重,Linux内核实现的自旋锁是不可递归的,这一点不同于自旋锁在其他操作系统中的实现,假如你想得到一个你正持有的锁,你必须自旋,等待你自己释放这个锁,但是你处于自旋忙等待中,所以永远没有机会释放锁,于是你就被自己锁死了,一定要注重!
自旋锁可以用在中断处理程序中,但是在使用时一定要在获取锁之前,首先禁止本地中断(当前处理器上的中断),否则中断处理程序就可能打断正持有锁的内核代码,有可能会试图支争用这个已经被持有的自旋锁。这样一来,中断处理程序就会自旋,等待该锁重新可用,但是锁的持有者在这个中断处理程序执行完毕之前不可能运行,这就会造成双重请求死锁。
自旋锁与下半部:由于下半部(中断程序下半部)可以抢占进程上下文中的代码,所以当下半部和进程上下文共享数据时,必须对进程上下文中的共享数据进行保护,所以需要加锁的同时还要禁止下半部执行。同样,由于中断处理程序可以抢占下半部,所以假如中断处理程序和下半部共享数据,那么就必须在获取恰当的锁的同时还要禁止中断。对于软中断,无论是否同种类型,假如数据被软中断共享,那么它必须得到锁的保护,因为同种类型的两个软中断也可以同进运行在一个系统的多个处理器上。但是,同一个处理器上的一个软中断绝不会抢占另一个软中断,因此,根本不需要禁止下半部。
评论加载中…
![]() |