1. 訊號量
1)訊號量(semaphore),也叫訊號燈。它是不同程序間或乙個給定程序內部不同執行緒間同步的機制。
2)二值訊號量:值為0或1。與互斥鎖類似,資源可用時值為1,不可用時值為0。
3)計數訊號量:值在0到n之間。同來統計資源,其值代表可用資源數。
4)等待操作是等待訊號量的值變為大於0,然後將其減一;而釋放操作則相反,用來喚醒等待資源的程序或者執行緒。
2. 訊號量程式設計函式
在linux系統中,使用訊號量通常需要建立訊號量、初始化訊號量、訊號量pv操作以及訊號量刪除四種操作。
1)建立訊號量
函式semget()
所需標頭檔案:#include
#include
#include
函式原型:int semget(key_t key, int nsems, intsem***)
函式引數:
key 訊號量的鍵值,其他程序通過該值訪問該訊號量,其中有個特殊值ipc_private,表示建立當前程序的私有訊號量
nsems 需要建立的訊號量數目,通常為1。若建立多個訊號量則稱為訊號量集
sem*** 同open()函式的第三個引數,為訊號量設定許可權,通常使用八進位制表示。
函式返回值:
成功:訊號量的識別符號(非負整數)
失敗:-1
2)初始化訊號量,函式semctl()用於對訊號量進行相應的控制,包括設定初始化值、獲取資訊、設定屬性、刪除訊號量(集)等操作
函式semctl()
標頭檔案:#include
#include
#include
函式原型:int semctl(int semid, int semnum, intcmd, union semun arg)
函式引數:
semid 訊號量識別符號(即semget()函式的返回值)
semnum 訊號量編號,通常存在多個訊號量時才會使用。通常取值為0,即第乙個訊號量。
cmd 需要對訊號量採取的操作。可取值有很多,常用的有:
ipc_stat 讀取訊息佇列的資料結構semid_ds並將其儲存在第四個引數arg結構變數的buf指定的位址中
ipc_setval 將訊號量值設定為arg中的val值
ipc_getval 獲取當前訊號量的值
ipc_rmid 從核心中刪除訊號量(集)
arg 是乙個union semun結構的共用體,常用型別如下:
union semun
int val; /* value for setval */
struct semid_ds *buf; /* buffer for ipc_stat,ipc_set */
unsigned short *array; /* array for getall, setall */
struct seminfo *__buf; /* buffer for ipc_info
(linux-specific) */
注意:某些系統內未給出union semun的定義,需要程式設計師自己定義該共用體。
struct semid_ds
uid_t sem_perm.uid; /* effective uid of owner*/
gid_t sem_perm.gid; /* effective gid of owner*/
函式返回值:成功:
ipc_stat、ipc_setval或ipc_rmid操作:0
ipc_getval操作:返回當前訊號量的值
失敗:-1
3)訊號量pv操作
函式semop()
標頭檔案:#include
#include
#include
函式原型:int semop(int semid, struct sembuf*sops, size_t nsops)
函式引數:
semid 訊號量識別符號(即semget()函式的返回值)
struct sembuf
unsigned short sem_num;//訊號量編號,若是單個訊號量則取值0
short sem_op;//取值-1為p操作,取值1為v操作
short sem_***;//通常取值sem_undo,表示程序結束後系統自動釋放該程序中未釋放的訊號量
nsops 需要操作的訊號量數目,通常取值1(乙個操作)
函式返回值:
成功:訊號量的識別符號
失敗:-1
示例:有兩個程序,程序a和程序b,這兩個程序通過共享記憶體通訊,程序a負責寫記憶體,程序b負責讀記憶體。要求程序a寫一次,然後b讀一次。這裡用兩個訊號量進行讀寫的同步。(在博文:ipc物件之共享記憶體中使用無名管道進行都寫得同步)。
方法一程式結構圖如下:
示例**:
@author: wanghao
@created time : wed 23 may 2018 07:37:06 pmpdt
@file name: sem_demo.c
@description:
#include
#include
#include
#include
#include
#include
/*the structure that stores the data*/
typedef structstorage;
void init(storage *s)
assert(s!= null);
/*create semaphore, return semaphore value*/
if((s->semid= semget(ipc_private,2,ipc_creat|ipc_excl|0777)) <0);
un.array= array;
/*set all values in the semaphore*/
if(semctl(s->semid,0,setall,un)<0)};
/*set semaphore 1 to p operation*/
struct sembuf ops_p[1] = };
/*set semaphore 1 to p operation*/
if(semop(s->semid,ops_p,1)<0)};
/*set semaphore 0 to v operation*/
struct sembuf ops_v[1] = };
/*set semaphore 0 to p operation*/
if(semop(s->semid,ops_p,1)<0)else if(pid > 0)elsestorage;
void init(storage *s)
assert(s!= null);
/*createsemaphore, return semaphore value*/
if((s->semid= semget(ipc_private,2,ipc_creat|ipc_excl|0777)) <0);
un.array= array;
/*setall values in the semaphore*/
if(semctl(s->semid,0,setall,un)<0)};
/*set semaphore 1 to p operation*/
struct sembuf ops_p[1] = };
s->val = val;
printf("%d write %d\n",getpid(),val);
/*set semaphore 1 to v operation*/
if(semop(s->semid,ops_v,1) <0)
/*set semaphore 1 to p operation*/
if(semop(s->semid,ops_p,1)<0)
void read(storage *s)
assert(s!= null);
/*setsemaphore 0 to p operation*/
structsembuf ops_p[1] = };
/*setsemaphore 0 to v operation*/
structsembuf ops_v[1] = };
/*setsemaphore 0 to p operation*/
if(semop(s->semid,ops_p,1)<0)elseif(pid > 0)else{
inti = 1;
for(;i<=100;i++){
read(s);
/*unlocka shared memory map*/
shmdt(s);
exit(0);
IPC之 訊號量集 多個訊號量
如果兩個程序不僅需要同步,還要保證先後執行順序,就要用兩個訊號量 互斥鎖 來解決 柵欄模型 實現以下框架中的四個子程序 所有程序做完任務後 在一起執行下一次 include include include include include include include include define ...
IPC 訊號量集
ipc通訊機制 訊號量集 1.int semget key t key,int nsems,int sem 第乙個引數是由ftok 獲取的key 第二個引數是要建立的訊號量的個數,如果是0表示獲取訊號量集id 第三個引數是ipc creat,建立訊號量集id。返回乙個訊號量集的id semid.se...
Linux學習筆記之IPC 物件之訊號量集
目的 配合共享記憶體完成程序間通訊 使用框架 key 申請訊號量集 pv操作 解除安裝刪除訊號量集 semget semop semctl 1 申請訊號量 include int semget key t key,int nsems,int sem 功能 該函式可以使用特定的key向核心提出訊號量集...