訊號量(semaphore)是用於保護臨界區的一種常用方法。只有得到訊號量的程序才能執行臨界區**,而沒有得到訊號量的程序進入休眠等待狀態。
linux系統中與訊號量相關的操作主要有如下4種。
下面**定義名為sem的訊號量。
struct semaphore sem;
struct semaohore結構體在核心中定義如下:
在/include/linux/semaphore.h目錄下:
struct semaphore;
在/include/linux/semaphore.h目錄下,void sema_init(struct semaphore*
sem, int val) 函式用於初始化訊號量,並設定訊號量sem的值為val。儘管訊號量可以被初始化為大於1的值從而成為乙個計數訊號量,但是它通常不被這樣使用。
核心定義了兩個巨集來把sem的值設定為1或者0。
#define init_mutex(sem) sema_init(sem, 1)
#define init_mutex_locked(sem) sema_init(sem, 0)
使用init_mutex(sem) 初始化訊號量時,表示訊號量最初是可以被獲取的。而使用init_mutex_locked(sem) 初始化訊號量時,此訊號量只有先被釋放才可以獲取。
void down(struct semaphore *sem);
該函式用於獲取訊號量sem,它會導致睡眠,因此不能在中斷上下文使用。
在核心裡該函式的源**如下:
在kernel/semaphore.c檔案裡:
53 void down(struct semaphore *sem)
54 這裡重點看58行:if (likely(sem->count > 0)),這句話表示當獲取訊號量成功時,就執行sem->count—; 即對訊號量的值減一。else表示獲取訊號量失敗,此時呼叫__down函式進入睡眠狀態,並將此程序插入到等待佇列尾部。
核心定義了訊號量的等待佇列結構體:
193 struct semaphore_waiter ;
此結構體是乙個雙向迴圈鍊錶。
int down_interruptible(struct semaphore *sem);
該函式功能與down()類似,不同之處是,down()在獲取訊號量失敗進入睡眠狀態時的程序是不能被打斷的,而down_interruptible()在進入睡眠狀態時的程序能被訊號打斷,訊號也會導致函式返回。下面我們也來看一看這個函式的原始碼:
在kernel/semaphore.c檔案裡:
75 int down_interruptible(struct semaphore *sem)
76 這裡我們可以看到,當獲取訊號量成功時,返回0,而獲取訊號量失敗時,返回乙個非0的值。在使用down_interruptible()函式獲取訊號量時,對返回值一般會進行檢查,如果非0,通常立即返回-erestartsys。如:
if ( down_interruptible(&sem) )
return -erestartsys;
這裡還有乙個問題:在獲取訊號量失敗後,為什麼down不能被中斷,而down_interruptible卻可以被中斷呢?我們從down和down_interruptible的源**可以得知,在獲取訊號量失敗後,down函式執行了__down函式,而down_interruptible函式執行了__down_interruptible。那麼讓我們來看一下這兩個函式的原始碼:
在kernel/semaphore.c檔案裡:
236 static noinline void __sched __down(struct semaphore *sem)
237
240241 static noinline int __sched __down_interruptible(struct semaphore *sem)
242
在__down函式裡,是把程序的狀態設定為task_uninterruptible ,即不可中斷狀態。
而在__down_interruptible裡,是把程序的狀態設定為task_interruptible ,即可中斷狀態。這就解釋了以上提出的問題。
4釋放訊號量
void up(struct semaphore *sem);
該函式用於釋放訊號量sem,喚醒等待者。
它的源**如下:
178 void up(struct semaphore *sem)
179 ,
};int thread_one(void *p);
int thread_two(void *p);
int thread_one(void *p)
return 0;
}int thread_two(void *p)
return 0;
}static int lan_init(void)
static void lan_exit(void)
module_init(lan_init);
module_exit(lan_exit);
臨界資源 互斥訪問 核心中的up和down函式
程序同步和互斥概念,臨界資源
制約關係的型別 根據共享資源性質的不同,可分為 同步 指兩個或兩個以上的程序由於某種時序上的限制而形成的相互合作的制約關係。直接制約關係 互斥 指兩個或兩個以上的程序由於競爭資源而形成的制約關係。間接制約關係 下列活動分別屬於哪種制約關係?同步 直接制約 互斥 間接制約 程序 程序 程序 資源 程序...
核心中的競爭狀態和互斥(簡述)
1 競爭狀態 簡稱竟態 2 臨界段 某一段 該 有可能造成併發,因此應該新增鎖。這段 應該盡可能地短 互斥鎖 死鎖 由於互斥鎖使用不對,導致的後果 3 同步與併發 多cpu 單cpu下 多工 中斷 1 原子操作 automic t,即不可分割的操作 以前認為原子不可以分割 2 訊號量 互斥鎖 3 自...
程序同步的基本概念 臨界資源 同步和互斥
在多道程式環境下,程序是併發執行的,不同程序之間存在著不同的相互制約關係。為了協調程序之間的相互制約關係,引入了程序同步的概念。雖然多個程序可以共享系統中的各種資源,但其中許多資源一次只能為乙個程序所使用,我們把一次僅允許乙個程序使用的資源稱為臨界資源。許多物理裝置都屬於臨界資源,如印表機等。此外,...