linux核心同步 4 訊號量

2021-06-26 21:41:48 字數 2681 閱讀 5844

任務獲取乙個已經被占用的訊號量,訊號量將其推進乙個等待佇列,然後讓其睡眠,cpu

去執行其他**。當持有訊號量的程序將訊號釋放,處於等待佇列彙總的任務被喚醒,並獲取訊號量。

訊號量會引起睡眠,所以在中斷上下文中不能使用訊號量。一般在程序上下文中使用。

乙個程序占用訊號量的同時不能同時占用自旋鎖,因為占用訊號量會引起睡眠,而占用自旋鎖是不允許睡眠的。

訊號量不同於自旋鎖,不會禁止核心搶占,所以持有訊號量的**可以被搶占。

訊號量的操作:

down():訊號量計數器減

1,若減一後大於等於

0,將獲得鎖並進入臨界區;若小於

0,任務將會放入等待佇列,不進入睡眠。

up():釋放訊號量,計數器加

1。若等待佇列不為空,那麼佇列中的任務在被喚醒的同時會獲 得該訊號量。

訊號量的定義:

[cpp]view plain

copy

struct

semaphore ;  

訊號量的使用:

[cpp]view plain

copy

static

declare_mutex(mr_sem);  

if(down_interruptible(&mr_sem))  

/*訊號已經接收,並進入到臨界區*/

/*釋放給定的訊號量*/

up(&mr_sem);  

own和

down_interruptible

函式的區別在於

down

將程序的狀態設定為不可中斷的,其他的操作基本相同。

訊號量的實現:

[cpp]view plain

copy

static

inline

int__sched __down_common(

struct

semaphore *sem, 

long

state,  

long

timeout)  

timed_out:  

list_del(&waiter.list);  

return

-etime;  

interrupted:  

list_del(&waiter.list);  

return

-eintr;  

}  

該函式首先會通過semaphore_waiter waiter變數將當前程序放到訊號量

sem的成員變數

wait_list

所管理的佇列中,接著在乙個

for迴圈中把當前程序的狀態設定為

task_interruptible

,再呼叫

schedule_timeout

時當前程序進入到睡眠狀態。函式將停留在

schedule_timeout

呼叫上,知道再次被排程執行。當該程序再一次被排程執行時,

schedule_timeout

開始返回,接下來根據程序被再次排程的原因進行處理:如果

waiter.up不為0

,說明程序在訊號量

sem的

wait_list

佇列中被該訊號量的

up操作所喚醒,程序可以獲得訊號量,並返回

0.如果程序是因為被使用者空間傳送的訊號所中斷或者是超時所引起的喚醒,則返回相應的錯誤**。因此對

down_interruptible

的呼叫總是應該堅持檢查其返回值,以確認函式是已經獲得了訊號量還是因為操作被中斷因而需要特別處理。通常驅動程式對返回的非

0值要做的工作是返回

-erestartsys。

up操作:

[cpp]view plain

copy

void

up(struct

semaphore *sem)    

[cpp]view plain

copy

static

noinline

void

__sched __up(

struct

semaphore *sem)  

"font-family: arial, helvetica, sans-serif;"

>    

__up函式首先會用 list_first_entry獲取

wait_list

上鍊表上的第乙個

waiter

節點,然後將其從

sem->wait_list

上刪除。

waiter->up=1

最後呼叫

wait_up_process

來喚醒waiter

節點對應的程序,這樣程序將會從之前

down_interruptible

呼叫中的

timeout = schedule_timeout(timeout)

醒來,waiter->up=1

,down_interruptible返回0

,程序獲得訊號量,該訊號量上

sem->wait_list

等待列表上的其它程序會繼續等待直到有程序釋放乙個訊號量或者被使用者空間中斷掉。

Linux核心 訊號量

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

同步 訊號量

include stdafx.h include includeusing namespace std int number 1 定義全域性變數 handle hsemaphore 定義訊號量控制代碼 unsigned long stdcall threadproc1 void lp long co...

linux核心同步機制之訊號量

定義 如果有乙個任務試圖獲得已經被占用的訊號量時,訊號量會將其推進乙個等待佇列,使其睡眠,當持有訊號量的程序將訊號量釋放以後,再喚醒該任務,並獲得該訊號量。標頭檔案head.h ifndef head h define head h include include include include e...