Linux中的信号量是一种睡眠锁。如果有一个任务试图获得一个不可用(已经被占用)的信号量时,信号量会将其推进一个等待队列,然后让其睡眠。这时处理器能重获自由,从而去执行其他代码。当持有的信号量可用(被释放后),处于等待队列中的那个任务将被唤醒,并将获得该信号量。
举个现实生活中的例子。当某个人到了门前,他抓取钥匙,然后进入房间。最大的差异在于当另一人到了门前,但无法得到钥匙时会发生什么情况。在这种情况下,这家伙不是在徘徊等待,而是把自己的名字写在一个列表中,然后打盹去了。当里面的人离开房间时,就在门口查看一下列表。如果列表上有名字,他就对第一个名字仔细检查,并在胸部给他一拳,叫醒他,让他进入房间。在这种方式中,钥匙(相当于信号量)继续确保一次只有一个人(相当于执行线程)进入房间(相当于临界区)。这就比自旋锁提供了更好的处理器利用率,因为没有把时间花费在忙等待上,但是信号量比自旋锁有更大的开销。
我么可以从信号量的睡眠特性得出一些有意思的结论:
- 由于争用信号量的进程在等待锁重新变为可用时会睡眠,所以信号量适用于锁会被长时间持有的情况。
- 相反,锁被短时间持有时,使用信号量就不太适宜了。因为睡眠,维护等待队列以及唤醒所花费的开销可能比锁被占用的全部时间还要长。
计数信号量和二值信号量
信号量一个有用的特性是它可以同时允许任意数量的锁持有者,而自旋锁在一个时刻最多允许一个任务持有它。信号量同时允许的持有者数量可以在声明信号量时指定。这个值称为使用者数量(usage count)或简单的叫做数量(count)。通常情况下,信号量和自旋锁一样,在一个时刻仅允许有一个锁持有者。这时计数等于1,这样的信号量被称为二值信号量或者称为互斥信号量。另一方面,初始化时也可以把数量设置为大于1的非0值。这种情况,信号量被称为计数信号量(counting semaphone),它允许在同一时刻至多有count个锁持有者。
摘自:《Linux内核设计与实现》
==========END==========
时间: 2024-10-22 13:01:08