訊號量(semaphore)與已經介紹過的 ipc 結構不同,它是乙個計數器。訊號量用於實現程序間的互斥與同步,而不是用於儲存程序間通訊資料。
**1、訊號量用於程序間同步,若要在程序間傳遞資料需要結合共享記憶體。
2、訊號量基於作業系統的 pv 操作,程式對訊號量的操作都是原子操作。
3、每次對訊號量的 pv 操作不僅限於對訊號量值加 1 或減 1,而且可以加減任意正整數。
4、支援訊號量組。
例子:就像乙個房間,訊號量相當於開門的鑰匙,房間相當於連線資源(一次僅允許乙個程序使用的資源;如:a程序正在使用臨界資源,b程序就無法使用,等a程序完成後才行。)
在linux中有許多的訊號量集,
p操作:拿鎖;v操作:放回鎖;
****
最簡單的訊號量是只能取 0 和 1 的變數,這也是訊號量最常見的一種形式,叫做二值訊號量(binary semaphore)。而可以取多個正整數的訊號量被稱為通用訊號量。
linux 下的訊號量函式都是在通用的訊號量陣列上進行操作,而不是在乙個單一的二值訊號量上進行操作。
1 #include
2// 建立或獲取乙個訊號量組:若成功返回訊號量集id,失敗返回-1
3int
semget
(key_t key,
int num_sems,
int sem_flags);4
// 對訊號量組進行操作,改變訊號量的值:成功返回0,失敗返回-1
5int
semop
(int semid,
struct sembuf semoparray[
], size_t numops);6
// 控制訊號量的相關資訊
7int
semctl
(int semid,
int sem_num,
int cmd,..
.);
semget建立新的訊號量集合時,必須指定集合中訊號量的個數(即num_sems),通常為1; 如果是引用乙個現有的集合,則將num_sems指定為 0 。
所需標頭檔案:
#include
#include
#include
函式返回值:成功:返回訊號量集的識別符號;出錯:-1,錯誤原因存於error中
key:0(ipc_private):會建立新訊號量集物件,key大於0的32位整數:視引數sem***來確定操作,通常要求此值**於ftok返回的ipc鍵值
nsems:建立訊號量集中訊號量的個數,該引數只在建立訊號量集時有效
msg***:
0:取訊號量集識別符號,若不存在則函式會報錯
ipc_creat:當sem***&ipc_creat為真時,如果核心中不存在鍵值與key相等的訊號量集,則新建乙個訊號量集;如果存在這樣的訊號量集,返回此訊號量集的識別符號
ipc_creat|ipc_excl:如果核心中不存在鍵值與key相等的訊號量集,則新建乙個訊息佇列;如果存在這樣的訊號量集則報錯
在semop函式中,sembuf結構的定義如下:
1
struct sembuf
2
sem_op 是一次操作中的訊號量的改變量:
若sem_op > 0,表示程序釋放相應的資源數,將 sem_op 的值加到訊號量的值上。如果有程序正在休眠等待此訊號量,則換行它們。
若sem_op < 0,請求 sem_op 的絕對值的資源。
如果相應的資源數可以滿足請求,則將該訊號量的值減去sem_op的絕對值,函式成功返回。
當相應的資源數不能滿足請求時,這個操作與sem_***有關。
sem_*** 指定ipc_nowait,則semop函式出錯返回eagain。
sem_*** 沒有指定ipc_nowait,則將該訊號量的semncnt值加1,然後程序掛起直到下述情況發生:
1、當相應的資源數可以滿足請求,此訊號量的semncnt值減1,該訊號量的值減去sem_op的絕對值。成功返回;
2、此訊號量被刪除,函式smeop出錯返回eidrm;
3、程序捕捉到訊號,並從訊號處理函式返回,此情況下將此訊號量的semncnt值減1,函式semop出錯返回eintr
成功:返回訊號量集的識別符號;出錯:-1,錯誤原因存於error中。
在semctl函式中的命令有多種,這裡就說兩個常用的:
1、setval:用於初始化訊號量為乙個已知的值。所需要的值作為聯合semun的val成員來傳遞。在訊號量第一次使用之前需要設定訊號量。
2、ipc_rmid:刪除乙個訊號量集合。如果不刪除訊號量,它將繼續在系統中存在,即使程式已經退出,它可能在你下次執行此程式時引發問題,而且訊號量是一種有限的資源。
訊號量(父子之間通訊):
#include
"stdio.h"
#include
#include
#include
// int semget(key_t key, int num_sems, int sem_flags);
// // 對訊號量組進行操作,改變訊號量的值:成功返回0,失敗返回-1
// int semop(int semid, struct sembuf semoparray, size_t numops);
// // 控制訊號量的相關資訊
// int semctl(int semid, int sem_num, int cmd, ...);
union semun
;void
pgetkey
(int id)
void
vputbackkey
(int id)
intmain()
else
if(pid==0)
else
}
共享記憶體與訊號量:
1 #include
2 #include
3 #include45
// 聯合體,用於semctl初始化
6union semun
7;1213
// 初始化訊號量
14int
init_sem
(int sem_id,
int value)
1523
return0;
24}2526
// p操作:
27// 若訊號量值為1,獲取資源並將訊號量值-1
28// 若訊號量值為0,程序掛起等待
29int
sem_p
(int sem_id)
3041
return0;
42}4344
// v操作:
45// 釋放資源並將訊號量值+1
46// 如果有程序正在掛起等待,則喚醒它們
47int
sem_v
(int sem_id)
4859
return0;
60}6162
// 刪除訊號量集
63int
del_sem
(int sem_id)
6471
return0;
72}7374
75int
main()
7687
88// 建立訊號量集,其中只有乙個訊號量
89if
((sem_id =
semget
(key,
1, ipc_creat|
0666))
==-1)
9094
95// 初始化:初值設為0資源被占用
96init_sem
(sem_id,0)
;9798if
((pid =
fork()
)==-1
)99perror
("fork error");
100else
if(pid ==0)
/*子程序*/
101106
else
/*父程序*/
107113
return0;
114}
訊號量 二值訊號量
訊號量 二值訊號量 訊號量是作業系統的重要部分,訊號量一般用來進行資源管理和任務同步。freertos中訊號量分為二值訊號量 互斥訊號量 計數訊號量和遞迴互斥訊號量,應用場景各不同。二值訊號量通常用於互斥訪問或同步,二值訊號量和互斥訊號量非常相似,但互斥訊號量有優先順序,二值訊號量沒有。因此二值訊號...
python訊號量 Python訊號量
python訊號量教程 訊號量是由作業系統管理的一種抽象資料型別,用於在多執行緒中同步對共享資源的使用。本質上說,訊號量是乙個內部資料,用於標明當前的共享資源可以有多少併發讀取。也可以簡單的理解為,訊號量是多把鎖,同時允許多個執行緒來更改資料,而 python訊號量與互斥鎖的關係 訊號量的乙個特殊用...
訊號 訊號量
訊號是由 系統或者程序傳送給目標程序的資訊,以通知目標程序某個狀態的改變或系統異常。linux訊號可以由如下條件產生 1 對於前台程序,使用者可以通過輸入特殊的終端字元來給它傳送訊號。比如輸入ctrl c通常或給程序傳送乙個中斷訊號 2 系統異常。比如浮點異常和非法記憶體段訪問。3 系統狀態變化 4...