首先看看訊號量的相關資料結構:
<
include
/linux/semaphore.h>
struct semaphore
;
訊號量的初始化:
<
include
/linux/semaphore.h>
#
define declare_mutex(name) \
struct semaphore name = __semaphore_initializer(name, 1)
#define __semaphore_initializer(name, n) \
也可以用以下方法來初始化訊號量:
<
include
/linux/semaphore.h>
static
inline
void sema_init(
struct semaphore *sem,
int val)
#define init_mutex(sem) sema_init(sem, 1)
#define init_mutex_locked(sem) sema_init(sem, 0)
pv操作:
p操作
void up(
struct semaphore *sem)
static noinline void __sched __up(
struct semaphore *sem)
此函式從等待列表中移出最前面的那個程序,然後喚醒它
struct semaphore_waiter
;
這個結構主要就是用來輔助把程序放到訊號量的等待佇列,後面的v操作會再介紹它
v操作:
void down(
struct semaphore *sem)
如果count是<=0的,那麼呼叫__down()來把程序放進等待佇列裡,現在看看__down()是怎麼實現的
static noinline void __sched __down(
struct semaphore *sem)
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結構,
struct semaphore_waiter
;
然後將這個結構加入到sem訊號量的等待鍊錶sem->wait_list中,接著將當前程序task填入waiter.task中,
然後在乙個迴圈中進行程序排程schedule_timeout,每進行一次排程,timeout會減小
如果當前程序task的狀態位就緒,則跳轉到interrupt,從訊號量列表sem-wait_list中刪除這個任務對應的節點
如果遇到意外的訊號或者等待時間到,從訊號量列表sem-wait_list中刪除這個任務對應的節點,返回相應的錯誤號
核心還提供了其他幾種v操作:
static noinline int __down_interruptible(struct semaphore *sem);
static noinline int __down_killable(struct semaphore *sem);
static noinline int __down_timeout(struct semaphore *sem, long jiffies);
這裡就不一一介紹了
讀者也可以參考這篇文章
核心同步機制-訊號量
構建linux2 6 32核心樹
系統環境 rhel6 核心版本 注意 下乙個和你當前執行版本一樣的核心,這裡可以看到我當前執行的核心版本是2.6.32 279.el6.x86 64,好,那我就下乙個2.6.32.x的版本 必須有和當前執行的版本有同樣的版本號,否則在載入模組時候insmod error inserting o l ...
Linux核心 訊號量
linux訊號量是一種睡眠鎖。如果有乙個任務試圖獲得乙個不可用 已經被占用 的訊號量時,訊號量會將其推入乙個等待佇列,然後讓其睡眠。這時處理器可以重獲自由,從而去執行其他 當持有的訊號量可用 被釋放 後,處於等待佇列中的那個任務被喚醒,並獲得該訊號量。舉例說明 當某個人來到門前,他抓取鑰匙,進入房間...
核心 訊號量
核心訊號量和自旋鎖類似,作用也是保護資料。不同之處是,程序獲取核心訊號量嘚瑟時候,如果不能獲取,則程序進入睡眠狀態。down dev sem up dev sem 核心訊號量和自旋鎖的不同 1 核心訊號量 不能用在 中斷處理函式 和 tasklet 等不可睡眠的場景 2 深層次的原因 linux核心...