linux2 6核心訊號量學習

2021-06-22 09:09:46 字數 3115 閱讀 3606

訊號量(semaphore

)是用於保護臨界區的一種常用方法。只有得到訊號量的程序才能執行臨界區**,而沒有得到訊號量的程序進入休眠等待狀態。

linux

系統中與訊號量相關的操作主要有如下4種。

1 定義訊號量

下面**定義名為

sem的訊號量。

struct semaphore sem;

struct semaohore

結構體在核心中定義如下:

在/include/linux/semaphore.h

目錄下:

struct semaphore;

2初始化訊號量

在/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)

初始化訊號量時,此訊號量只有先被釋放才可以獲取。

3獲取訊號量

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

240

241 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);

0 給主人留下些什麼吧!~~

Linux核心 訊號量

linux訊號量是一種睡眠鎖。如果有乙個任務試圖獲得乙個不可用 已經被占用 的訊號量時,訊號量會將其推入乙個等待佇列,然後讓其睡眠。這時處理器可以重獲自由,從而去執行其他 當持有的訊號量可用 被釋放 後,處於等待佇列中的那個任務被喚醒,並獲得該訊號量。舉例說明 當某個人來到門前,他抓取鑰匙,進入房間...

核心 訊號量

核心訊號量和自旋鎖類似,作用也是保護資料。不同之處是,程序獲取核心訊號量嘚瑟時候,如果不能獲取,則程序進入睡眠狀態。down dev sem up dev sem 核心訊號量和自旋鎖的不同 1 核心訊號量 不能用在 中斷處理函式 和 tasklet 等不可睡眠的場景 2 深層次的原因 linux核心...

linux核心同步 4 訊號量

任務獲取乙個已經被占用的訊號量,訊號量將其推進乙個等待佇列,然後讓其睡眠,cpu 去執行其他 當持有訊號量的程序將訊號釋放,處於等待佇列彙總的任務被喚醒,並獲取訊號量。訊號量會引起睡眠,所以在中斷上下文中不能使用訊號量。一般在程序上下文中使用。乙個程序占用訊號量的同時不能同時占用自旋鎖,因為占用訊號...