内核信号量类似于自旋锁,当锁关闭时,它不允许内核控制路径继续执行。与自旋锁不同的是,当内核控制路径试图获取内核信号量所保护的忙资源时,相应的进程被挂起,进而会导致进程切换;而自旋锁不会导致进程切换。因此,只有可以睡眠的函数才能获取内核信号量;中断处理程序和可延迟函数都不能使用内核信号量。
内核信号量结构如下:
/**
* 内核信号量结构
*/
struct semaphore {
/**
* 如果该值大于0,表示资源是空闲的。如果等于0,表示信号量是忙的,但是没有进程在等待这个资源。
* 如果count为负,表示资源忙,并且至少有一个进程在等待。
* 但是请注意,负值并不代表等待的进程数量。
*/
atomic_t count;
/**
* 存放一个标志,表示是否有一些进程在信号量上睡眠。
* 如果没有进程在信号量等待队列上睡眠时,sleeper通常为0,否则为1(这点很重要,见下面的down函数)
*/
int sleepers;
/**
* 存放等待队列链表的地址。当前等待资源的所有睡眠进程都放在这个链表中。
* 如果count>=0,那么这个链表就应该是空的。
*/
wait_queue_head_t wait;
};
释放信号量
当进程希望释放内核信号量锁时,就调用up()函数,如下:
static inline void up(struct semaphore * sem)
{
__asm__ __volatile__(
"# atomic up operation\n\t"
/**
* 首先增加count的值
*/
LOCK