一、什麼是信号量
1、概念
核心的信号量在概念和原理上與使用者态的信号量是一樣的,但是它不能在核心之外使用。
信号量又稱為信号燈(semaphore),本質上是一種睡眠鎖。如果有一個任務試圖獲得一個不可用(已經被占用)的信号量時,信号量會将其推進一個等待隊列,然後讓其睡眠。這時處理器能重獲自由,進而去執行其他代碼。當持有的信号量可用(被釋放後),處于等待隊列中的那個任務将被喚醒,并将獲得該信号量。
信号量一個有用的特性是它可以同時允許任意數量的鎖持有者,而自旋鎖和互斥鎖在一個時刻最多允許一個任務持有它。信号量同時允許的持有者數量可以在聲明信号量時指定。這個值稱為使用者數量(usage count)或簡單的叫做數量(count)。通常情況下,信号量和自旋鎖一樣,在一個時刻僅允許有一個鎖持有者。這時計數等于1,這樣的信号量被稱為二值信号量或者稱為互斥信号量。另一方面,初始化時也可以把數量設定為大于1的非0值。這種情況,信号量被稱為計數信号量(counting semaphore),它允許在同一時刻至多有count個鎖持有者。
2、資料結構
struct semaphore {
raw_spinlock_t lock;
unsigned int count;
struct list_head wait_list;
};
結構體成員說明:
count:相當于信号量的值,大于0,資源空閑;等于0,資源忙,但沒有程序等待這個保護的資源;小于0,資源不可用,并至少有一個程序等待資源。
wait:存放等待隊列連結清單的位址,目前等待資源的所有睡眠程序都會放在這個連結清單中。
sleepers:存放一個标志,表示是否有一些程序在信号量上睡眠
二、信号量的使用
1、初始化
void sema_init (struct semaphore *sem, int val);
void init_MUTEX (struct semaphore *sem); //将sem的值置為1,表示資源空閑
void init_MUTEX_LOCKED (struct semaphore *sem); //将sem的值置為0,表示資源忙
2、加鎖
void down(struct semaphore * sem); // 可引起睡眠
int down_interruptible(struct semaphore * sem); // down_interruptible能被信号打斷
int down_trylock(struct semaphore * sem); // 非阻塞函數,不會睡眠。無法鎖定資源則馬上傳回
3、解鎖
void up(struct semaphore * sem);
三、為什麼使用信号量
1、用于線程間的同步。
2、當同一時刻,有多個對象需要同時持有鎖的情況下,可以使用信号量。